Jiří Dvořák, Libor Boleček
xdvora87stud.feec.vutbr.cz,
xbolec01
stud.feec.vutbr.cz
Cílem tohoto projektu je sestavení komunikace dvou mikrokontrolérů ATMega16, využívající bezdrátové digitální moduly RFM12B/868D v pásmu ISM. Výchozím vodítkem pro napsání programu je ukázkový kód zveřejněný výrobcem v datasheetu modulu. Jeden modul bude naprogramován do přijímacího módu a druhý modul bude v módu vysílacím. Komunikace modulů s mikrokontolérem probíhá přes rozhraní SPI. Moduly jsou vhodné pro dálkové řízení, přenos dat ze senzorů, zabezpečovací systémy aj.
Modul RFM12B/868D komunikuje na frekvenci 868MHz. Rozsah pracovních napětí je 2,2V až 3,8V. Udávaná citlivost -102dBm, max. výkon 7dBm. Ostatní parametry možno najít v [1]. Základní piny modulu jsou VDD (kladný pól napájení), GND (zem), SDI (vstup data SPI), SDO (výstup data SPI), SCK (hodiny SPI), NSEL (chip select funkční jako povolovací pin v nízké úrovni), NIRQ (požadavek přerušení) Ostatní piny možno najít v [1]. Pouzdro modulu má piny vyvedené na kolíkovou lištu s nestandardní roztečí 2mm viz obr.1. Lišty pro připojení externích modulů na vývojové desce v laboratoři mají dutinky ve dvou řadách s roztečí 2,54mm. Prvním úkolem tedy bylo vyrobit pinovou redukci pro připojení na vývojovou desku.
Obr.1: Pouzdro modulu převzato z [1].
Zároveň však bylo nutné doplnit redukci o usměrňovač na potřebných 3,8V pro provoz modulu a zajistit stejné napětí na vstupních a výstupních pinech předřadnými odpory. Schéma zapojení redukce je na obr.2 a předlohy pro oboustanou desku plošných spojů (měřítko 1:1) na obr.3.
Obr.3: Schéma regukce.
Obr.3: Předlohy pro desku plošných spojů (top a bottom) zrcadlově 1:1.
Vyhotovené redukce, osazené moduly a připravené pro zapojení do vývojové desky jsou na obr.4.
Obr.3: Předlohy pro desku plošných spojů (top a bottom) zrcadlově 1:1.
Redukce se připojuje do spodní části patice portu B na vývojové desce. Po zastrčení do desky je realizování propojení VDI, GND, SCK, SDO, SDI a NSEL. Jednotlivé funkční piny jsou pro modul RFM12B a ATMega16 popsány rozdílně. Schéma propojení je na obr.4. Propojení je tedy chápáno následovně:
Obr.3: Propojení s portem B vývojové desky (zastrčení) a propojení s portem D (drátově)
Zastrčením redukce do patice pro port B na vývojové desce a nadrátováním přerušení NIRQ na pin2 portu D tak vznikne potřebné zapojení.
Základní kód, ze kterého byl odvozen námi použitý kód je k nalezení v [1]. Tento kód dodávaný výrobcem však obsahoval chyby, které musely být odhaleny.
KÓD VYSÍLAČE
#include#include ".\avr\interrupt.h" /* makra pro praci s SPI rozhrani */ #define SCK 7 /*SPI clock*/ #define SDO 5 /*SPI data vystup*/ #define SDI 6 /*SPI data vstup*/ #define CS 4 /*SPI chip select*/ #define NIRQ 2 /* vstupne-vystupni rizeni */ #define HI(x) PORTB |= (1<<(x)) /*nastaveni bitu x portu B do log. urovne 1*/ #define LO(x) PORTB &= ~(1<<(x)) /*nastaveni bitu x portu B do log. urovne 0*/ #define WAIT_NIRQ_LOW() while(PIND & (1<<NIRQ)) /*kontrola preruseni na INT0*/ /* LED */ #define LED 6 #define LED_ON() PORTD &= ~(1<<LED) /*rozsviceni LED na bitu 6 portu D pomoci log. urovne 0*/ #define LED_OFF() PORTD |= (1<<LED) /*zhasnuti LED na bitu 6 portu D pomoci log. urovne 1*/ /* standardni inicializace portu pro SPI */ void portInit() { HI(CS); HI(SDI); LO(SCK); DDRB = (1<<CS) | (1<<SDI) | (1<<SCK); /*definovani prislušných pinů portu B jako vystupnich*/ DDRD = (1<<LED); } /* SPI posilani 16-bitoveho cmd */ unsigned int writeCmd(unsigned int cmd) { unsigned char i; unsigned int recv; recv = 0; LO(SCK); /*CLK v urovni low*/ LO(CS); /*CHIP SELECT v urovni low = aktivace obvodu vysilace na SPI*/ for(i=0; i<16; i++) { /*smycka pro zasilani 16-bit dat*/ if(cmd&0x8000) HI(SDI); else LO(SDI); HI(SCK); /*CLK v urvni high = puls hodin*/ recv<<=1; if( PINB&(1<<SDO) ) { recv|=0x0001; } LO(SCK); /*CLK v urovni low = ukonceni pulsu*/ cmd<<=1; /*posuv na dalsi bit dat*/ } HI(CS); /*CHIP SELECT v urovni high = deaktivace obvodu vysilace na SPI - ukonceni komunikace*/ return recv; } /*inicializace modulu vysilace dle manualu*/ void rfInit() { writeCmd(0x80E7); //EL,EF,868band,12.0pF writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC writeCmd(0xA640); //frequency select writeCmd(0xC647); //4.8kbps writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR writeCmd(0xCED4); //SYNC=2DD4 , AG writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN writeCmd(0x9850); //!mp,90kHz,MAX OUT writeCmd(0xCC17); //OB1 , ACOB0, LPX,Iddy,CDDIT,CBW0 writeCmd(0xE000); //NOT USED writeCmd(0xC800); //NOT USED writeCmd(0xC040); //1.66MHz,2.2V } /*fce zaslani dat vysilaci*/ void rfSend(unsigned char data) { while(PIND & (1<<NIRQ)) writeCmd(0xB800 + data); char lcd_vystup[16]; lcd_init(); /*inicializace displeje*/ lcd_clrscr(); /*vymazani displeje*/ sprintf(lcd_vystup,"%d",data); /*formatovani pro displej*/ lcd_puts(lcd_vystup); /*vystup na displej*/ } int main() { volatile unsigned int i,j; asm("cli"); for(i=0;i<1000;i++)for(j=0;j<123;j++); /*startovaci prodleva*/ portInit(); /*inicializace portu*/ rfInit(); /*inicializace vysilace*/ while(1) { LED_OFF(); /*vypnuti LED*/ writeCmd(0x0000); /*vycteni status registru*/ rfSend(0xAA); /*zaslani hlavicky zpravy - dle datasheetu*/ rfSend(0xAA); rfSend(0xAA); rfSend(0x2D); /*synchronizace*/ rfSend(0xD4); for(i=0; i<16; i++) { rfSend(0x30+i); /*vysilana data*/ } rfSend(0xAA); /*3 volitelne byty na zaver*/ rfSend(0xAA); rfSend(0xAA); LED_ON(); /*rozsviceni LED*/ for(i=0; i<10000; i++) for(j=0; j<123; j++); /*prodleva po kazdem vysilani*/ } }
KÓD PŘIJÍMAČE
#include#include ".\avr\interrupt.h" #include "lcd_h.h" /* makra pro praci s SPI rozhrani */ #define SCK 7 /*SPI clock*/ #define SDO 5 /*SPI data vystup*/ #define SDI 6 /*SPI data vstup*/ #define CS 4 /*SPI chip select*/ #define NIRQ 2 /* vstupne-vystupni rizeni */ #define HI(x) PORTB |= (1<<(x)) /*nastaveni bitu x portu B do log. urovne 1*/ #define LO(x) PORTB &= ~(1<<(x)) /*nastaveni bitu x portu B do log. urovne 0*/ #define WAIT_NIRQ_LOW() while(PIND&(1<<NIRQ)) /*kontrola preruseni na INT0*/ /* LED */ #define LED 6 #define LED_ON() PORTD &= ~(1<<LED) /*rozsviceni LED na bitu 6 portu D pomoci log. urovne 0*/ #define LED_OFF() PORTD |= (1<<LED) /*zhasnuti LED na bitu 6 portu D pomoci log. urovne 1*/ #define BAUDRATE 25 /*Baud rate 19200 at 8MHz*/ /*inicalizace RS232*/ void rsInit(unsigned char baud) { UBRRL = baud; /*nastaveni Baud rate dle zadane baud*/ UCSRC = (1<<UCSZ0) | (1<<UCSZ1); /*nastaveni formatu 8bitu data, 1 stop bit*/ UCSRB = (1<<RXEN) | (1<<TXEN); /*povoleni vysilani i prijimani*/ } /*zaslani dat po RS232*/ void rsSend(unsigned char data) { while( !(UCSRA & (1<<UDRE))); UDR = data; /*ulozeni dat do vysilaciho registru RS232*/ } /*cteni dat z RS232*/ unsigned char rsRecv() { while( !(UCSRA & (1<<RXC))); return UDR; /*vycteni dat z prijimaciho registru RS232*/ } /* standardni inicializace portu pro SPI */ void portInit() { HI(CS); HI(SDI); LO(SCK); DDRB = (1<<CS) | (1<<SDI) | (1<<SCK); DDRD = (1<<LED); } /* SPI posilani 16-bitoveho cmd */ unsigned int writeCmd(unsigned int cmd) { unsigned char i; unsigned int recv; recv = 0; LO(SCK); /*CLK v urovni low*/ LO(CS); /*CHIP SELECT v urovni low = aktivace obvodu prijimace na SPI*/ for(i=0; i<16; i++) { /*smycka pro zasilani 16-bit dat*/ if(cmd&0x8000) HI(SDI); else LO(SDI); HI(SCK); /*CLK v urvni high = puls hodin*/ recv<<=1; if( PINB&(1<<SDO) ) { recv|=0x0001; } LO(SCK); /*CLK v urovni low = ukonceni pulsu*/ cmd<<=1; /*posuv na dalsi bit dat*/ } HI(CS); /*CHIP SELECT v urovni high = deaktivace obvodu prijimace na SPI - ukonceni komunikace*/ return recv; } /*inicializace modulu vysilace dle manualu*/ void rfInit() { writeCmd(0x80E7); //EL,EF,868band,12.0pF writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC (bug was here) writeCmd(0xA640); //freq select writeCmd(0xC647); //4.8kbps writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR (FIFO level = 8) writeCmd(0xCED4); //SYNC=2DD4; writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN writeCmd(0x9850); //!mp,90kHz,MAX OUT writeCmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0 writeCmd(0xE000); //NOT USE writeCmd(0xC800); //NOT USE writeCmd(0xC040); //1.66MHz,2.2V } /*prijimani dat prijimacem*/ unsigned char rfRecv() { unsigned int data; while(1) { data = writeCmd(0x0000); /*vycteni status registru prijimace*/ if ( (data&0x8000) ) /*kontrola nastaveni MSB status registru*/ { data = writeCmd(0xB000); /*vycteni dat z fifo*/ return (data&0x00FF); } } } /*reset FIFO zasobniku prijimace dle Datasheetu*/ void FIFOReset() { writeCmd(0xCA81); writeCmd(0xCA83); } int main(void) { unsigned char data, i; char lcd_vystup[16]; portInit(); rfInit(); /*inicializace SPI*/ rsInit(BAUDRATE); /*inicializace RS232*/ FIFOReset(); /*reset FIFO zasobniku prijimace*/ lcd_init(); /*inicializace displeje*/ lcd_clrscr(); /*vymazani displeje*/ while(1) { //waitForData(); LED_ON(); /*rozsviceni LED*/ for (i=0; i<16; i++) /*vycteni prijatych dat polling metodou*/ { data = rfRecv(); sprintf(lcd_vystup,"%d",data); /*formatovani pro displej*/ lcd_puts(lcd_vystup); /*vypis na displej*/ LED_OFF(); /*zhasnuti LED*/ //rsSend(data); } FIFOReset(); /*reset FIFO zasobniku prijimace*/ } return 0; }
Kód by zkomlipován bez chyb a nahrán do mikrokontrolérů. U vysílače jsou na LCD displeji zobrazeny data posílaná do modulu a průběh odesílání je signalizován LED diodou. Nepodařilo se ověřit, zda-li jsou data správně zpracovávány modulem a jsou-li vysílána. U přijímače by se na LCD měla zobrazovat přijatá data, ale k tomu nedochází. Není jisté, zda je funkce přijímače správná a data nejsou vysílána, nebo jsou vysílána, ale přijímač nepracuje správně. Bohužel až pozdě byla objevena stránka s návodem jak modul rozchodit. V oficiální dokumentaci se pravděpodobně vyskytují chyby.
Deska plošných spojů - bottom
Deska plošných spojů - top
Kód přijímače
Kód vysílče
[1] HOPE RF. Universal ISM band FSK tranciever modula RFM12b [online]. [citováno 20.5.2009]. Dostupný z WWW: <http://zefiryn.tme.pl/dok/wd1/rfm12b.pdf>
[2] RFM12b and AVR - quick start [online]. [citováno 20.5.2009]. Dostupný z WWW:
<http://zenburn.net/~goroux/rfm12b/rfm12b_and_avr-%20quick_start.pdf>