Choď na obsah Choď na menu
 

RFM moduly

http://www.kubanec.borec.cz/?stranka=rfm_moduly

 

 

RFM modulky

Možná jste se už někdy setkali s modulkama RFM12B, jsou to bezdrátové transcievery pro přenos dat, je u nich parádní, že se u nich dá programově nastavit snad úplně všechno (přenosová rychlost v kb/s, výkon vysílače...). Komunikují s okolním prostředím (procesorem) přes rozhraní SPI. Jejich cena se pohybuje okolo 150Kč. Jinak zde je originální datasheet i s návodem.

Je však škoda, že tvůrci tohoto návodu jaksi zapomněli na jednom řádku zdrojového kódu zapnout u přijímací části samotný přijímač a každý asi pochopí co to (ne)bude dělat. A proto jsem se rozhodl, že dám dohromady nějaký jednoduchý návod jak rozchodit komunikaci těchto dvou modulů mezi sebou.

 

Tak jdeme na to

Za prvé si musíme vybrat procesor, kterým to budem celé řídit. Klidně si můžeme vybrat procesor, který má hardwarové SPI a budeme mít o starost míň. Já jsem si vybral trošku useless procesor PIC16F84, ale byl doma tak co s ním.

Tak to by jsme měli vybraný procesor, pak už stačí trošku pochopit pár funkcí v téhle knihovně a máme vyděláno. Celá sada souborů se dá stáhnout zde.

Hlavičkový soubor:




#ifndef rfm_modul
#define rfm_modul

#include "htc.h"

#ifndef  SDI
#define  SDI           RB0
#define  SDO           RB1 		//definice jednotlivých portů
#define  SCK           RB5
#define  nSEL          RB4
#define  nIRQ          RB3
#define  FFIT		 RA0
#endif

void rf_init(void); 
unsigned int rf_writecmd( unsigned int CMD );
unsigned char rf_read(void);
void rf_fifo_reset(void);
void Init_port(void);
void rf_transmitter(void);
void rf_receiver(void);
void rf_sleep(void);
void rf_send(unsigned char data);
void Init_port(void);

#endif


Zdrojový soubor:



#include "rfm.h"

//------------------------------------
//inicializace portů
//-----------------------------------
void Init_port(void){ 
	RP0=1;	//banka 1,aby se nastavovaly hodnoty v trisech
	FFIT=1; //1 vstup, 0 výstup
	nIRQ=1;
	SDI=0;
	SDO=1;
	SCK=0;
	nSEL=0;
	RP0=0;
	}
//------------------------------------
//spací mod - vypne vysílač i přijímač
//-----------------------------------
void rf_sleep(void){
  rf_writecmd(0x8201); 
  rf_writecmd(0x0000);
}
//------------------------------------
//vysílací mod
//-----------------------------------
void rf_transmitter(void){
  rf_writecmd(0x8239); //er,!ebb,ET,ES,EX,!eb,!ew,DC 
  rf_writecmd(0x0000);
}
//------------------------------------
//přijímací mod
//-----------------------------------
void rf_receiver(void){
  rf_writecmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC (bug was here)
  rf_writecmd(0x0000);
}
//------------------------------------
//inicializace modulku
//-----------------------------------
void rf_init(void){
	
  Init_port();
  nSEL=1;  SDI=1;  SCK=0;  SDO=0; 
  
  rf_writecmd(0x80E7); //EL,EF,868band,12.0pF
  rf_writecmd(0xA640); //freq select
  rf_writecmd(0xC647); //4.8kbps
  rf_writecmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
  rf_writecmd(0xC2AC); //AL,!ml,DIG,DQD4
  rf_writecmd(0xCA81); //FIFO8,SYNC,!ff,DR (FIFO level = 8)
  rf_writecmd(0xCED4); //SYNC=2DD4;
  rf_writecmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
  rf_writecmd(0x9850); //!mp,90kHz,MAX OUT
  rf_writecmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0
  rf_writecmd(0xE000); //NOT USED
  rf_writecmd(0xC800); //NOT USED
  rf_writecmd(0xC040); //1.66MHz,2.2V
}
//----------------------------------------
//funkce pro zápis 2bytů přes spi
//zároveň vrací hodnotu přečtenou z modulu
//----------------------------------------
unsigned int rf_writecmd(unsigned int cmd) {
    unsigned char i;
    unsigned int recv;
    recv = 0;
    SCK=0;
    nSEL=0;
    for(i=0; i<16; i++) {
      if(cmd&0x8000) SDI=1; else SDI=0;
      SCK=1;
      recv<<=1;
      recv+=SDO;
      
      SCK=0;
      cmd<<=1;
    }
    nSEL=1;
    return recv;
  }
//------------------------------------
//funkce pro čtení z bufferu
//-------------------------------------
unsigned char rf_read() {
  while(!FFIT) continue; 
  //čeká na bit FFIT, který přijímač oznamuje, že modul dokončil příjem
  return (rf_writecmd(0xB000)&0xff);
  }
//----------------------------------
//funkce na resetování bufferu
//----------------------------------
void rf_fifo_reset() {
  rf_writecmd(0xCA81);
  rf_writecmd(0xCA83);
  }
//----------------------------------
//funkce na vyslání dat přijimačem
//----------------------------------
void rf_send(unsigned char data){
	while(nIRQ) continue;
	//nIRQ říká že modul má odesláno a může se pokračovat
	rf_writecmd(0xB800 + data);
}


Tak to máme knihovnu, teď už zbývá ukázat jak ji použít prakticky, tenhle vysílač dokola každých 100ms vysílá byty 0x30 až 0x40:


#define _XTAL_FREQ 4000000  //nastaveni frekvence oscilátoru
#define _PIC16F84A
#include "htc.h"  	
#include "rfm.h"

__CONFIG(XT & UNPROTECT & WDTDIS & PWRTEN); //nastavení pojistek

//-------------------------------------------
//Hlavní program
//-------------------------------------------
void main(){
  unsigned char i;
  rf_init();	//inicializace 
  rf_transmitter(); //režim vysílání
  for(;;){
	rf_writecmd(0);
	  
	rf_send(0xAA);  //preamble - musí se vyslat nějaká hlavička
	rf_send(0xAA);
	rf_send(0xAA);
	rf_send(0x2D);	//synchroskupina, dá se změnit nebo zkrátit na 1byte
	rf_send(0xD4);
	 	
	for (i=0;i<16;i++)
	 	rf_send(0x30+i);
		 	
	rf_send(0xAA); //dummy - nějaké ukončení vysílání
	rf_send(0xAA);
	rf_send(0xAA);
	del(100);
   }
  for(;;);
}

Tak teď už jenom stačí nějaký ten přijímač a bude to fungovat


#define _XTAL_FREQ 4000000  //nastaveni frekvence oscilátoru
#define _PIC16F84A
#include "htc.h" 
#include "rfm.h"

__CONFIG(XT & UNPROTECT & WDTDIS & PWRTEN); //nastavení pojistek

//--------------------------------------------
//Hlavní program
//--------------------------------------------
void main(){ 
	unsigned char j,i=0;
	bank1 unsigned char data[16]; //pole do kterého se načtou přijatá data
  
	rf_init();	//inicializace modulu
	rf_receiver(); //modulu do režimu přijmu
	rf_fifo_reset(); 
	//vyčištění bufferu, musí se to dělat po každém čtení jinak to nefunguje

	for (;;){
		for(j=0;j<16;j++){
			data[j]=rf_read(); 	//přečte data z bufferu do pole
		}
		rf_fifo_reset();
		for (j=0;j<16;j++)
			eeprom_write(i++,data[j]);	//přečtená data nahraje do eeprom
	}
}