用ATMEGA16控制NRF905进行简单的收发,调了一周了,希望哪位大侠能帮俺播开云雾!!
[复制链接]
发送段代码: #include <iom16v.h> #include <macros.h> #define uint unsigned int #define uchar unsigned char #define Low_TX_EN PORTD&=~(1 << PD7) #define High_TX_EN PORTB|= (1 << PD7) #define High_TRX_CE PORTD|= (1 << PD6) #define Low_TRX_CE PORTD&=~(1 << PD6) #define High_PWR PORTD|= (1 << PD5) #define Low_PWR PORTD&=~(1 << PD5) //--------------------------------SPI口定义------------------------------------- #define High_SCK PORTB|=(1 << PB7) #define Low_SCK PORTB&=~(1 << PB7) #define High_CSN PORTB|= (1 << PB4) #define Low_CSN PORTB&=~(1 << PB4) #define High_CD PORTD|= (1 << PD4) #define Low_CD PORTD&=~(1 << PD4) #define High_AM PORTD|= (1 << PD3) #define Low_AM PORTD&=~(1 << PD3) #define High_DR PORTD |= (1 << PD2) #define Low_DR PORTD &= ~(1 << PD2) //----------------------------------905-SPI指令--------------------------------- #define WC 0x00 #define RC 0x10 #define WTP 0x20 #define RTP 0x21 #define WTA 0x22 #define RTA 0x23 #define RRP 0x24 uchar TxBuf[4]={0x01,0x02,0x03,0x04}; //待发送的数据 uchar TxAddress[4]={0xcc,0xcc,0xcc,0xcc }; //发送的地址 uchar RFConf[11]= { 0x00, //配置命令// 0x5f, //CH_NO,配置频段在915MHZ 0x0b, //输出功率为+6db,不重发,节电为正常模式 0x44, //地址宽度设置,为4字节 0x04,0x04, //接收发送有效数据长度为4字节 0xCC,0xCC,0xCC,0xCC, //接收地址 0x58, //CRC充许,8位CRC校验,外部时钟信号不使能,16M晶振,,输出时钟频率为4MHZ, }; //--------------------------延时函数------------------------------------------- void delay(uint z) { uint i,j; for(i=z;i>0;i--) for(j=1714;j>0;j--); } void delayus(uint x) { uint i; while(x--) for(i=0;i<80;i++); } //----------------------------------SPI初始化----------------------------------- void Spi_initial(void) { SPCR=0x50; SPSR=0x00; // SPCR = (1<<SPE)|(1<<MSTR)|(0<<CPOL)|(0<<SPR0); // 主机模式,fck/16, SPI方式0 } //---------------------------------SPI写程序---------------------------------- uchar SpiWrite(uchar Data)//r { SPDR = Data; while(!(SPSR & (1<<SPIF) )) //SPIF即等于7, 等待SPI发送完毕 {}; // 等待SPI发送完毕 return SPDR; } //---------------------------------系统状态初始化------------------------------- void system_init(void) { High_CSN; // Spi disable Low_SCK; // Spi clock line init low Low_DR; // Init DR for input Low_AM; // Init AM for input Low_CD; // Init nrf905_CDfor input High_PWR; // nRF905 power on Low_TRX_CE; // 初始化为空闲模式 Low_TX_EN ; // 默认为接收模式 } //--------------------------------NRF905寄存器初始化函数------------------------ void Config905(void) { uchar i; Low_CSN; // Spi enable for write a spi command //SpiWrite(WC); // Write config command写放配置命令 for (i=0;i<11;i++) // Write configration words 写放配置字 { SpiWrite(RFConf); } High_CSN; // 关闭SPI } //--------------------------------NRF905待发数据打包---------------------------- void txpacket(void) { uchar i; Low_CSN; // 使能Spi,允许对nrf905进行读写操作 delayus(1); SpiWrite(WTP); // 写数据前先写写数据命令 for (i=0;i<4;i++) { SpiWrite(TxBuf); // 待发送的4字节数据 } High_CSN; // 关闭Spi,不允许对nrf905进行读写操作 delayus(2); Low_CSN; // 再次使能Spi,可以对SPI进行读写操作 SpiWrite(WTA); // 写地址前首先先写地址命令 for (i=0;i<4;i++) // 写 4 bytes 地址 { SpiWrite(TxAddress); } High_CSN; // 关闭Spi High_TRX_CE; // 905的发送使能有效 ?????这一步是否是多余的呢??因为可以独立写发送函数。 delayus(2); // 等待DR变高,也即发送数据完成 Low_TRX_CE; // 设置TRX_CE=0,发送使能无效 } //-------------------------------发送模式激发----------------------------------- void setxmode(void) { Low_TRX_CE; // 905的发送使能有效 High_TX_EN; // 905设置为发送模式 delayus(3); // delay for mode change(>=650us)根据晶振不同要改变 } //--------------主函数---------------------------------------------------------- void main(void) { DDRB=DDRB|BIT(4)|BIT(5)|BIT(7)&(~BIT(6)); //设置AVR的SS,MOSI,SCK为输出,MISO为输入。 DDRC|=BIT(0); //置PC0为输出. PORTC=0x00; //端口C初始化. DDRD=0xff; //刚开始时DDRD全为输出,便于system_init函数里把AM,DR,CD初始化为低。 Spi_initial(); system_init(); DDRD=0xe3; //初始化以后把AM,DR,CD引脚置为输入,开始侦测DR的引脚变化,文档里说数据发送完成后DR会置高。 Config905(); delayus(50); while(1) { setxmode(); //激发发送模式 txpacket(); //发送数据打包 if((PIND&0x04)!=0) //如果DR引脚变高,则让小灯闪。 { PORTC|=BIT(0); delay(2000); PORTC&=~BIT(0); delay(2000); } } } 接收端代码: #include <iom16v.h> #include <macros.h> #define uint unsigned int #define uchar unsigned char #define Low_TX_EN PORTD&=~(1 << PD7) #define High_TX_EN PORTB|= (1 << PD7) #define High_TRX_CE PORTD|= (1 << PD6) #define Low_TRX_CE PORTD&=~(1 << PD6) #define High_PWR PORTD|= (1 << PD5) #define Low_PWR PORTD&=~(1 << PD5) //--------------------------------SPI口定义------------------------------------- #define High_SCK PORTB|=(1 << PB7) #define Low_SCK PORTB&=~(1 << PB7) #define High_CSN PORTB|= (1 << PB4) #define Low_CSN PORTB&=~(1 << PB4) #define High_CD PORTD|= (1 << PD4) #define Low_CD PORTD&=~(1 << PD4) #define High_AM PORTD|= (1 << PD3) #define Low_AM PORTD&=~(1 << PD3) #define High_DR PORTD |= (1 << PD2) #define Low_DR PORTD &= ~(1 << PD2) //----------------------------------905-SPI指令--------------------------------- #define WC 0x00 #define RC 0x10 #define WTP 0x20 #define RTP 0x21 #define WTA 0x22 #define RTA 0x23 #define RRP 0x24 uchar TxAddress[4]={0xcc,0xcc,0xcc,0xcc }; //发送的地址 uchar RFConf[11]= { 0x00, //配置命令// 0x5f, //CH_NO,配置频段在915MHZ 0x0b, //输出功率为10db,重发,节电为正常模式 0x44, //地址宽度设置,为4字节 0x04,0x04, //接收发送有效数据长度为4字节 0xCC,0xCC,0xCC,0xCC, //接收地址 0x58, //CRC充许,8位CRC校验,外部时钟信号不使能,16M晶振,,输出时钟频率为4MHZ, }; //--------------------------延时函数------------------------------------------- void delay(uint z) { uint i,j; for(i=z;i>0;i--) for(j=1714;j>0;j--); } void delayus(uint x) { uint i; while(x--) for(i=0;i<80;i++); } //----------------------------------SPI初始化----------------------------------- void Spi_initial(void) { SPCR=0x50; SPSR=0x00; //SPCR = (1<<SPE)|(1<<MSTR)|(0<<CPOL)|(0<<SPR0); // 主机模式,fck/16, SPI方式0 } //---------------------------------SPI写程序---------------------------------- uchar SpiWrite(uchar Data)//r { SPDR = Data; while(!(SPSR & (1<<SPIF) )) //SPIF即等于7, 等待SPI发送完毕 {}; // 等待SPI发送完毕 return SPDR; } //---------------------------------系统状态初始化------------------------------- void system_init(void) { High_CSN; // Spi disable Low_SCK; // Spi clock line init low Low_DR; // Init DR for input Low_AM; // Init AM for input Low_CD; // Init nrf905_CDfor input High_PWR; // nRF905 power on Low_TRX_CE; // 初始化为空闲模式 Low_TX_EN ; // 默认为接收模式 } //--------------------------------NRF905寄存器初始化函数------------------------ void Config905(void) { uchar i; Low_CSN; //SPI有效 delayus(2); //SpiWrite(WC); // Write config command写放配置命令 for (i=0;i<11;i++) // Write configration words 写放配置字 { SpiWrite(RFConf); } High_CSN; // 关闭SPI } void SetRxMode(void) { High_TRX_CE; Low_TX_EN; delayus(3); } //--------------主函数---------------------------------------------------------- void main(void) { DDRB=DDRB|BIT(4)|BIT(5)|BIT(7)&(~BIT(6)); //设置AVR的SS,MOSI,SCK为输出,MISO为输入。 DDRC=0xff; DDRC=0x00; //设置AVR的PC4为输出,因为PC4接了小灯。 DDRD=0xff; //刚开始时DDRD全为输出,便于system_init函数里把AM,DR,CD初始化为低。 Spi_initial(); system_init(); DDRD=0xe3; //初始化以后把AM,DR,CD引脚置为输入,开始侦测CD和AM的引脚变化,文档里说检测到相同频率的载波后CD引脚会置高,接收到匹配的地址AM会置高 Config905(); delayus(50); while(1) { SetRxMode(); if((PIND&0x18)!=0) //如果AM或CD引脚有一个是高,则小灯开始闪。 PORTC|=BIT(4); delay(2000); PORTC&=~BIT(4); delay(2000); } } 哪位用过此模块的高手帮帮小弟吧。
|