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.

[C] Atmega32 - błąd w obliczeniach trzech zmiennych

steter 04 Sie 2012 23:03 1377 10
  • #1 04 Sie 2012 23:03
    steter
    Poziom 7  

    Witam forumowiczów.

    Od paru godzin męczę się z pewnym problemem.
    Nie rozumiem dlaczego Atmega 32A błędnie liczy mnożenie trzech zmiennych.

    Utworzyłem zmienną "wynik" wielkości 4 bajtów (zakres liczb 0 do 4294967295)
    utworzyłem zmienną "a" wielkości 2 bajtów (zakres liczb 0 do 65535)
    utworzyłem zmienną "b" wielkości 1 bajta (zakres liczb 0 do 255)
    utworzyłem zmienną "c" wielkości 1 bajta (zakres liczb 0 do 255)

    każdej zmiennej przydzieliłem początkowe wartości

    wynik=0
    a=1024
    b=25
    c=13

    wynik mnożenia [ wynik=a*b*c ] powinien wynosić 332800 a moja Atmega_32A pokazuje na LCD 5120
    Dla pewności , że lcd nie robi mnie w konia , wpisuję w kodzie instrukcję warunkową, że jeśli zmienna "wynik" równa się 5120 to niech zapali mi diodę podłączoną do portu A pinu 0.
    Dioda się zapala.

    Kombinowałem z różnymi liczbami i nawet wychodziły mi wartości ujemne.
    Czy popełniłem gdzieś błąd w kodzie?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    częstotliwość Atmegi 1MHz

    0 10
  • #3 04 Sie 2012 23:22
    piotrva
    Moderator na urlopie...

    Poczytaj o czymś takim jak rzutowanie. W twoim przykładzie obliczenia są wykonywane (z tego co wiem o C) na zmiennej 16-sto bitowej i dopiero potem kopiowane do 32-bitowej - stąd odcinanie danych.
    Powinieneś napisać to tak:

    Code:

    wynik=(uint32_t)a*(uint32_t)b*(uint32_t)c; 

    Wtedy obliczenia będą prowadzone na zmiennych 32 bitowych i nie dojdzie do utraty wyższych bitów danych

    0
  • #4 04 Sie 2012 23:37
    steter
    Poziom 7  

    Uczę się właśnie na temat ADC i właśnie tam zaszła konieczność takiego mnożenia,
    korzystam z książki Pana Mirosława Kardaś, w książce są to zmienne właśnie w takich
    rozmiarach, widać muszę jeszcze sporo poczytać, prawidłowo obliczyło dopiero po zmianie typu zmiennej "a" na 32bity, a wyświetliło po podziale zmiennej "wynik" przez 100.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dziękuję za pomoc.
    Pozdrawiam.
    Temat uważam za zamknięty.

    0
  • #5 04 Sie 2012 23:39
    excray
    Poziom 39  

    Pobierz ze strony autora erratę do tej książki.

    0
  • #6 04 Sie 2012 23:53
    steter
    Poziom 7  

    Ale ja mam wydanie drugie, więc jest poprawione.
    Porównałem błędy (czy czasem nie mam pierwszego wydania)
    i na pewno mam drugie.

    Pozdrawiam.

    0
  • #7 04 Sie 2012 23:55
    excray
    Poziom 39  

    Więc pewnie będzie kolejna errata :-P

    0
  • #8 05 Sie 2012 04:24
    mirekk36
    Poziom 42  

    excray napisał:
    Więc pewnie będzie kolejna errata :-P


    Errata to może nie - ale warto zapoznać się z tym: LINK i zapoznać się dobrze z czymś takim jak "domyślna promocja do typu int w AVR GCC".

    0
  • #9 05 Sie 2012 12:11
    steter
    Poziom 7  

    Intryguje mnie jeszcze jedna rzecz.

    Mianowicie podczas konwersji wartości ADC na wartość napięcia widniejącą na LCD wkrada się mały błąd w wyświetlaniu (tak mi się przynajmniej wydaje). Otóż gdy
    wartość zmiennej pm wynosi 248 to na LCD widzimy 8.6V a powinniśmy widzieć 8.06V jest to różnica połowy Volta

    dla wartości

    pm=246 na LCD jest 7.99V
    pm=248 na LCD jest 8.6V
    pm=250 na LCD jest 8.12V

    może to mało znacząca różnica, i w początkach nauki programowania nie przeszkadza, ale chciałbym zobaczyć jakieś szybkie i krótkie rozwiązanie takiego problemu.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Pozdrawiam.

    0
  • #10 05 Sie 2012 12:44
    tronics
    Poziom 36  

    Cytat:
    reszta z dzielenia wynosi 06

    Jakie 06? Gdzie ty widziałeś taki zapis? To jest zwykłe 6 i stąd masz problem. Inaczej rozbij obliczenia i będzie ok.

    0
  • #11 05 Sie 2012 13:01
    steter
    Poziom 7  

    Mój błąd, reszta z dzielenia wynosi 6.

    Problem rozwiązany, wystarczyło napisać warunek,

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0