További tulajdonságok
Az adó maximális
teljesítménye: 3dBm (2mW)
A vevő maximális
érzékenysége: -97dBm
Adatsebesség:
250Kbps, 1Mbps, 2Mbps
Adatcsomagok
hossza: 1 és 32 byte között
Adat-pipe
száma: 6, azaz egy 6 modulból álló hálózatot lehet készíteni
Maximális
vezérlőfrekvencia: 8MHz
Áramfogyasztás:
Kikapcsolt állapotban 2.5μA, Standby-I üzemmódban 50 μA, Standby-II üzemmódban
330μA
Vezérlés
típusa: SPI
A
regiszterek bankokba vannak csoportosítva, akár a PIC mikrovezérlőknél.
A
küldendő adatokat nem egy kivezetésen kapja, hanem konfigurációs parancsként
(FIFO vermek)
A DIP és SMD változat között annyi a különbség, hogy a DIP tokozatra rá van forrasztva egy 1x8-as tüskesor. Az áramkör 12.8mm széles és 16.8mm hosszú és vastagsága alkatrészestől nem haladja meg a 2mm-t. Az antennának nincs kivezetés, a panelre maratott antenna készen rá van hangolva az RFM modul impedanciájára, ami a vonalvastagságból ítélve nem lehet több 80 ohmnál.
GND -
GrouND: negatív tápfeszültség
VDD -
Voltage Drain Drain: pozitív tápveszültség
CE - Chip Enable: ezzel
lehet bekapcsolni az adást vagy a vételt
CSN - Chip Select Not: ezzel jelezhető,
hogy az SPI interfész figyeljen oda a lábakra érkező adatokra
SCK (SPI ClocK): SPI órajel bemenet a
szoftveres vezérléshez
MOSI - Master Out Slave In: itt fogadja a
konfigurációs parancsokat
MISO - Master In Slave Out: innen lehet leolvasni
a parancsok nyugtáját, a lekérdezések válaszait
A panelon lévő leragasztott
IC az RF73 adóvevő IC-t rejti, a többi ellenállás, tekercs, kondenzátor,
antenna a hangolására és az IC helyes üzembe helyezésére szolgál, a kristály
pedig az rendszerórajelt adja.
Az RF73 tartalmaz egy beépített
időosztásos duplexszel működő RF adóvevőt, mely jelei frekvenciában vannak
modulálva. A küldendő jelek modulálás előtt még átmennek egy Gauss szűrőn, ami
csökkenti a jel spektrális szélességét. Tehát a modulátorba érkező jelek nem
bitek lesznek, hanem a Gauss függvényhez hasonlító impulzusok (nullából nem
ugrik fel hirtelen a jelszint a tápfeszültségre, hanem csak fokozatosan és
ezáltal keskenyebb impulzusok alakulnak ki, melyek spektruma is sokkal kisebb
tartományban ingadozik). A vett adatok demodulálása után a „Data Slicer”
szétválasztja a csomagokat, majd a „Packet Processing” feldolgozza a fejléceket
és a tiszta adatot bepakolja az Rx FIFO-ba. A regiszterek, melyek a
beállítások, állapotok, küldendő/fogadott adatok memorizálására szolgálnak,
bankokra vannak osztva, hogy a memória minél hatékonyabban ki legyen használva.
Olcsóbb és egyszerűbb megoldás a gyártó szempontjából, minthogy további
címbuszokat használjon (hiszen csak a Bank0 bankkal kell dolgozni, a Bank1-et
csak egyszer, a bekapcsoláskor való beállításnál vesszük igénybe). Az SPI
interfész arra szolgál hogy a regiszterekbe be és ki lehessen tologatni
(clockkolni) a biteket.
Működés
Három alapvető passzív üzemmód van:
- Power
Down: mikor a modul sem adni sem venni nem képes, de nyitva tartja az SPI
interfészt hogy lekérdezhetőek legyenek az állapotregiszterek és fel lehessen
ébreszteni ha szükséges.
- Standby-I:
mikor a modul befejezte az adást vagy a vételt ebbe az üzemmódba kapcsol, hogy
csökkentse a fogyasztást
- Standby-II:
mikor adó módban az adatok már elhagyták a modul antennáját, de már töltődik be
az újabb adag küldendő információ.
Az adó és vevő aktív üzemmódok beállítása az adatlap
alapján rengeteg féleképpen történhet:
- A vevő nyugtázhatja vagy nem a vett információt
- Az adó újraküldheti az adatokat, ha nem kapott nyugtát
(max 15-ször). Beállítható, hogy nyugta nélkül is újraküldje a csomagokat
néhányszor.
- Ha az RX verem megtelt, de újabb adat jön, ürítse ki a
vermet hogy fogadhassa azt
- A vett adatok címei változtathatóak 3,4,5 bájt
hosszúságig. Ha minden pipe más címet kap, akkor a vevő képes 6 különböző
adótól kapott információt külön-külön tárolni. Hogy a vevő a megfelelő adónak
küldje vissza a nyugtát, a neki lefoglalt vételi címet adási címként használja,
éppen ezért kötelező, hogy a nyugtát váró adó Rx címe is találjon ezzel. Az
adók és a vevő nyilván ugyanazon a frekvencián működnek és a sok adó jele
zavarhatja egymást. Ennek kiküszöbölésére szolgál az automatikus újraküldés
késésének állíthatósága. Ha minden adónál más ez az érték, akkor különböző
intervallumokban fognak adni és a vevő tisztán veheti mindeniket. Csupán
bekapcsoláskor fog mindenik egyszerre sugározni. A vevő egyszerre 3 adó
nyugtáját képes eltárolni (Az Rx és a Tx FIFO verem is 3 szintű).
- A csomag fejlécében szerepelhet a csomag hosszúsága
(dinamikus), a csomagazonosító (új csomag vagy újraküldött, és ha újraküldött
akkor hányadik) és a nyugtázást kérő flag.
- A csomaghosszúság lehet statikus és dinamikus is minden
pipe-nak külön külön. A fejléc hozzáfűzése a csomaghoz az adónál és annak
feldolgozása a vevőnél automatikusan történik.
- Engedélyezni lehet a hibakeresést (CRC), ami az
adatlapban megadott polinomot alkalmazza a csomag címére, az eredmény hossza 1
vagy 2 byte lehet.
- A frekvenciasávot 1MHz-es felbontással állíthatjuk
2400MHz-től 2483.5MHz-ig
- Az adó teljesítménye és a vevő érzékenysége állítható
Forráskód
A HopeRF honlapjáról letölthető a forráskód, ami egy egyszerű adás-vételt valósít meg két modul között. A forráskód
PIC-nek volt szánva, ezért átírtam, hogy használható legyen AVR-el.
Az fenti kapcsolás és az
alábbi forráskód adónak és vevőnek is egyaránt jó. A main() függvényben
kommentbe kell tenni a nem használt Send() vagy Receive() függvényt. A program
a lehető legegyszerűbb beállításokat használja (nincs nyugtázás, nincs CRC,
egyetlen adat-pipe és nincs újraküldés) valamint egy előre definiált
byte-sorozatot ad vagy vesz újra meg újra. Az adónak beállított modulon a piros
LED jelzi az adást, a vevőnek beállított modulon pedig a zöld LED jelzi a
vételt.
#define F_CPU 1000000UL //az AVR rendszerórajel frekvenciája
#include <util/delay.h>
#include <avr/pgmspace.h>
#define UINT8 unsigned char
#define UINT32 unsigned long
#define MAX_PACKET_LEN 32 //legfeljebb 32Byte payload a FIFO-ban
#define RED_LED PB5 //Adást jelzõ LED
#define GREEN_LED PB4 //Vételt jelzõ LED
#define CE PA6 //Chip Enable: a chip adjon-e vagy vegyen
#define CSN PA5 //Chip Select Not: az SPI figyeljen-e a parancsokra
#define SCK PA3 //SPI ClocK: órajel a hardveres vezérléshez
#define MISO PA1 //Master In Slave Out: lekérdezés
#define MOSI PA2 //Master Out Slave In: parancsok
#define RED_LED_OUT() DDRB |= (1<<RED_LED) //adás LED kimenet
#define HI_RED_LED() PORTB|= (1<<RED_LED)
#define LOW_RED_LED() PORTB&=~(1<<RED_LED)
#define GREEN_LED_OUT() DDRB |= (1<<GREEN_LED) //vétel LED kimenet
#define HI_GREEN_LED() PORTB|= (1<<GREEN_LED)
#define LOW_GREEN_LED() PORTB&=~(1<<GREEN_LED)
#define CE_OUT() DDRA |= (1<<CE) //CE kimenet
#define HI_CE() PORTA|= (1<<CE)
#define LOW_CE() PORTA&=~(1<<CE)
#define CSN_OUT() DDRA |= (1<<CSN) //CSN kimenet
#define HI_CSN() PORTA|= (1<<CSN)
#define LOW_CSN() PORTA&=~(1<<CSN)
#define SCK_OUT() DDRA |= (1<<SCK) //vezérlő órajel kimenet
#define HI_SCK() PORTA|= (1<<SCK)
#define LOW_SCK() PORTA&=~(1<<SCK)
#define MISO_IN() DDRA &= ~(1<<MISO) //lekérdezés bemenet
#define MISO_HI() PINA&(1<<MISO)
#define MOSI_OUT() DDRA |= (1<<MOSI) //parancs kimenet
#define HI_MOSI() PORTA|= (1<<MOSI)
#define LOW_MOSI() PORTA&=~(1<<MOSI)
// fontosabb parancsok
#define READ_REG 0x00 //regiszterbõl olvas: 001xxxxx, ahol x=cím
#define WRITE_REG 0x20 //regiszterbe ír: 001xxxxx, ahol x=cím
#define RD_RX_PLOAD 0x61 //kiolvas 32B adatot az Rx FIFO-ból
#define FLUSH_TX 0xE1 //kiüríti Tx FIFO-t
#define FLUSH_RX 0xE2 //kiüríti Rx FIFO-t
#define W_TX_PAYLOAD_NOACK_CMD 0xb0 //kikapcsolja a nyugtázást
#define ACTIVATE_CMD 0x50 //a feature regisztereket ki/be kapcsolja
#define R_RX_PL_WID_CMD 0x60 //lekérdezi az Rx FIFO hosszát: 01100000
// fontosabb regiszter címek
#define CONFIG 0x00 //CONFIG regiszter címe (Bank0)
#define STATUS 0x07 //STATUS regiszter címe (Bank0)
#define FIFO_STATUS 0x17 //FIFO_STATUS regiszter címe (Bank0)
#define FEATURE 0x1D //FEATURE regiszter címe (Bank0)
//fontosabb állapot értékek
#define STATUS_RX_DR 0x40 //ha a STATUS regiszterben az RX_DR bit=1
#define FIFO_STATUS_TX_FULL 0x20 //ha a FIFO_STATUS regiszterben a TX_FULL=1
#define FIFO_STATUS_RX_EMPTY 0x01 //ha a FIFO_STATUS regiszterben az RX_EMPTY=1
const UINT32 Bank1_Reg0_13[]={ //Bank1-ben az értékek sorrendje: MSB byte -> LSB byte
0xE2014B40, //00 = 40.4B.01.E2 - kötelezõ érték
0x00004BC0, //01 = C0.4B.00.00 - kötelezõ érték
0x028CFCD0, //02 = D0.FC.8C.02 - kötelezõ érték
0x41390099, //03 = 99.00.39.41 - kötelezõ érték
0x0B869ED9, //04 = D9.9E.86.0B - kötelezõ érték
0xA67F0624, //05 = 24.06.7F.A6 - kötelezõ érték
0x00000000, //06 = 00.00.00.00 - lefoglalt
0x00000000, //07 = 00.00.00.00 - lefoglalt
0x63000000, //08 = 00.00.00.63 - csak olvasni lehet (chip ID)
0x00000000, //09 = 00.00.00.00 - lefoglalt
0x00000000, //0A = 00.00.00.00 - lefoglalt
0x00000000, //0B = 00.00.00.00 - lefoglalt
0x00127300, //0C = 00.73.12.00 - 120us mód, Dynamic compatible
0x36B48000};//0D = 00.80.B4.36 - kötelezõ érték
const UINT8 Bank1_Reg14[]={ //FF.EF.7D.F2.08.08.20.82.04.10.41 - kötelezõ érték
0x41,0x10,0x04,0x82,0x20,0x08,0x08,0xF2,0x7D,0xEF,0xFF};
const UINT8 Bank0_Reg[][2] PROGMEM={ //Bank0-ban az értékek sorrendje: LSB byte -> MSB byte
{0,0x03}, //00-CONFIG: 00000011 = PRX, bekapcs, nincs CRC
{1,0x00}, //01-EN_AA: 00000000 = nem nyugtáz semmit sem
{2,0x01}, //02-EN_RXADDR: 00000001 = csak az adatpipe0 címet használjuk
{3,0x03}, //03-SETUP_AW: 00000011 = 5 byte cimhossz
{4,0x00}, //04-SETUP_RETR:00000000 = újraküldés kikapcs
{5,0x00}, //05-RF_CH: 00000000 = 2400+0=2400MHz
{6,0x07}, //06-RF_SETUP: 00000111 = 1Mbps; 5dBm sugárzás; magas nyereség
{7,0x00}, //07-STATUS: 00000000 = csak olvasni lehet
{28,0x3F}, //1C-DYNPD: 00111111 = dinamikus payload mindenik pipe-nak
{29,0x07}};//1D-FEATURE: 00000111 = dinamikus payload hossz bekapcs; Payload nyugtával és anélkül
const UINT8 RX0_Address[]={0xE7,0xE7,0xE7,0xE7,0xE7};//0A - pipe0 vételi címei és a Tx adási címei
void Initialize(void);
void Send(void);
void Receive(void);
void RFM73_Initialize(void);
void SwitchToTxMode(void);
void SwitchToRxMode(void);
UINT8 SPI_RW(UINT8 value);
void SPI_Write_Reg(UINT8 reg, UINT8 value);
UINT8 SPI_Read_Reg(UINT8 reg);
void SPI_Read_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length);
void SPI_Write_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length);
void SwitchCFG(char _cfg);
const UINT8 tx_buf[17] PROGMEM={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x78}; //küldendõ adat, az utolsó byte az ellenörzõösszeg
UINT8 rx_buf[MAX_PACKET_LEN];
//********************************************************************************************************
int main(void)
{
_delay_ms(1000); //bekapcsolási késés 1mp
Initialize(); //portok, regiszterek inicializálása
while(1)
{
Send();
//Receive();
}
}
//--------------------------------------------------------------------------------------------------------
void Initialize(void) //inicializáló függvény
{
CE_OUT(); //adás/vétel inicializáló kimenet
CSN_OUT(); //SPI inicializáló kimenet
SCK_OUT(); //órajel kimenet
MISO_IN(); //nyugta bemenet
MOSI_OUT(); //parancs kimenet
RED_LED_OUT(); //adó LED kimenet
GREEN_LED_OUT(); //vevõ LED kimenet
LOW_CE(); //nincs se adás se vétel
HI_CSN(); //nincs SPI kommunikáció
LOW_SCK(); //nincs órajel
LOW_MOSI(); //nincs parancs
LOW_RED_LED(); //adó LEd kikapcs
LOW_GREEN_LED(); //vevõ LED kikapcs
RFM73_Initialize(); //adatbankok feltöltése, vevõ üzemmód
}
//--------------------------------------------------------------------------------------------------------
void Send(void)
//adó függvény
{
UINT8 i,fifo_sta;
UINT8 temp_buf[32];
for(i=0;i<17;i++)
temp_buf[i]=pgm_read_byte(&tx_buf[i]);
//a küldendõ 17 byte eltárolása
SwitchToTxMode(); //adó
üzemmód
fifo_sta=SPI_Read_Reg(FIFO_STATUS); //FIFO állapotának
lekérdezése
if((fifo_sta&FIFO_STATUS_TX_FULL)==0) //ha van még hely a TX_FIFO-ban
{
HI_RED_LED(); //akkor
bkapcsol a piros LED 30 miliszekundumig
SPI_Write_Buf(W_TX_PAYLOAD_NOACK_CMD,
temp_buf, 17); //adatok FIFO-ba írása
_delay_ms(30);
LOW_RED_LED();
_delay_ms(30);
}
}
//--------------------------------------------------------------------------------------------------------
void Receive(void)
//vevõ függvény
{
UINT8 len,sta,fifo_sta,chksum;
UINT8 rx_buf[MAX_PACKET_LEN];
sta=SPI_Read_Reg(STATUS); //állapotregiszter kiolvasása
if((STATUS_RX_DR&sta)
== STATUS_RX_DR) //ha új adat került a FIFO-ba
{
do
{
len=SPI_Read_Reg(R_RX_PL_WID_CMD); //csomaghossz
lekérdezése
if(len<=MAX_PACKET_LEN) //ha
a csomag mérete megfelelõ
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,len);
//akkor a FIFO kiolvasása
else
SPI_Write_Reg(FLUSH_RX,0); //különben a
FIFO kiüríése
fifo_sta=SPI_Read_Reg(FIFO_STATUS); //maradt-e még a
FIFO-ban valami
}while((fifo_sta&FIFO_STATUS_RX_EMPTY)==0);
//ismételd míg üres nem lesz
chksum =
rx_buf[0]+rx_buf[1]+rx_buf[2]+rx_buf[3]+rx_buf[4]+rx_buf[5]+rx_buf[6]+
+rx_buf[7]+rx_buf[8]+rx_buf[9]+rx_buf[10]+rx_buf[11]+rx_buf[12]+rx_buf[13]+
+rx_buf[14]+rx_buf[15]; //ellenörzõösszeg kiszámítása
if(chksum==rx_buf[16]&&rx_buf[0]==0x30)
//ha az ellenörzõösszeg és az elsõ byte stimmel
{
HI_GREEN_LED();//akkor bekapcsolja a zöld LEDet
_delay_ms(30);
LOW_GREEN_LED();
_delay_ms(30);
}
SwitchToRxMode(); //adó üzemmód és egyben a FIFO kiürítése
}
SPI_Write_Reg(WRITE_REG|STATUS,sta);//RX_DR,TX_DS,MAX_RT megszakításjelzõ bitek kikapcs
}
//--------------------------------------------------------------------------------------------------------
UINT8 SPI_RW(UINT8 value) //parancsadó
és választ fogadó függvény
{
UINT8 bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) //a
"value" bitenkénti átjárása
{ //mindig a MSB bitet adjuk
if(value
& 0x80) HI_MOSI(); else LOW_MOSI(); //parancs bitek
value = (value << 1); //következõ
bit betolása a MSB-be
HI_SCK(); //órajel
félciklus
if(MISO_HI())
value |= 0x01; //a visszajelzõ bitek betöltése "value"-ba
LOW_SCK(); //órajel félciklus
}
return(value); //a visszajelzés
visszatérítése
}
//--------------------------------------------------------------------------------------------------------
void SPI_Write_Reg(UINT8 reg, UINT8
value) //"reg" címû regiszterbe írja a
"value"-t
{ //az írás
sorrendje: parancs(regisztercím) és parancs(érték)
LOW_CSN(); //az SPI
parancs elején a CSN alacsony kell legyen
SPI_RW(reg); //regiszter
kiválasztása
SPI_RW(value); //az érték
beleírása
HI_CSN(); //az SPI
parancs magas CSN-el zárul
}
//--------------------------------------------------------------------------------------------------------
UINT8 SPI_Read_Reg(UINT8 reg) //kiolvassa
"reg" regiszter tartalmát és visszatéríti
{
UINT8 value;
LOW_CSN(); //SPI
parancs eleje
SPI_RW(reg); //regiszter
kiválasztása
value = SPI_RW(READ_REG); //az érték
kiolvasása
HI_CSN(); //SPI
parancs vége
return(value); //a kiolvasott
érték visszatérítése
}
//--------------------------------------------------------------------------------------------------------
void SPI_Read_Buf(UINT8 reg, UINT8 *pBuf,
UINT8 length)
{ //"reg"
regiszterbõl kiolvassa a "length" hosszúságú "pBuf" tömböt
UINT8 byte_ctr;
LOW_CSN(); //SPI
parancs eleje
SPI_RW(reg); //regiszter
kiválasztása
for(byte_ctr=0;byte_ctr<length;byte_ctr++)
//a tömb minden eleme egy-egy byte
pBuf[byte_ctr] =
SPI_RW(READ_REG); //az érték kiolvasása
HI_CSN(); //SPI
parancs vége
}
//--------------------------------------------------------------------------------------------------------
void SPI_Write_Buf(UINT8 reg, UINT8
*pBuf, UINT8 length)
{ //"reg"
regiszterbe beleírja a "length" hosszúságú "pBuf" tömböt
UINT8 byte_ctr;
LOW_CSN(); //SPI
parancs eleje
SPI_RW(reg); //regiszter
kiválasztása
for(byte_ctr=0;
byte_ctr<length; byte_ctr++) //a tömb minden eleme
egy-egy byte
SPI_RW(*pBuf++); //az érték
beleírása
HI_CSN(); //SPI
parancs vége
}
//--------------------------------------------------------------------------------------------------------
void
SwitchToRxMode() //átvált Rx üzemmódba (PRIM_RX=1 és
CE=1)
{
UINT8 value;
SPI_Write_Reg(FLUSH_RX,0); //Rx FIFO
kiürítése
LOW_CE(); //standby-I üzemmód
value=SPI_Read_Reg(CONFIG); //a konfigurációs
bitek
value=value|0x01; //melyek közül az elsõt 1-re
állítjuk (PRX üzemmód)
SPI_Write_Reg(WRITE_REG
| CONFIG, value); //a megváltoztatott érték
visszatöltése
HI_CE(); //CE=1
}
//--------------------------------------------------------------------------------------------------------
void
SwitchToTxMode() //átvált Tx üzemmódba (PRIM_RX=0 és
CE=1)
{
UINT8 value;
SPI_Write_Reg(FLUSH_TX,0); //Tx FIFO kiürítése
LOW_CE(); //standby-I üzemmód
value=SPI_Read_Reg(CONFIG); //a konfigurációs
bitek
value=value&0xfe; //melyek
közül az elsõt 0-ra állítjuk (PTX üzemmód)
SPI_Write_Reg(WRITE_REG
| CONFIG, value); //a megváltoztatott érték
visszatöltése
HI_CE(); //CE=1
}
//--------------------------------------------------------------------------------------------------------
void SwitchCFG(char _cfg) //váltogatás a
bankok között: 1=Bank1 0=Bank0
{
UINT8 Tmp;
Tmp=SPI_Read_Reg(STATUS); //állapotregiszter
bitjei
Tmp=Tmp&0x80; //melyek közül a
hetedik (MSB) jelzi a bankot
if( (
(Tmp)&&(_cfg==0) )||( ((Tmp)==0)&&(_cfg) ) ) //ha nem ugyanarra történik a váltás
SPI_Write_Reg(ACTIVATE_CMD,0x53); //akkor váltson át a másikra
}
//--------------------------------------------------------------------------------------------------------
void RFM73_Initialize()
{
UINT8 i,j;
UINT8
WriteArr[12];
_delay_ms(100);
SwitchCFG(0); //-----------------------------Bank0-----------------------------------------
for(i=0;i<8;i++)
// a Bank0_Reg tömb elsõ 8 elemének betöltése a
Bank0-ba
SPI_Write_Reg((WRITE_REG|pgm_read_byte(&Bank0_Reg[i][0])),pgm_read_byte(&Bank0_Reg[i][1]));
for(j=0;j<5;j++)
//Bank0 0A regisztere: az 5 byte-os pipe0 címe
WriteArr[j]=RX0_Address[j];
SPI_Write_Buf((WRITE_REG|10),&(WriteArr[0]),5);
for(j=0;j<5;j++)
//Bank0 10 regisztere: a Tx cím ugyanaz kell legyen
mint a pipe0 vételi címe
WriteArr[j]=RX0_Address[j];
SPI_Write_Buf((WRITE_REG|16),&(WriteArr[0]),5);
i=SPI_Read_Reg(FEATURE);//a FEATURE regisztert kiolvasva
if(i==0) //ha mindenik bitje
0, akkor nem volt aktiválva
SPI_Write_Reg(ACTIVATE_CMD,0x73); //és
aktiválni kell
for(i=9;i>=8;i--)
//a FEATURE aktiválása után betöltjük az értékeket
SPI_Write_Reg((WRITE_REG|pgm_read_byte(&Bank0_Reg[i][0])),pgm_read_byte(&Bank0_Reg[i][1]));
SwitchCFG(1); //-----------------------------Bank1-----------------------------------------
for(i=0;i<=8;i++)//a Bank1 0-8 regisztereiben a byte-ok fordított sorrendben
vannak (MSB->LSB)
{
for(j=0;j<4;j++)
//4 byte-os regiszterek vannak a Bank1-ben
WriteArr[j]=Bank1_Reg0_13[i]>>(8*(j));
SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}
for(i=9;i<=13;i++)//a Bank1 9-13 regisztereiben a sorrend LSB->MSB
{
for(j=0;j<4;j++)
WriteArr[j]=Bank1_Reg0_13[i]>>(8*(3-j));
SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}
for(j=0;j<11;j++)
//Bank1 0E regisztere 11 byte hosszú
WriteArr[j]=Bank1_Reg14[j];
SPI_Write_Buf((WRITE_REG|0x0E),&(WriteArr[0]),11);
_delay_ms(50);
SwitchCFG(0);
SwitchToRxMode(); //Alapállás
a vevõ üemmód
}
A C programozási
nyelvben használt #define direktívákkal érthetőbbé tehető az AVR lábainak neve
valamint a rájuk küldött parancsok értéke. Az eredeti forráskódban minden
használható címet, értéket, parancsot definiáltak, én azonban csak a
létfontosságúakat hagytam meg. A bank1 regisztereit kötelezően be kell állítani,
a bank0-ban lévők közül viszont elég azokat, melyek menet közben módosulnak is.
RFM73_Initialize: ez tölti be a tömbökben tárolt beállításokat a regiszterekbe. Egyes
regiszterek hosszúsága több Byte hosszú is lehet, Bank1 regisztereinek értékeit pedig fordított
Byte sorrendben kell betologatni. A beállítások elvégeztével a függvény
visszavált Bank0-ra és beáll vevő üzemmódba.
SwitchCFG: a bankok közti átváltást
valósítja meg. Hogy épp melyik bank aktív, az a STATUS regiszter hetedik
bitjében szerepel. Ha nem ugyanaz amire váltani szeretnénk akkor átvált a másikra.
SwitchToTxMode: átvált adó üzemmódra
átírván a CONFIG regiszter legelső bitjét.
SwitchToRxMode: átvált vevő üzemmódra
átírván a CONFIG regiszter legelső bitjét.
SPI_Write_Buf: beleírja a paraméternek
megadott tömböt (buffert) a paraméternek megadott regiszterbe. A Tx FIFO
feltöltésére jó.
SPI_Read_Buf: kiolvassa a paraméternek
megadott regiszterből az értékeket a paraméternek megadott tömbbe (bufferbe).
Az Rx FIFO kiolvasására jó.
SPI_Write_Reg: beírja a paraméternek megadott regiszterbe a
paraméternek megadott értéket.
SPI_Read_Reg: kiolvassa a paraméternek megadott regiszter
tartalmát és visszatéríti azt.
SPI_RW: az SPI kommunikációt megvalósító
függvény. A MOSI lábra tolja a paraméternek megadott parancsot (ami lehet
olvasó parancs is) és közben elmenti a MISO lábról érkezett biteket, majd
visszatéríti őket.
Receive: a vevő
függvény, mely ellenőrzi, hogy került-e új adat a FIFO-ba. Mivel a csomag
hossza dinamikus (hogy kisebb tömbököt is lehessen a Tx FIFO-ba rakni a Send
függvényben), leellenőrzi, hogy nem-e hoszabb a maximális 32 byte-nál (a
fejlécben van ez az információ). Ha a hossza megfelelő akkor belerakja a vett
értékeket egy helyi változóba és mindezt addig ismétli míg az üres FIFO-t jelző
flag be nem kapcsol. Ezután összeadja a tömb értékeit és megnézi, hogy talál-e
az ellenőrző összeggel (az utolsó értékkel). Itt sajnos elemenként kellett
összeadni mert for ciklussal nem működött megfelelően. Ha az értékek találnak
(és az első érték is jó) akkor 30 miliszekundumig felgyúl a zöld LED. Ezek után
a FIFO-t ki kell üríteni, és itt a vevő üzemmódra kapcsolás a legalkalmasabb. A végén kiolvasott állapotérték
újbóli visszaírása arra jó, hogy a rádiómodulnak „nyugtázzuk” a feladat
végeztét.
Send: az adó függvény, mely elküldi a tx_buf
tömbben tárolt értékeket a Tx FIFO-nak. Előbb helyi változóba kimenti az
értékeket (optimálisabb helyi változókkal dolgozni mint globálisokkal) majd
átvált adó üzemmódba. Ha a FIFO telítetsségét jelző bit nincs bekapcsolva akkor
meg lehet pakolni a FIFO-t. Ezt a 30 miliszekundumig világító piros LED jelzi.
Mivel az Attiny26 adatmemóriálya igen
csekély és a regiszterek hatalmasak, a feltöltésükre szánt adatok nem férnek
el az AVR adatmemóriájában. Szerencsére az avr/pgmspace.h header segítségével
alkalmazható a PROGMEM attribútum, melynek segítségével a programmemóriában is
tárolhatóak az adatok. A PROGMEM-el tárolt adatok a pgm_read_byte(&adat)
függvénnyel olvashatók ki.