Witam
Jako nowy użytkownik chciałbym się przywitać i jednocześnie podzielić swoim sposobem na obsługę pilota nadającego w kodzie RC5. W sieci, również tutaj, opisywanych jest wiele implementacji tego zagadnienia, jednak żadna nie pasowała do moich potrzeb. Pokusiłem się więc o opracowanie własnego kodu.
W moim projekcie zajęte są zasoby sprzętowe używane zazwyczaj do tego celu, a mianowicie timer 16 bitowy i jego przerwanie ICP oraz wszystkie przerwania zewnętrzne - INTx.
Założenia są następujące:
- Należy wykorzystać przerwanie 8 bitowego timera (które przy okazji może również prowadzić inne "czasówki")
- Odbieranie kodów RC5 nie może blokować pracy procesora ani zbytnio go obciążać.
Wykorzystałem algorytm opisany w nocie Atmela "AVR410: RC5 IR Remote Control Receiver"
Algorytm ten (z małą zmianą) zaimplementowałem jednak w postaci maszyny stanu pracującej w funkcji przerwania timera wywoływanej co 0.1ms. W przerwaniu tym próbkowany jest stan wyjścia odbiornika podczerwieni podłączonego do dowolnego pinu jednego z portów procesora.
Proponowana przeze mnie implementacja działa bardzo pewnie. Nie stwierdziłem błędnie odebranych ani odrzuconych ramek RC5.
Poniżej przedstawiam kod i dalej opis działania.
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
A teraz jak to działa:
Z punktu widzenia użytkownika kodu, wystarczy wiedzieć, że po odebraniu ramki RC5 ustawiana jest flaga
flagIR. Po wykryciu tego faktu należy obsłużyć odebraną komendę, która znajduje się w zmiennej cmdIR a następnie wyzerować flagę. W cmdIR znajduje się cała ramka RC5 łącznie z adresem urządzenia oraz
toggle bitem, szczególnie o tym ostatnim warto pamiętac....
Poniżej opis dla dociekliwych:
Opis zmiennych:
cmdIR - zmienna 16 bitowa w której przechowywana jest ostatnio odebrana ramka RC5.
flagIR - flaga ustawiana po poprawnym odebraniu ramki RC5. Flaga ta powinna być wyzerowana przez aplikacje po obsłużeniu odebranego polecenia
stanIR - główna zmienna sterująca maszyny stanu.
timIR - zmienna służąca do zliczania czasu.
new_IRP - aktualny stan wyjścia odbirnika podczerwieni.
old_IRP - stan wyjścia odbiornika podczerwieni z poprzedniego cyklu (poprzedniego wywołania przerwania)
bcIR - licznik ilości odebranych bitów
refIR34, refIR54 - referencyjne czasy obliczone jako odpowiednio 3/4 i 5/4 czasu trwania transmisji jednego bitu.
Opis kodu:
W pierwszej linii aktualny stan wyjścia odbiornika podczerwieni zapamiętywany jest w zmiennej
new_IRP, jest to konieczne, ponieważ zmiana stanu w trakcie wykonywania kodu, może w pewnych przypadkach powodować błędne odrzucanie ramki danych. W ostatniej linii, wartość ta zapamiętywana jest w zmiennej
old_IRP i służy jako wartość "poprzednia" w następnym wywołaniu przerwania.
Właściwą pracę maszyny stanu rozpoczyna instrukcja
switch. Kod opisujący działanie maszyny w poszczególnych stanach zawarty jest pomiędzy parami instrukcji
case - break.
Stan 0: W tym stanie maszyna oczekuje na wyzerowanie flagi
flagIR, co oznacza, że ostatnio odebrana ramka została już obsłużona i można przystąpić do odbioru kolejnej. Jeśli
flagIR == 0 następuje przejście do stanu 1.
Stan 1:W tym stanie zmienna
timIR wykorzystana jest od odmierzania czasu trwania stanu wysokiego na wyjściu odbiornika podczerwieni, a więc czasu trwania "ciszy w eterze". Jeżeli wykryte zostanie 25.4 ms nieprzerwanej ciszy, maszyna przechodzi do stanu 2.
Stan 2: W tym stanie maszyna oczekuje na zbocze opadające na wyjściu odbiornika. Może ono oznaczać środek pierwszego bitu startu. Jeśli takie zbocze zostanie wykryte, następuje wyzerowanie licznika
timIR i przejście do stanu 3.
stan 3: W tym stanie maszyna oczekuje na kolejne zbocze opadające na wyjściu odbiornika. Może ono oznaczać środek drugiego bitu startu. Jednocześnie mierzony jest czas jaki upływa od wykrycia poprzedniego zbocza. Jeśli czas ten jest dłuższy niż 2,2ms, lub jeśli oczekiwane zbocze nastąpi po czasie krótszym niż 1,3ms, uznajemy że odebrana transmisja nie jest w formacie RC5 i przechodzimy do stanu 1.
Jeżeli natomiast zbocze opadające zostanie wykryte w dopuszczalnym przedziale czasowym, uznajemy że odebrano właśnie drugi bit startu. Na podstawie zmierzonego czasu trwania transmisji jednego bitu obliczone zostają referencyjne czasy 3/4 i 5/4 bitu (
refIR34 i
refIR54), wyzerowany zostaje licznik
timIR a następnie maszyna przechodzi do stanu 4.
stan 4:W tym stanie odbierane są kolejne bity ramki RC5. Po odczekaniu czasu
refIR34 (a więc dokładnie w 1/4 kolejnego bitu) stan wyjścia odbiornika jest wprost wartością nadawanego bitu. Stan ten zostaje wówczas wpisany do zmiennej
cmdIR, zwiększony zostaje również licznik ilości odebranych bitów
bcIR.
Następnie maszyna oczekuje na zbocze (dowolne) na wyjściu odbiornika. Oznacza ono środek aktualnie odbieranego bitu. Jeżeli takie zbocze nie wystąpi w czasie
refIR54, uznajemy że odbierana transmisja nie jest w formacie RC5 i maszyna powraca do stanu 1.
Jeżeli jednak zbocze zostanie wykryte w odpowiednim czasie, następuje wyzerowanie licznika
timIR. Oznacza to synchronizacje do kolejnego bitu. Od tej chwili maszyna, ciągle znajdująca się w stanie 4, odczekuje kolejny czas
refIR34 i odczytuje kolejny bit. Po poprawnym odczytaniu 12 bitów ustawiona zostaje flaga flagIR a maszyna przechodzi do stanu 0. Odebrana ramka znajduje się w zmiennej
cmdIR.
Warto zauważyć, że przedstawiony kod nie obciąża zbytnio procesora. Przez przeważającą część czasu maszyna znajduje się w stanie 2 w którym sprawdzany jest tylko jeden warunek.
Mam nadzieje, że komuś się to przyda.