Kursy • Poradniki • Inspirujące DIY • Forum
« Poprzedni artykuł z seriiNastępny artykuł z serii »
Wstępna konfiguracja układu i oczekiwanie…
Na samym początku musimy odpowiednio skonfigurować nasz układ, co zrealizujemy korzystając z następującej funkcji:
void Rfm_init(void){
Rfm_xmit(SW_RESET);//resetuję programowo układ RFM12B
_delay_ms(250);
//inicjalizacja RFM12B
//ustawienie pasma 868MHz, konfiguracja FIFO
Rfm_xmit(CONFIGURATION|EN_DATA_REG|EN_FIFO|BAND_868|CAP_12_0);
//włączenie oscylatora
Rfm_xmit(POWER|EN_OSC|DIS_CLKO);
//ustawienie pasma (musi być takie samo w nadajniku i odbiorniku)
//Dla naszego układu częstotliwość musi zawierać się w przedziale 860480000-879515000Hz i musi być podawana ze skokami 5000Hz
Rfm_xmit(FREQUENCY|RF12_FREQUENCY_CALC_868(868000000UL));
//ustawienie prędkości transmisji danych (musi być takia sama w nadajniku i odbiorniku)
Rfm_xmit(BAUD|BAUD_4800);
//ustawienie pasma 134kHz i parametrów odbiornika
Rfm_xmit(RECEIVER|P20_VDI|BW134|LNA_0|RSSI_103);
//ustawienie cyfrowego filtra danych i opcji odzyskiwania zegara
Rfm_xmit(DATA_FILTER|AUTO_CR|DIGITAL_F|DQD_4);
//reset bufora FIFO, konfiguracja synchronizacji za pomocą 2 bajtów, ustawienie generowania przerwania FFIT po odebraniu 8 bitów
Rfm_xmit(FIFO_RST|FIFO_IT_8|FIFO_SYNC|HS_RST_DIS);
//konfiguracja kontrolera częstotliwości
Rfm_xmit(AFC|KEEP_RX|REST_OFF|EN_FOFFSET|EN_AFC);
//konfiguracja nadajnika i jego mocy (na ustawienie maksymalne)
Rfm_xmit(TRANSMITER|FSK_PHASE_0|FSK_DF_90K|OUT_P_0);
//konfiguracja pętli PLL
Rfm_xmit(PLL|PLL_DH_DIS|SEL_CLK_2_5|MAX_BAUD_256);
//wyłączenie timera wakeup
Rfm_xmit(WAKEUP_TIM|WUT_X_2_0|0);
//wyłączenie oszczędzania energii
Rfm_xmit(LOW_DC|LOW_DC_DIS);
//ustawienie monitora napięcia na 2,2V
Rfm_xmit(BOD_CLK|CLK_5_00|BOD_2_2);
}
Najpierw oczywiście dokonujemy programowego resetu naszego układu, aby mieć pewność, że nie natkniemy się na jakieś niespodzianki czy pozostałości po poprzednich transmisjach.
Potem przystępujemy do konfiguracji układu, zapisując wartości do rejestrów konfiguracyjnych. Opiszę tu pokrótce, co robią dane polecenia, jednak do pełnego ich zrozumienia konieczna jest lektura noty katalogowej:
- Ustawiamy częstotliwość pracy układu (musi być zgodna z oznaczeniem pasma na układzie: 433/868/915MHz) oraz inne parametry analogowe. Włączamy także bufor odbiorczy danych.
- Włączamy oscylator i wyłączamy wyjście zegarowe z układu (w celu zmniejszenia zakłóceń).
- Ustawiamy częstotliwość nośną (czyli częstotliwość, na jakiej będzie pracował układ) – nadajnik i odbiornik muszą mieć ustawioną oczywiście tę samą wartość. Jeśli chcemy używać równolegle kilku linii komunikacyjnych, opartych na tych układach, to możemy kolejnemu systemowi ustawić inną częstotliwość. W komentarzu podałem zakres częstotliwości dla modułu 868MHz i skok, z jakim możemy je ustawiać – pamiętajmy jednak, że stosując dwa systemy pracujące na zbliżonych częstotliwościach, narażamy się na zakłócenia.
- Ustawiamy prędkość transmisji – zasadniczo im wyższa prędkość, tym szybciej dane zostaną przesłane, jednak jednocześnie zwiększa się wtedy wpływ zakłóceń.
- Konfigurujemy parametry odbiornika – poziom sygnału, na jaki będzie reagował oraz rozpiętość zakresu częstotliwości, które będzie akceptował.
- Aktywujemy cyfrowe dekodowanie danych.
- Ustawiamy generowanie przerwania po odebraniu 8 bitów danych (wykorzystamy tę funkcjonalność w kolejnej części naszych zmagań) oraz ustawiamy wykorzystanie 2 bajtów synchronizacyjnych. Teraz do synchronizacji będziemy musieli przesłać 5 bajtów, 4 o stałych wartościach: 0xAA 0xAA 0xAA 0x2D oraz piąty, którego wartość będziemy potem definiować. Dzięki temu odbiór danych będzie rozpoczynany tylko po otrzymaniu tej sekwencji, a dodatkowy definiowany bajt możemy wykorzystać jako adres odbiorczy naszego układu.
- Konfigurujemy automatyczny kontroler częstotliwości.
- Ustawiamy maksymalną moc nadajnika i parametry modulacji.
- Konfigurujemy pętlę PLL, powielającą częstotliwość z rezonatora.
- Wyłączamy timer do wybudzania układu z drzemki, a także tryb oszczędzania energii.
- Ustawiamy wykrywanie zaniku zasilania na poziom 2,2V.
Ponadto przygotujmy jeszcze jedną funkcję, która podczas nadawania i odbierania umożliwi sprawdzenie, czy układ jest gotowy do zapisania kolejnego bajtu do nadania lub czy odebrany został już cały bajt i można go odczytać z bufora układu.
uint8_t Rfm_ready_wait(void){
uint8_t i=0;
CS_PORT &= ~(1<<CS_RFM);//załączam pin CS układu
_delay_us(1);//czekam nieco aby układ mógł zareagować
while(!((1<<SPI_MISO)&SPI_PIN)){//następnie co 1ms sprawdzam, czy układ jest wolny, tzn, czy wystawił na linii MISO 1.
_delay_ms(1);
if((++i)==200){
return 1;//po ok. 200ms przerywam oczekiwanie i zwracam 1 - czyli sygnalizuję błąd
}
}
return 0;//jeśli pętla zostanie przerwana z powodu wystąpienia stanu wysokiego na linii MISO to zwracam 0 - nie ma błędu
}
Funkcja ta na początku aktywuje układ RFM12B, a następnie oczekuje na wystąpienie stanu wysokiego na linii MISO – w ten sposób RFM sygnalizuje gotowość.
Ponadto, prezentowana funkcja nie będzie oczekiwała w nieskończoność. Jeśli układ RFM nie da sygnału o gotowości w przeciągu 200ms (gdyż np. nie odbierze w tym czasie żadnych danych, bo nikt do niego nie nadaje), funkcja zwróci wartość 1, co oznacza, że w tym czasie układ nie odpowiedział.
Pierwsze odbieranie
Teraz, kiedy wiemy już jak wstępnie skonfigurować moduł radiowy, przyszedł czas na napisanie oprogramowania dla odbiornika i nadajnika. Zacznijmy od tego pierwszego:
Rfm_spi_init();//inicjalizacja magistrali SPI
uart_init(9600);//inicjalizacja USART
sei();//włączamy przerwania do obsługi uart
uart_puts("rnrnRFM12B - RECEIVERrn");//wyświetlamy powitanie
Rfm_init();//inicjalizujemy układ RFM12B
Rfm_xmit(SYNC_PATTERN|0xD4);
//ustawiamy programowalny bajt synchronizacji na wartość 0xD4
//wykorzystamy tę funkcjonalność do adresowania wielu układów
//włączamy odbiornik
Rfm_xmit(POWER|EN_RX|EN_BASEBAND|EN_OSC|DIS_CLKO);
_delay_ms(5);
while(1){
//para komend powodująca w efekcie działania reset synchronizacji odbiornika
Rfm_xmit(FIFO_RST|FIFO_IT_8|HS_RST_DIS);
Rfm_xmit(FIFO_RST|FIFO_IT_8|EN_AFT_SYNC|HS_RST_DIS);
uint8_t timeout=Rfm_ready_wait();//oczekujemy na odebranie przez układ danych
if(timeout){//i w zależności od tego czy układ odpowiedział
//albo wyświetlamy informacje o braku odebranych danych
uart_puts("NO INCOMING DATArn");
}else{
//albo odbieramy dane z bufora
uint8_t data=Rfm_xmit(FIFO_READ);
//i wyświetlamy je
sprintf(bufor,"INCOMING DATA:%drn",data);
uart_puts(bufor);
}
}
Jak widać, program odbiornika jest niezwykle prosty:
- Po inicjalizacji układu ustawiamy wspomniany wcześniej bajt synchronizacji na wartość 0xD4.
- Włączamy tryb odbiornika i układ oscylatora.
- Ww pętli głównej na początku resetujemy synchronizację tak, aby kolejne dane układ zaczął odbierać dopiero po przesłaniu 5 bajtów synchronizacyjnych.
- Teraz musimy poczekać na odpowiedź układu RFM, który poinformuje nas, jeśli odbierze jakieś dane. W przeciwnym wypadku po ok. 200ms program wyświetli komunikat o braku danych.
- Jeśli dane zostaną odebrane, to wówczas odczytujemy 1 bajt z bufora układu RFM (tyle będzie nadawał nadajnik) i wyświetlamy jego wartość.
Nadawanie
Do czego byłby nam przydatny odbiornik, do którego nie miałby kto nadawać! W tym przypadku, w celach demonstracyjnych, oprócz podpiętego układu RFM12B, podłączmy do pinów PB0 i PB1 przyciski zwierające do masy i przyjrzyjmy się poniższemu programowi:
Rfm_spi_init();//inicjalizacja magistrali SPI
Rfm_init();//wstępna konfiguracja układu RFM12B
DDRB &= ~((1<<PB0)|(1<<PB1));//konfiguruję piny PB0-1 jako wejście
PORTB |= (1<<PB0)|(1<<PB1);//i włączam podciąganie
uint8_t data;
while(1){
//sprawdzam przyciski i ustawiam odpowiednie bity w bajcie do nadania
data = 0;
if(!(PINB&(1<<PB0))){
data |= 1;
}
if(!(PINB&(1<<PB1))){
data |= 2;
}
if(data==0)continue;//jeśli nic nie wciśnięto to rozpoczynamy pętlę od początku
//włączamy nadajnik
Rfm_xmit(POWER|EN_TRANSMISSION|EN_SYNTH|EN_OSC|DIS_CLKO);
//nadajemy 3 bajty synchronizacji (0xAA)
//dwa pierwsze są już domyślnie umieszczone w buforze nadawczym po komendzie włączającej nadajnik
Rfm_ready_wait();
Rfm_xmit(TX_WRITE|0xAA);
//następnie kolejny bajt synchrnoizacji (0x2D)
Rfm_ready_wait();
Rfm_xmit(TX_WRITE|0x2D);
Rfm_ready_wait();
//oraz definiowalny bajt synchronizacji (czyli nasz adres)
Rfm_xmit(TX_WRITE|0xD4);
Rfm_ready_wait();
Rfm_xmit(TX_WRITE|data);
Rfm_ready_wait();
//oraz pusty bajt - konieczny by poprawnie zakończyć trnasmisję
Rfm_xmit(TX_WRITE|0xAA);
Rfm_ready_wait();
//następnie czekamy na zakończenie transmisji
uint16_t status;
do
{
status=Rfm_xmit(STATUS_READ);
} while (!(status&M_TX_READY));
//i wyłączamy nadajnik
Rfm_xmit(POWER|DIS_CLKO);
_delay_ms(100);
}
Program po inicjalizacji układu i konfiguracji pinów do obsługi przycisków, sprawdza, czy którykolwiek z przycisków został przyciśnięty. Jeśli tak, to wykonywane są instrukcje obsługi modułu radiowego:
- Włączamy tryb nadawania i oscylator, po czym czekamy chwilę na reakcję układu.
- Każdorazowo czekamy aż układ będzie gotowy do przyjęcia kolejnej porcji danych.
- Wysyłamy 3-krotnie bajt o wartości 0xAA (I część synchronizacji).
- Wysyłamy bajt o wartości 0x2D (II część synchronizacji).
- Wysyłamy bajt o wartości 0xD4 – jest to definiowalny bajt synchronizacji, który my wykorzystamy np. jako adres układu. Już teraz możecie sprawdzić, że zmiana tego bajtu na różne wartości w nadajniku i odbiorniku spowoduje całkowity brak komunikacji.
- Wysyłamy nasze dane – w tym przykładzie jeden bajt.
- Wysyłamy 1 bajt o jakiejkolwiek wartości, aby móc wyłączyć odbiornik w odpowiednim momencie.
- Czekamy, aż ostatnio wpisany bajt (u nas 0xAA) będzie nadawany (zwolni się miejsce w buforze, co zasygnalizuje odpowiedni bit w rejestrze statusu) i wyłączamy nadajnik.
Tym oto sposobem w terminalu podpiętym do układu MASTER (odbiornika) powinniśmy zobaczyć efekt podobny do tego:
Gdzie 1 - oznacza wciśnięcie pierwszego przycisku, 2 – drugiego, a 3 - obu.
W ten sposób wykonaliśmy prosty pilot radiowy, który informuje nas o wciśnięciu przycisków! Posiada on jednak kilka mniej lub bardziej istotnych wad, ale o tym porozmawiamy w kolejnej części – tymczasem możemy pobawić się w zdalne miganie diodami LED, odpowiednio modyfikując przedstawione programy.
« Poprzedni artykuł z seriiNastępny artykuł z serii »
Załączniki
To nie koniec, sprawdź również
Przeczytaj powiązane artykuły oraz aktualnie popularne wpisy lub losuj inny artykuł »
avr, komunikacja, RFM12B, SPI
Trwa ładowanie komentarzy...