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.

[ATmega8][C] - Wysłanie przez USART wartości liczbowej i przypisanie jej do PWM

Defozo 06 Mar 2013 16:22 1320 7
  • #1 06 Mar 2013 16:22
    Defozo
    Poziom 17  

    Witam, jestem początkującym programistą.
    Zamierzam napisać program na µC ATmega8, który odbierze liczbę z zakresu 0-255 przez USART i ustawi odpowiednio rejestry OCR1A i OCR1B w zależności od wysłanej liczby i przypisanemu jej rejestrowi.

    Próbowałem napisać kod, który po wysłaniu 'y' dla rejestru OCR1A lub 'u' dla rejestru OCR1B przypisze odpowiednią wartość, która zostałaby wysłana po nadaniu 'y' lub 'u', jednak mam wrażenie, że masakrycznie to zepsułem.
    Oto mój "genialny" kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Na pewno jest jakiś prosty sposób na rozwiązanie tego problemu.

    Proszę o pomoc,
    Defozo

    0 7
  • Pomocny post
    #2 06 Mar 2013 16:40
    bajcik
    Poziom 11  

    1) w przerwaniu odbierającym bajt lepiej wrzucić do do zmiennej albo buforka i opuścić przerwanie. Obsługę polecenia zrobić w pętli głównej. Tym bardziej że wysyłasz tam wiadomość - nie wiem czy nie powoduje to złej interakcji.

    2) zamiast
    pwm1value = pwm1value+wiadomosc*10;
    powinno być
    pwm1value = 10*pwm1value+(wiadomosc-'0');

    3) najlepiej rozdzielić pajęczynkę ifów/elsów tak żeby osobno było rozpoznawanie komendy, osobno wczytywanie liczby, osobno ustawianie OCR1B.

    Ogólnie: rób i testuj małe kawałeczki, potem je scalaj we większą całość cały czas testując

    0
  • Pomocny post
    #3 06 Mar 2013 16:58
    BlueDraco
    Specjalista - Mikrokontrolery

    Dużo wygodniej jest przesyłać polecenia w postaci <liczba><polecenie> niż <polecenie><liczba>. Nie musisz wtedy zapamiętywać, co trzeba będzie zrobić z liczbą wtedy, kiedy już będziesz ją miał. Widzisz liczbę - czytasz liczbę, i nieważne ile będzie miała cyfr - schemat czytania cyfry jest zawsze ten sam (mnożysz przez 10 to, co ju masz i dodajesz wartość cyfry). Widzisz polecenie - wykonujesz polecenie z wczytanym wcześniej argumentem.

    0
  • #4 07 Mar 2013 16:54
    Defozo
    Poziom 17  

    BlueDraco napisał:
    Dużo wygodniej jest przesyłać polecenia w postaci <liczba><polecenie> niż <polecenie><liczba>. Nie musisz wtedy zapamiętywać, co trzeba będzie zrobić z liczbą wtedy, kiedy już będziesz ją miał. Widzisz liczbę - czytasz liczbę, i nieważne ile będzie miała cyfr - schemat czytania cyfry jest zawsze ten sam (mnożysz przez 10 to, co ju masz i dodajesz wartość cyfry). Widzisz polecenie - wykonujesz polecenie z wczytanym wcześniej argumentem.


    Chciałem zrobić tak jak radzisz, ale coś chyba źle poszło, bo nie ważne jaką wartość wyślę to silnik zachowuje się jakby miał wpisane OCR1A/OCR1B = 0 (przestaje się kręcić).
    Umieszczam cały kod:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #5 07 Mar 2013 17:37
    BlueDraco
    Specjalista - Mikrokontrolery

    To, co nazywasz "liczba" po polsku nazywa się "cyfra". Aby uzyskać wartość cyfry musisz odjąć od niej kod zera, czyli wartosc = znak - '0';

    Obsługa przerwania odbioru transmisji powinna działać w min. 2 stanach: oczekiwania na cokolwiek i skanowania liczby. W stanie podstawowym po napotkaniu pierwszej cyfry zerujesz liczbę (albo i nie), zapisujesz w niej wartość cyfry i przechodzisz do stanu skanowania liczby. W tym stanie jeśli napotkasz cyfrę - "dokładasz" ją do liczby:
    liczba = liczba * 10 + znak - '0';
    Jeśli trafisz na coś innego niż cyfra - przechodzisz do stanu podstawowego i wykonujesz rozpoznane polecenie albo ignorujesz znak.

    0
  • #6 07 Mar 2013 19:58
    Defozo
    Poziom 17  

    BlueDraco napisał:
    Aby uzyskać wartość cyfry musisz odjąć od niej kod zera, czyli wartosc = znak - '0';

    Okej:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    BlueDraco napisał:
    W stanie podstawowym po napotkaniu pierwszej cyfry zerujesz liczbę (albo i nie), zapisujesz w niej wartość cyfry i przechodzisz do stanu skanowania liczby.

    Zapisuję wartość cyfry:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I przechodzę do "stanu skanowania liczby":
    BlueDraco napisał:
    W tym stanie jeśli napotkasz cyfrę - "dokładasz" ją do liczby:
    liczba = liczba * 10 + znak - '0';

    Nie rozumiem! Przecież właśnie to zrobiłem!

    Można jaśniej?


    Dziękuję za dotychczasowe odpowiedzi i proszę o dalszą pomoc,
    Defozo

    0
  • Pomocny post
    #7 07 Mar 2013 20:22
    BlueDraco
    Specjalista - Mikrokontrolery

    Tylko ty nigdzie nie czytasz cyfr.

    case '0' || '1' || itd. to dokładnie to samo co case 1:

    Raczej w default: daj if (c >= '0' && c <= '9').

    No i coś nie widzę tych dwóch stanów skanowania wejścia, ale może jakimś cudem to działa.

    Po co Ci te procedury z jednym podstawieniem? Koszt wywołania procedury jest znacznie większy niż koszt wykonania jej ciała, a czytelności kodu to nie poprawia

    0
  • #8 18 Mar 2013 18:46
    Defozo
    Poziom 17  

    BlueDraco napisał:
    Tylko ty nigdzie nie czytasz cyfr.

    case '0' || '1' || itd. to dokładnie to samo co case 1:

    Raczej w default: daj if (c >= '0' && c <= '9').

    No i coś nie widzę tych dwóch stanów skanowania wejścia, ale może jakimś cudem to działa.

    Po co Ci te procedury z jednym podstawieniem? Koszt wywołania procedury jest znacznie większy niż koszt wykonania jej ciała, a czytelności kodu to nie poprawia

    Teraz działa poprawnie!
    Te procedury potrzebne mi były, ponieważ w starym środowisku programistycznym jakimś cudem nie chciało mi inaczej przypisywać wartości do zmiennej globalnej.

    Umieszczam program:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jednak mam kolejne pytanie:
    [ATmega8][C][Delphi][BTM-222] - Czy konieczne są opóźnienia w transmisji?


    Dziękuję za pomoc!
    Temat zamykam...
    Defozo

    0