logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

AVR dziwne liczby, mnożenie

ginar 17 Lis 2008 10:31 2328 8
  • #1 5749001
    ginar
    Poziom 21  
    Witam
    Od dłuższego czasu nie mogę dojść co jest nie tak:
    set_Freq[] - typu int
    set_Freq[x]- przyjmuje cyfry od 0..9
    unsigned long int SET

    zamienia wprowadzone cyfry na liczbę
    kawałek kodu:
    
        SET =set_Freq[0]+10*set_Freq[1]+100*set_Freq[2]+1000*set_Freq[3]+10000*set_Freq[4]+100000*set_Freq[5]+1000000*set_Freq[6];
    //poniżej to tylko wyswietlenie     
    Command_LCD(2 ,86);
        dtostrf(SET,1,0,table_y);
     WriteText_LCD(table_y);
    while(1){};
    

    w takiej formie zmienna SET zawsze ma błąd na 5 pozycji. jesli próbuje sie wpisać na tą pozycję cyfrę >3. Pozostałe pozycje/wagi (wyzsze lub niższe są ok).

    próbowałem również ręcznie w programie wpisać:
    np.
    
    SET =60000;
    ....
        

    i to jest ok. ale już
    
    SET =10000*6;
    ....
        

    daje dziwną liczbę 4294961929

    dla SET =10000*4;
    4294941425
    dla SET =10000*5;
    42949514378

    używam bibliotek:

    #include <avr/io.h>
    #include <avr/delay.h>
    #include <Function_AD9833.c> //dołączana biblioteka obsługi AD9833 z katalogu
    #include <LCD_HD44780.c> //dołączana biblioteka obsługi LCD z katalogu
    #include <stdio.h>
    #include <inttypes.h>
    #include <avr/interrupt.h> //obsługa przerwań
    #include <avr/signal.h>
  • #2 5749032
    szelus
    Poziom 34  
    Zakresy wartości. Zmień 10000 na 10000UL.

    P.S. Po co konwerujesz SET na zmienny przecinek przed konwersją na string? Nie lepiej użyć ltoa()?
  • #3 5749279
    zumek
    Poziom 39  
    A po jakie licho, tworzyć takiego gigantycznego stwora :?:
     SET=set_Freq[0]+10*set_Freq[1]+100*set_Freq[2]+1000*set_Freq[3]+10000*set_Freq[4]+100000*set_Freq[5]+1000000*set_Freq[6];
    //poniżej to tylko wyswietlenie

    Ani to "ładne", ani "pamięciooszczędne" :-P
    Prosta pętla, załatwi to bezbłędnie i oszczędnie:
    
    	SET=0;
    	for(i=0;i<x;i++) 
    	{
    		SET=SET*10+set_Freq[i];
    	}
    

    Poza tym:
    
    set_Freq[] - typu int
    set_Freq[x]- przyjmuje cyfry od 0..9
    unsigned long int SET
     

    Po co sys_Freq[] jest typu int :?: Marnotrawstwo pamięci danych.
    szelus napisał:
    P.S. Po co konwerujesz SET na zmienny przecinek przed konwersją na string? Nie lepiej użyć ltoa()?

    Autor tematu ma chyba kłopoty, z rozróżnianiem typu danych, bo do funkcji dtostrf (double __val, signed char __width, unsigned char __prec, char *__s),
    zamiast double podstawia unsigned long, a potem sie dziwi , że widzi cuda na LCD. O ostrzeżeniach kompilatora , wogóle nie wspomina - dziwne :|

    Piotrek
  • #4 5756568
    ginar
    Poziom 21  
    Po zamianie 10000 na 10000ul , działa ok.
    Mógłby ktoś objaśnić podać lika , dlaczego tak się działo?

    Cytat:
    Po co sys_Freq[] jest typu int Question Marnotrawstwo pamięci danych.
    zgadzam się, w rzeczywistym programie używam typów uintx_t .
  • #5 5757137
    szelus
    Poziom 34  
    To już było tyle razy...

    W C niejawna promocja typów int w wyrazeniu następuje tylko, jeżeli jeden z operandów jest typu o większym zakresie wartości, a nie kiedy wynik operacji może przekroczyć zakres typu. Ten drugi przypadek spada na programistę.

    Wiesz oczywiście, ża na AVR int to maksymalnie 32767? No to literał 10000 jest typu int. Jak pomnożysz przez inny int, który jest większy od 3, to przekroczysz zakres. 10000ul jest typu unsigned long i wymusi pomocję drugiego operandu do typu unsigned long przed wykonaniem mnożenia.
    Proste?
  • #6 5757280
    ginar
    Poziom 21  
    Cytat:
    Wiesz oczywiście, ża na AVR int to maksymalnie 32767

    w tym własnie problem..
    z tego co napisałeś podejrzewam, że na int przychodzi 16 bitów (bit znaku i 15 bitów na wartość ) co by wychodziło 2^16 różnych warości.
    na PC to chyba można uzyć do tego celu funkcji sizeof ,aby wiedzieć ile bitów przypada na dany typ zmiennej, a jak to można sprawdzić na AVR?
  • Pomocny post
    #7 5757430
    szelus
    Poziom 34  
    ginar napisał:

    na PC to chyba można uzyć do tego celu funkcji sizeof ,aby wiedzieć ile bitów przypada na dany typ zmiennej,

    sizeof należy chyba do standardu C, nieprawdaż?
    Cytat:

    a jak to można sprawdzić na AVR?

    Przeczytać w instrukcji?
    Przejrzeć zawartość pliku stdint.h?
  • #8 5757862
    Dr.Vee
    VIP Zasłużony dla elektroda
    I na przyszłość nie używać w systemach wbudowanych char, short, int, long, tylko [u]int{8,16,32}_t zdefiniowanych w pliku stdint.h

    Pozdrawiam,
    Dr.Vee
  • #9 5758145
    ginar
    Poziom 21  
    dzieki, rzeczywiscie w stdint.h jest wszystko opisane
    Cytat:
    I na przyszłość nie używać w systemach wbudowanych char, short, int, long, tylko [u]int{8,16,32}_t zdefiniowanych w pliku stdint.h
    tak tez mam zamiar zrobic, wtedy bedzie przejzyszcie
    Pozdr.
REKLAMA