Kurs AVR GCC Dekoder RC5

background image

Artykuł pochodzi ze strony XYZ HOBBY ROBOT (

xyz.isgreat.org

)

Kurs AVR-GCC Dekoder protokołu RC5

3.06.11 ABXYZ

Artykuł jest dodatkiem poszerzającym tematykę publikowanego na
tej stronie kursu AVR-GCC

Pilot na podczerwień to tani i prosty sposób na bezprzewodowe
sterowanie urządzeniami z bliskiej odległości. W tym artykule
opisałem jak wykonać odbiornik współpracujący ze standardowym
pilotem RC5. Funkcję dekodera protokołu RC5 będzie oczywiście
pełnił mikrokontroler- napiszemy taki programik w języku C.
Odbiornik można wykorzystać do budowy różnych urządzeń
sterowanych pilotem.

Scalony odbiornik podczerwieni SFH5110-36

Obok pilota RC5 i mikrokontrolera AVR ATMEGA będzie potrzebny
scalony odbiornik podczerwieni SFH5110-36, układ ten jest łatwo
dostępny i kosztuje ok 3zł.

Fot. 1. SFH5110-36 Scalony odbiornik/demodulator podczerwieni

Rys.1. Podłączenie układu SFH5110-36

Rysunek poniżej wyjaśnia sposób działania układu SFH5110-36.
Odbiornik SFH5110-36 posiada trzy wyprowadzenia: 1-wyjście
cyfrowe, 2-masa, 3-zasilanie(5V) . Normalnie na wyjściu odbiornika
SFH5110-36 jest wysoki stan napięcia, gdy odbiornik zostanie
oświetlony pilotem, na wyjściu pojawi się stan niski. Pilot świeci
diodami IR impulsowo, z częstotliwością ok 36kHz, gdyż odbiornik
SFH5110-36 reaguje tylko na oświetlenie impulsowe o
częstotliwości 36kHz, eliminuje to wpływ zakłóceń z innych źródeł
światła.

1 z 7

background image

Rys. 2. Zasada działania i sposób użycia odbiornika podczerwieni SFH5110-36.

Scalony odbiornik podczerwieni podobny do SFH5110-36 można
wyciągnąć ze zużytego TV lub innego sprzętu. Przed wylutowaniem
trzeba tylko rozeznać do których wyprowadzeń przyłączone jest
zasilanie, a które jest wyjściem danych.

Pilot RC5

Chociaż w każdym porządnym domu znajdzie się kilka pilotów na
podczerwień, to jest całkiem prawdopodobne, że żaden nie działa
zgodnie z protokołem Philips RC5. Ale to żaden problem.
Nowiutkiego pilota RC5 kupisz na allegro w cenie ok 5..7zł. Ja
posłużę tu się pilotem od starego telewizora, fotka poniżej, pilot ten
ma w środku układ scalony SAA3010P.

Fot. 2. Klasyczny pilot, pozostał mi po wymianie starego TV, w środku ma układ scalony

SAA3010P

Protokół zdalnego sterowania RC5

Wciśnięcie przycisku w pilocie RC5 skutkuje wysłaniem ramki
danych, która składa się z czternastu bitów danych. Najpierw idą
dwa bity startowe, oba zawsze mają wartości 1. Następny jest bit
kontrolny toggle, bit ten zmienia swoją wartość na przeciwną, za
każdym razem, kiedy naciśnięty jest któryś przycisk w pilocie.
Kolejne pięć bitów sys5..sys0 to adres systemu (urządzenia), dla TV
adres ma wartość 0. Pozostałe sześć bitów cmd4..cmd0, zawierają
numer przycisku.

2 z 7

background image

Rys.3. Ramka danych protokołu sterowania RC5 składa się z 14 bitów.

W protokole RC5 wykorzystuje się kodowanie bitów Manchaster. Bit
o wartości 1 kodowany jest jako przejście poziomu sygnału z
niskiego na wysoki, a bit o wartości 0, jako przejście z poziomu
wysokiego na niski. W obu przypadkach zmiana poziomu sygnału
następuje w połowie czasu trwania bitu. Czas trwania każdego bitu
wynosi ok 1.8 milisekundy.

Rys.4. Kodowanie bitów Manchester

Pilot RC5 przesyła kolejne ramki danych w odstępie czasu nie
mniejszym niż okres trwania 50 bitów.

Rys.5. Odstęp pomiędzy kolejnymi ramkami danych równa się czasowi trwania 50 bitów.

Przykładowy program dekodera RC5

Program będzie dekodował komendy pilota RC5 i prezentował wynik
na siedmiu diodach LED. Sześć diod pokaże numer przycisku, a
siódma - toggle bit. Toggle bit zmienia swój stan przy każdym
wciśnięciu przycisku. Siedem diod LED przyłączyłem do portu D
AVRa, a odbiornik podczerwieni SFH5110-36 do PB0.

W programie wykorzystano przerwanie wywoływane przepełnieniem
timera0 - "Timer0 Overflow". Timer0 skonfigurowany jest tak, że
przerwania występują co 32 mikrosekundy. Z każdym wystąpieniem
przerwania inkrementowana jest globalna zmienna "timerL", a co
256 wystąpień przerwania, inkrementowana jest globalna zmienna
"timerH". Zmienne "timerL" i "timerH" tworzą zegary, które
użyjemy w programie do mierzenia czasu trwania impulsów i do
wymierzania odcinków czasu.

Wykrywaniem i dekodowaniem komend rc5 zajmuje się funkcja
"detect". Funkcja "detect" uruchamiana jest w głównej pętli
programu, zwraca 12-bitowy kod komendy RC5, albo wartość -1,
jeśli w okresie 131ms nie wykryje komendy lub wystąpi błąd.

3 z 7

background image

Na początku funkcji "detect" program odczytuje w pętli stań wejścia
uC, do którego podłączono odbiornik podczerwieni SFH5110-36,
oczekując okresu ciszy trwającego co najmniej 3.5ms - cisza to stan
wysoki napięcia na wyjściu SFH5110-36. Przypominam, że
normalnie na wyjściu odbiornika SFH5110-36 jest wysoki stan
napięcia, a gdy odbiornik oświetlany jest pilotem, to na wyjściu
pojawia się stan niski. Jeśli w ciągu 131ms nie wystąpił okres ciszy
trwający 3.5ms, to funkcja kończy działanie zwracając kod -1,
oznaczający brak komendy. Następnie program oczekuje
opadającego zbocza sygnału w połowie pierwszego bitu startowego

Po wykryciu bitu startowego mierzony jest czas trwania niskiego
poziomu sygnału. Jeśli nie wykryto pierwszego bitu startowego w
okresie 131ms, albo mierzony czas trwania poziomu niskie sygnału
w pierwszym bicie startowym okazał się dłuższy niż 1.1ms, to
funkcja kończy działanie zwracając kod oznaczający brak komendy.
Dalej program oczekuje opadającego zbocza w środku drugiego bitu
startowego. Funkcja wykorzystuje opadające lub rosnące zbocze
sygnału w połowie każdego bitu do synchronizacji. Odczyt wartości
kolejnego bitu ramki dokonuje się po okresie 3/4 czasu trwania bitu
od momentu wykrycia zbocza w środku poprzedniego bitu.
Odczytana wartość bitu zachowywana jest w zmiennej. Dalej, jeśli
odczytano wartość bitu 1, to program oczekuje wystąpienia zbocza
opadającego w środku bitu, a jeśli odczytano wartość bitu 0, zbocza
narastającego. W momencie wykrycia krawędzi w środku bitu
następuje wyzerowanie timera i cała akcja jest powtarzana dla
kolejnego bitu. Jeśli program nie wykryje odpowiedniego zbocza w
okresie 5/4 czasu trwania bitu od momentu poprzedniej
synchronizacji, to funkcja kończy działanie z błędem.

Rys. 6. Próbkujemy po 3/4 czasu trwania bitu od momentu wykrycia zbocza sygnału w

połowie poprzedniego bitu.

A oto nasz programik, całość w jednym pliku.

//---------------------------------------------------------------
// Plik "main.c"
//
// KURS AVR-GCC (abxyz.bplaced.net)
//
// Dekoder RC5
//
// (schemat i opis działania w artykule)
// testowanie na atmega8 (8MHz)
//---------------------------------------------------------------

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

4 z 7

background image

// Odbiornik podczerwieni SFH5110 przyłączona do portu PB0

#define RC5_IN (PINB & (1<<0))

//

typedef

unsigned

char

u8;

;

;

;

typedef

unsigned

int

uint;

;

;

;

// Zmienne globalne pełnią rolę programowych zegarów
// napędzanych przerwaniem TIMER0_OVF

volatile

u8 timerL;

;

;

;

volatile

u8 timerH;

;

;

;

//---------------------------------------------------------------
// Funkcja konfiguruje i uruchamia Timer0
// oraz włącza przerwanie od przepełnienia timera,
// przerwanie powinno występować co 32us.
//---------------------------------------------------------------

void

init_rc5()

()

()

()

{

{

{

{

//atmega8

TCCR0 =

=

=

= (

(

(

(

1

<<

<<

<<

<<CS00);

);

);

);

// włącza Timer0

TIMSK =

=

=

= (

(

(

(

1

<<

<<

<<

<<TOIE0);

);

);

);

// włącza przerwanie "Timer0 Overflow"

/*
//atmega88
TCCR0B = (1<<CS00);
TIMSK0 = (1<<TOIE0);
*/

// Zezwala na przerwania

sei();

();

();

();

}

}

}

}

//---------------------------------------------------------------
// Procedura obsługi przerwania Timer0 Overflow"
//---------------------------------------------------------------

ISR(

(

(

(TIMER0_OVF_vect)

)

)

)

{

{

{

{

volatile

static

u8 inttemp;

;

;

;

// zmienna timerL zwiększa się co 32us

timerL++;

++;

++;

++;

// zmienna timerH zwiększa się co 8.192ms (32us*256)

inttemp++;

++;

++;

++;

if

(!

(!

(!

(!inttemp )

)

)

) timerH++;

++;

++;

++;

}

}

}

}

//---------------------------------------------------------------
// Funkcja wykrywa i dekoduje komendę pilota RC5
//---------------------------------------------------------------

uint detect()

()

()

()

{

{

{

{

u8 temp;

;

;

;

u8 ref1;

;

;

;

u8 ref2;

;

;

;

u8 bitcnt;

;

;

;

uint command;

;

;

;

timerH =

=

=

=

0

;

;

;

;

timerL =

=

=

=

0

;

;

;

;

// Czeka na okres ciszy na linii wejścia uC trwający 3.5ms

// Jeśli nie wykryje takiego okresu ciszy w ciągu 131ms,

// to kończy działanie funkcji z błędem

while

(

(

(

( timerL<

<

<

<

110

)

)

)

)

{

{

{

{

if

(

(

(

(timerH>=

>=

>=

>=

16

)

)

)

)

return

command =

=

=

= -

-

-

-

1

;

;

;

;

if

(!

(!

(!

(!RC5_IN)

)

)

) timerL =

=

=

=

0

;

;

;

;

}

}

}

}

// Czeka na pierwszy bit startowy.

// Jeśli nie wykryje bitu startowego w ciągu 131ms,

// to kończy działanie funkcji z błędem

while

(

(

(

(RC5_IN)

)

)

)

if

(

(

(

(timerH>=

>=

>=

>=

16

)

)

)

)

return

command =

=

=

= -

-

-

-

1

;

;

;

;

// Pomiar czasu trwani niskiego poziom syganłu

// w pierwszym bicie startowym.

// Jeśli nie wykryje rosnącego zbocza sygnału w ciągu

5 z 7

background image

// 1ms, to kończy działanie funkcji z błędem

timerL =

=

=

=

0

;

;

;

;

while

(!

(!

(!

(!RC5_IN)

)

)

)

if

(

(

(

(timerL>

>

>

>

34

)

)

)

)

return

command =

=

=

= -

-

-

-

1

;

;

;

;

//

temp =

=

=

= timerL;

;

;

;

timerL =

=

=

=

0

;

;

;

;

// ref1 - oblicza 3/4 czasu trwania bitu

ref1 =

=

=

=temp+(

+(

+(

+(temp>>

>>

>>

>>

1

);

);

);

);

// ref2 - oblicza 5/4 czasu trwania bitu

ref2 =(

=(

=(

=(temp<<

<<

<<

<<

1

)+(

)+(

)+(

)+(temp>>

>>

>>

>>

1

);

);

);

);


// Oczekuje na zbocze opadające sygnału w środku drugiego

// bitu startowego.

// Jeśli nie wykryje zbocza w ciągu 3/4 czasu trwania

// bitu, to kończy działanie funkcji z błędem

while

(

(

(

(RC5_IN)

)

)

)

if

(

(

(

(timerL >

>

>

> ref1)

)

)

)

return

command =

=

=

= -

-

-

-

1

;

;

;

;

// W momencie wykrycia zbocza sygnału, synchronizuje

// zmieną timerL dla próbkowania bitu toggle

timerL =

=

=

=

0

;

;

;

;

// Odczytuje dekoduje pozostałe 12 bitów polecenia rc5

for

(

(

(

(bitcnt=

=

=

=

0

,

,

,

, command =

=

=

=

0

;

;

;

; bitcnt <

<

<

<

12

;

;

;

; bitcnt++)

++)

++)

++)

{

{

{

{

// Czeka 3/4 czasu trwania bitu od momentu wykrycia

// zbocza sygnału w połowie poprzedniego bitu

while

(

(

(

(timerL <

<

<

< ref1)

)

)

) {};

{};

{};

{};


// Próbkuje - odczytuje port we uC

if

(!

(!

(!

(!RC5_IN)

)

)

)

{

{

{

{

// Jeśli odczytano 0, zapamiętuje w zmiennej

// "command" bit o wartości 0

command <<=

<<=

<<=

<<=

1

;

;

;

;

// Oczekuje na zbocze rosnące sygnału w środku bitu.

// Jeśli nie wykryje zbocza w ciągu 5/4 czasu trwania

// bitu, to kończy działanie funkcji z błędem

while

(!

(!

(!

(!RC5_IN)

)

)

)

if

(

(

(

(timerL >

>

>

> ref2)

)

)

)

return

command =

=

=

= -

-

-

-

1

;

;

;

;

}

}

}

}

else

{

{

{

{

// Jeśli odczytano 1, zapamiętuje w zmiennej

// "command" bit o wartości 1

command =

=

=

= (

(

(

(command <<

<<

<<

<<

1

)

)

)

) |

|

|

|

0x01

;

;

;

;

// Oczekuje na zbocze opadające sygnału w środku bitu.

// Jeśli nie wykryje zbocza w ciągu 5/4 czasu trwania

// bitu, to kończy działanie funkcji z błędem

while

(

(

(

(RC5_IN)

)

)

)

if

(

(

(

(timerL >

>

>

> ref2)

)

)

)

return

command =

=

=

= -

-

-

-

1

;

;

;

;

}

}

}

}

// W momencie wykrycia zbocza sygnału, synchronizuje

// zmieną timerL dla próbkowania kolejnego bitu

timerL =

=

=

=

0

;

;

;

;

}

}

}

}

// Zwraca kod polecenia rc5

// bity 0..5 numer przycisku

// bity 6..10 kod systemu(urządzenia)

// bit 11 toggle bit

return

command;

;

;

;

}

}

}

}

//---------------------------------------------------------------
// GLÓWNA FUNKCJA PROGRAMU
//---------------------------------------------------------------

int

main(

(

(

(

void

)

)

)

)

{

{

{

{

//

uint cmd;

;

;

;

u8 out;

;

;

;

6 z 7

background image

// Porty PD0..PD6 wyjściami - diody LED

DDRD =

=

=

=

0x7f

;

;

;

;

PORTD =

=

=

=

0x00

;

;

;

;

// uruchamia Timer0 i przerwanie

init_rc5();

();

();

();

while

(

(

(

(

1

)

)

)

)

{

{

{

{

// Wykrywa i dekoduje polecenie pilota RC5

cmd =

=

=

= detect();

();

();

();

// Jeśli odebrano komendę

if

(

(

(

(cmd !=

!=

!=

!= -

-

-

-

1

)

)

)

)

{

{

{

{

// Na sześciu diodach LED pokaże numer polecenia rc5,

// a na siódmej LED - toggle bit

out =

=

=

= (

(

(

(cmd &

&

&

& (

(

(

(

1

<<

<<

<<

<<

11

))

))

))

)) >>

>>

>>

>>

5

;

;

;

;

out |=

|=

|=

|= cmd &

&

&

&

0x3f

;

;

;

;

PORTD =

=

=

= (

(

(

(out);

);

);

);

}

}

}

}

}

}

}

}

return

0

;

;

;

;

}

}

}

}

Listing 1 Program dekodera RC5

Ważne! Program przeznaczony jest dla uC atmega8 taktowanego
zegarem 8MHz. W przypadku, gdy mikrokontroler ma pracować
z częstotliwością inną niż 8MHz, to program będzie wymagał
drobnego dopasowania. Jeśli masz z tym problem, pytaj na forum.

Katalog z plikami projektu można pobrać klikając w link

dekoder_rc5.zip

. Kod wynikowy programu ma wielkość 400 bajtów.

Pisząc niniejszy artykuł opierałem się na atmelowskiej nocie
aplikacyjnej AVR410

doc1473.pdf

.

3.06.11 ABXYZ

Copyright © 2009-2011 ABXYZ - Wszelkie prawa zastrzeżone

7 z 7


Wyszukiwarka

Podobne podstrony:
Kurs AVR GCC cz 1
Kurs AVR GCC, cz 2
Kurs AVR GCC cz 4 2
Kurs AVR GCC cz 2
Kurs AVR GCC, cz 5
Kurs AVR GCC, cz 1
Kurs AVR GCC cz 3
Kurs AVR GCC, cz 4
Kurs AVR GCC, cz 3
Kurs AVR GCC Wyświetlacz LCD od Nokii 3310
Kurs AVR GCC cz 5
Kurs AVR GCC cz 1

więcej podobnych podstron