Dzień dobry.
Wiem, że temat omawiany w szerokim zakresie. ale chciałem zrobić to sam i niestety jest pewien problem.
Program wykonuję na ATmega 1284, chcę odebrać bajty z modułu GPS/GLONASS. Wcześniej udało mi się to zrobić za pomocą hardware'u, jednakże teraz chciałbym skorzystać ze sleep mode'ów i potrzebuję wybudzania na bit UART'a.
Do problemu podszedłem w taki sposób, że na początku czekam na zbocze opadające (początek bitu startu) i włączam Timer. Timer liczy ile bitów przeminęło (częstotliwość ustawiona na ~9600Hz) i program czeka na zbocze narastające. Inicjalizuję licznik odebranych bitów wartością -1, aby zignorować bit startu i nie interpretować go jako bit danych. Zastosowałem taki trik, że jeżeli zbocze pojawiło się tuż przed przerwaniem Timer'a to sprawdzam, czy wartość rejestru TCNT jest większa niż 0.9 * OCR (czyli bliskie jest przerwanie z Timer'a). W zależności od zbocza ustawiam bity odebrane: jeżeli stan na pinie wynosi jeden to znaczy, że ostatnie zbocze było narastające i odebrano ostatnio logiczne jedynki; analogicznie dla stanu pinu wynoszącemu zero. Wykrycie całego bajtu zachodzi podczas, gdy zostało wykryte początkowe zbocze bitu stopu lub gdy w przerwaniu Timer'a zostaną naliczone 8 bajtów. Wykrycie zachodzi w przerwaniu Timer'a, gdy ostatni bit danych był logicznym 0.
Kod programu:
uart.h:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
uart.c:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Przy odebraniu pełnego bajtu generuję przerwanie programowe, w którym następuje obsługa danych na poziomie bajtów (wyłuskiwanie odpowiednich danych z tekstu).
Problem polega na tym, że dostaję "krzaki" i wydaje mi się, że bajtów odbieram mniej niż powinienem, czyli tak jakby nie wykrywane były wszystkie zbocza lub przerwania Timer'a były w nie odpowiednim momencie.
Wykonałem testy:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Ustawiłem Timer2 na częstotliwość 8000000/256 = 31250 Hz:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
i przy każdym zboczu zapisywałem ile minęło od ostatniego zbocza; to są wyniki:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Lewa kolumna to odczytana wartość rejestru TCNT, środkowa wartość to wartość cycles_not_int a prawa kolumna to stan pinu.
Widać, że jest tu jakiś determinizm. Gdy wziąłem powtarzające się wiersz i obliczyłem czasy pomiędzy kolejnymi zboczami, wyszło mi, że wynoszą one 57.25, 128, 227.25, 267, 366.125 [us]. Nie rozumiem dlaczego nie ma tu wartości wielokrotności 104us, czyli 1/9600 (baud rate).