Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATtiny26][avr-gcc] Wyswietlenie double na LCD - dtostrf()

wladziu22 14 Gru 2009 19:10 5133 9
  • #1 14 Gru 2009 19:10
    wladziu22
    Poziom 17  

    Witam wszystkich.

    Chcąc wykorzystać dobrodziejstwa avr-gcc użyłem funkcji dtostrf(). Mam funkcje wypisującą znak na LCD i jak robię np:

    Code:

    void wypiszNaLCD(unsigned char*p)
    {
       unsigned char c;
       while((c = *p++) != '\0')
          print(c);
    }
    //////////////////////////////
    int main(void)
    {
    .
    .
    .       
            unsigned char str[10];
       int i =1234;
       itoa(i,str,10);
       wypiszNaLCD(str);
    }

    To oczywiście wypisze mi 1234 na LCD
    ale...gdy chce wyświetlić double robię tak w funkcji main:
    Code:

       volatile double wynik;
       unsigned char str2[10];
       wynik = 12.123;
            dtostrf(wynik,3,3,str);
       wypiszNaLCD(str2);

    Dodatkowo w pliku Makefile ustawiam:
    Code:

    PRINTF_LIB = $(PRINTF_LIB_FLOAT)
    co widać poniżej

    Code:

    #---------------- Library Options ----------------
    # Minimalistic printf version
    PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

    # Floating point printf version (requires MATH_LIB = -lm below)
    PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

    # If this is left blank, then it will use the Standard printf version.
    #PRINTF_LIB =
    #PRINTF_LIB = $(PRINTF_LIB_MIN)
    PRINTF_LIB = $(PRINTF_LIB_FLOAT)

    # Minimalistic scanf version
    SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

    # Floating point + %[ scanf version (requires MATH_LIB = -lm below)
    SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

    # If this is left blank, then it will use the Standard scanf version.
    SCANF_LIB =
    #SCANF_LIB = $(SCANF_LIB_MIN)
    #SCANF_LIB = $(SCANF_LIB_FLOAT)


    MATH_LIB = -lm

    ale niestety nie wyświetla mi nic na LCD.
    W czym tkwi problem? Coś jeszcze powinienem ustawić makefile?

    0 9
  • Pomocny post
    #2 14 Gru 2009 19:46
    Freddie Chopin
    Specjalista - Mikrokontrolery
  • Pomocny post
    #3 14 Gru 2009 19:59
    tmf
    Moderator Mikrokontrolery Projektowanie

    A BTW na AVR nie istnieje typ double - dla scislosci istnieje, ale jest to to samo co float. Nie wiem jak avr-libc potraktuje double - czy tu nie bedzie jakis spiec.

    0
  • #4 14 Gru 2009 21:27
    wladziu22
    Poziom 17  

    kurcze ale babol...mam nadzieje ze to rozwiąże problem. Niestety nie mogę sprawdzić, bo dziwne ale po poprawie tego kodu wiesza mi się procek na tej funkcji :/ podobnie na pierwszym przykładzie ?!:/ Nie wiem co jest grane...

    a co double... nic mi nie krzyczał kompilator wiec nie zmieniałem na float.

    Dodano po 17 [minuty]:

    Dobra, mała poprawka..ten pierwszy przykład ponownie mi zadziałał, ale to z:

    Code:
    dtostrf(wynik,3,3,str);
    
    wypiszNaLCD(str);

    i zmianie w makefile powoduje reset uC. Jutro spróbuje z najnowszym pakietem winAVR, bo jadę na jakiejś starszej wersji.

    0
  • #5 15 Gru 2009 21:31
    wladziu22
    Poziom 17  

    Sprawdziłem dzisiaj ten babol (na najnowszej wersji WINAVR)....i niestety ale nadal na wyświetlaczu widzę jakby się wieszał procek. String wrzucony na wyświetlacz, tuz przed wywołaniem funkcji dtostrf() miga :/
    Zmiana z double na float tez nie pomogła.

    Dodano po 5 [minuty]:

    Dobra już chyba wiem gdzie tkwi problem :) Przekroczona pamięć programu tuz po dołączeniu nagłówka <stdlib.h>, wywołaniu funkcji i dodaniu zmiany w Makefile.
    Efekt po kompilacji:

    Code:

    Device: attiny26

    Program:    4868 bytes (237.7% Full)
    (.text + .data + .bootloader)

    Data:         48 bytes (37.5% Full)
    (.data + .bss + .noinit)


    ahhhh...Dobrze rozumuje ? :)

    0
  • Pomocny post
    #6 15 Gru 2009 22:31
    shg
    Specjalista techniki cyfrowej

    Tak, za dużo kodu napchałeś.

    Code:
    PRINTF_LIB = $(PRINTF_LIB_FLOAT) 

    To Ci nie potrzebne, dtostrf() nie używa tego kodu i powstało właśnie po to, żeby pozbyć się "ociężałego" printf(). Na takim małym procku lepiej printf() i scanf() (i podobnych) nie używać, a już na pewno nie w wariancie zmiennoprzecinkowym.

    0
  • #7 15 Gru 2009 22:38
    tmf
    Moderator Mikrokontrolery Projektowanie

    Z tego co widze nie masz dolaczonej biblioteki matematycznej (libm, -lm), sprobuj ja dolaczyc, to powinno znacznie zredukowac ilosc zajetej pamieci, ale ciagle bez gwarancji, ze sie zmiesci.
    Na pewno potrzebujesz typow zmiennopozycyjnych? Arytmetyka stalopozycyjna ci nie wystarczy?

    0
  • #8 16 Gru 2009 07:19
    wladziu22
    Poziom 17  

    Ok. Spróbuje jeszcze bez włączania zmiennego przecinka makefile. Nie jest mi potrzebny zmienny przecinek. Tak tylko pomyślałem, że może skorzystam z tego ale nie sądziłem, ze aż tyle pamięci to wszytko zużywa. Dopiero po zainstalowaniu najnowszego WINAVR zauważyłem ile faktycznie przekroczyłem zakres (i po stworzeniu nowego pliku Makefile w nowej wersji). Mnożenie, dzielenie i modulo mam w małym palcu ;-) tak wiec podołam i bez zmiennego przecinka.


    Zaciekawiło mnie również to, ze fun. itoa() (z najnowszej paczki winavr) zwróciła string ale odwrócony. Zapewne coś źle robię, bo nie sadze, że funkcja ta ma błąd.

    Co do włączenia biblioteki matematycznej, zdaje się ze mam włączona:

    Code:
    MATH_LIB = -lm 

    0
  • #9 16 Gru 2009 10:23
    tmf
    Moderator Mikrokontrolery Projektowanie

    Fakt, jakos to przeoczylem :) Co do itoa to istotnie dla ATTiny26 ta funkcja ma blad i zwraca odwrocony string! Nie wiem czy juz ktos to raportowal tworcom AVR-libc.

    0
  • #10 17 Gru 2009 20:14
    wladziu22
    Poziom 17  

    ta funkcja ma błąd/nie działa poprawnie bo nie działa char *strrev(char *str), który jest wywoływany na koniec itoa().
    Probowalem u siebie i nie odwróciło string-a:

    Code:
          itoa(1234,pomiarNap,10);
    
          strrev(pomiarNap);
          wypiszNaLCD(pomiarNap);

    oczywiście będzie nadal 4321 na LCD.

    Dodano po 18 [minuty]:

    Na szczęście przy krótkich stringach można jeszcze wyłuskiwać poszczególne znaki z tablicy i wypisywać na LCD np tak jak ja to zrobiłem:
    Code:

    char pomiarNap[16];
    unsigned int NapiecieSred; //wartość z ADC
    unsigned long buff;
    unsigned int tmp;
    ......
    .....
    .....
    buff = (unsigned long)NapiecieSred*5000ul;
    buff = buff/1024ul;
    tmp = (unsigned int)buff;
    itoa(tmp,pomiarNap,10);

    wypiszNaLCD("Pomiar=");
    sendsign(pomiarNap[3]);
    sendsign('.');
    sendsign(pomiarNap[2]);
    sendsign(pomiarNap[1]);
    sendsign(pomiarNap[0]);
    wypiszNaLCD("[V]");


    jednak coś nie tak zrobiłem w przeliczaniu wyniku z ADC i czasami wyskakuje mi zamiast zera "jakis krzak" :/

    0