nRF24L01中文全数据手册翻译

合集下载

nrf24L01配置

nrf24L01配置

CE 输入RX 或TX 模式选择
CSN 输入SPI 片选信号, 低电平使能,硬件不能直接接低电平
SCK 输入SPI 时钟最高8MHZ
MOSI 输入从SPI 数据输入脚
MISO 三态输出从SPI 数据输出脚
IRQ 输出中断低电平使能 TX_DS或MAX_RT或RX_DR高电平,IRQ产生中断低电平
写寄存器只有在掉电模式和待机模式下可操作。

TX模式
填充TX FIFO
PWR_UP=1,PRIM_RX=0,
CE=1(高电平持续时间最小为10us),启动发射
每一条指令的执行都必须通过一次CSN 由高到低的变化
CE一直高,TX FIFO有数据就一直发射,TX FIFO空就进入待机2模式,在这个模式,TX FIFO有数据就进入发送模式开始发送数据。

CE大于10US高脉冲,只能发一包,发完进入待机1模式。

发送数据宽度是动态的吗?
PWR_UP=1,PRIM_RX=1,CE=1启动接收
CE=0进入待机模式1
载波检测cd,跳频,
发送模块没有成功发送数据时,发送端PLOS_CNT显示数据包丢失率太高时可将其设置位接收模式检测CD值如果CD为高说明通道出现了拥挤现象需要更改通信频道
时序
SPI指令,
F340
无线传32字节,是8位一组,4组,
STM32F103
一个8位,一个32位,如何通信
两个的FLASH地址位多了,
SPI接口几位,
如何送到FIFO
测试。

NRF24L01通道使用(DOC)

NRF24L01通道使用(DOC)

网上面关于多通道通信的好多资源都可以去共享,我也下了好多去调试,结果发现基本上都是调不通的。

其实这个归根到底还是一个地址匹配问题,通道0和1还好说,它是默认开启的,一般没问题,但通道2至5,通道如何匹配,数据手册上也只是说地址要匹配,到底要怎么做它没讲。

下面什么都不说了,直接上程序,这是用PIC16F877A来控制的,我会把要注意的重点标记出来,当然主要是多通道地址匹配的,其它的我就不多说了自己领悟。

接收部分:#include <pic.h> //调用头文件,可以去PICC软件下去查找PIC16F88X单片机的头文件__CONFIG(XT&WDTDIS&LVPDIS&BORDIS); //定义配置字,晶振类型:XT,关闭开门狗,禁止低电压编程,禁止欠压复位#define u8 unsigned char#define u16 unsigned int#define BUZZER RB1u8 i=0,a=0,data[13]=0;#define NRF24L01_MISO RC4#define NRF24L01_MOSI RC5 //输出#define NRF24L01_SCK RC3 //输出#define NRF24L01_CE RC0 //使能控制设为输出#define NRF24L01_CSN RC2 //片选控制设为输出#define NRF24L01_IRQ RC1 //中断标志设为输入#define RS RE0#define RW RE1#define E RE2unsigned char SPIx_ReadWriteByte(unsigned char byte){unsigned char data;SSPBUF=byte;do{;}while(SSPIF==0);SSPIF=0;data=SSPBUF;return(data); // return read byte}//24L01操作线//#define NRF24L01_CE PAout(4) //24L01片选信号//#define NRF24L01_CSN PCout(4) //SPI片选信号//#define NRF24L01_IRQ PCin(5) //IRQ主机数据输入#define READ_REG 0x00 //读配置寄存器,低5位为寄存器地址#define WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字节#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.发射模式下用#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送.#define pop 0xFF //空操作,可以用来读状态寄存器//SPI(NRF24L01)寄存器地址#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能#define EN_AA 0x01 //使能自动应答功能bit0~5,对应通道0~5#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时250*x+86us#define RF_CH 0x05 //RF通道,bit6:0,工作通道频率;#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发//bit5:数据发送完成中断;bit6:接收数据中断;#define MAX_TX 0x10 //达到最大发送次数中断#define TX_OK 0x20 //TX发送完成中断#define RX_OK 0x40 //接收到数据中断#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器#define CD 0x09 //载波检测寄存器,bit0,载波检测;#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法#define FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RXFIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;///////////////////////////////////////////////////// /////////////////////////////////////////24L01发送接收数据宽度定义#define TX_ADR_WIDTH 5 //5字节的地址宽度#define RX_ADR_WIDTH 5 //5字节的地址宽度#define TX_PLOAD_WIDTH 32 //20字节的用户数据宽度#define RX_PLOAD_WIDTH 32 //20字节的用户数据宽度void NRF24L01_Init(void);//初始化void RX_Mode(void);//配置为接收模式void TX_Mode(void);//配置为发送模式u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//读数据区u8 NRF24L01_Read_Reg(u8 reg);//读寄存器u8 NRF24L01_Write_Reg(u8 reg, u8 value);//写寄存器u8 NRF24L01_Check(void);//检查24L01是否存在u8 NRF24L01_TxPacket(u8 *txbuf);//发送一个包的数据u8 NRF24L01_RxPacket(u8 *rxbuf);//接收一个包的数据const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x0 1}; //本地发送地址const u8 RX_ADDRESS0[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0 x01}; //接收0通道地址const u8 RX_ADDRESS1[RX_ADR_WIDTH]={0xc2,0xc2,0xc2,0xc2,0x c1}; //接收1通道地址const u8 RX_ADDRESS2[1]={0xb3}; //接收2通道地址const u8 RX_ADDRESS3[1]={0xa5}; //接收3通道地址const u8 RX_ADDRESS4[1]={0x35}; //接收4通道地址const u8 RX_ADDRESS5[1]={0x8f}; //接收5通道地址/********************************************/void delay1(unsigned char n){unsigned int m;for(;n>0;n--)for(m=0;m<100;m++){asm("NOP");}}void lcd_busy(){TRISD7=1; /*1602上DB7=1表明总线忙,同时RS=0 选择指令寄存器,RSS=1是选择数据寄存器*/RS=0;RW=1;E=1;while(RD7==1);E=0;TRISD7=0;}void lcd_write_commend(unsigned char u){lcd_busy();RS=0;RW=0;PORTD=u;E=1;asm("NOP");E=0;}void lcd_write_data(unsigned char k){lcd_busy();RS=1;RW=0;PORTD=k;E=1;asm("NOP");E=0;}void lcd_1602_ddram_add(u8 x,u8 y)//x是列,y是行,ddram是字符显示的地址{if(y==1){lcd_write_commend(0x80+x);}if(y==2){lcd_write_commend(0xc0+x);}}void lcd_disp(unsigned char x,unsigned char y,unsigned char l){x&=0x0f;//列地址限制在0-15y&=0x01;if(y==0x00)lcd_write_commend(x|0x80); //第一行的列地址写入elselcd_write_commend((x+0x40)|0x80); //第二行的列地址写入lcd_write_data(l+0x30);}void lcd_1602_display_shu(u8 num,u16 shu,u8 x,u8 y)//在液晶的任何位置显示五位内的数字{u8 wan,qian,bai,shi,ge;if(num>=1) ge=shu%10;if(num>=2) shi=shu%100/10;if(num>=3) bai=shu%1000/100;if(num>=4) qian=shu%10000/1000; if(num==5) wan=shu/10000;lcd_1602_ddram_add(x,y);if(num==1)lcd_write_data(ge|0x30);if(num==2){lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}if(num==3){lcd_write_data(bai|0x30);lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}if(num==4){lcd_write_data(qian|0x30);lcd_write_data(bai|0x30);lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}if(num==5){lcd_write_data(wan|0x30);lcd_write_data(qian|0x30);lcd_write_data(bai|0x30);lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}}void init_1602(){TRISD=0x00;TRISE=0x00;ADCON1=0X82;PORTE=0;PORTD=0;lcd_write_commend(0x38); /*这里的设置是更具需要,选择1602的各项配置,1602共有11条指令*/delay1(100);lcd_write_commend(0x38); /*这里的设置是更具需要,选择1602的各项配置,1602共有11条指令*/delay1(100);lcd_write_commend(0x38); /*这里的设置是更具需要,选择1602的各项配置,1602共有11条指令*/delay1(100);lcd_write_commend(0x38); //8位数据,双列,5*7字形lcd_write_commend(0x08);//显示功能关,无光标lcd_write_commend(0x01);//清屏指令lcd_write_commend(0x06);//写入新的数据后,光标右移,显示屏不移动lcd_write_commend(0x0c);//显示功能开,无光标,}/**********************汉字显示的代码******************************/const u8 hz1[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x11,0x1F};//日const u8 hz2[]={0x0F,0x09,0x0F,0x09,0x0F,0x09,0x09,0x13};//月const u8 hz3[]={0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02};//年const u8 hz4[]={0x1F,0x1F,0x04,0x04,0x04,0x04,0x1F,0x1F};//工const u8 hz5[]={0x0E,0x0A,0x0E,0x1F,0x04,0x07,0x03,0x01};//号void CGRAM(const u8 *hz,const u8 temp) //自定义字符存储{u8 i;for(i=0;i<8;i++){lcd_write_commend(temp+i);lcd_write_data(*(hz+i));}}/*******************************************///SPI写寄存器//reg:指定寄存器地址//value:写入的值u8 NRF24L01_Write_Reg(u8 reg,u8 value){u8 status;NRF24L01_CSN=0; //使能SPI传输status =SPIx_ReadWriteByte(reg);//发送寄存器号SPIx_ReadWriteByte(value); //写入寄存器的值NRF24L01_CSN=1; //禁止SPI传输return(status); //返回状态值}//读取SPI寄存器值//reg:要读的寄存器u8 NRF24L01_Read_Reg(u8 reg){u8 reg_val;NRF24L01_CSN = 0; //使能SPI传输SPIx_ReadWriteByte(reg); //发送寄存器号reg_val=SPIx_ReadWriteByte(0XFF);//读取寄存器内容NRF24L01_CSN = 1; //禁止SPI传输return(reg_val); //返回状态值}//在指定位置读出指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len){u8 status,u8_ctr;NRF24L01_CSN = 0; //使能SPI传输status=SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_Rea dWriteByte(0XFF);//读出数据NRF24L01_CSN=1; //关闭SPI传输return status; //返回读到的状态值}//在指定位置写指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len){u8 status,u8_ctr;NRF24L01_CSN = 0; //使能SPI传输status = SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //写入数据NRF24L01_CSN = 1; //关闭SPI传输return status; //返回读到的状态值}//启动NRF24L01发送一次数据//txbuf:待发送数据首地址//返回值:0,接收完成;其他,错误代码u8 NRF24L01_RxPacket(u8 *rxbuf){u8 sta;//SPIx_SetSpeed(SPI_SPEED_8); //spi速度为9Mhz (24L01的最大SPI时钟为10Mhz)sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值NRF24L01_Write_Reg(WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志if(sta&RX_OK)//接收到数据{NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WID TH);//读取数据NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器return 0;}return 1;//没收到任何数据}//该函数初始化NRF24L01到RX模式//设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR //当CE变高后,即进入RX模式,并可以接收数据了void RX_Mode(void){NRF24L01_CE=0;NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)TX_ ADDRESS,RX_ADR_WIDTH);//接收设备接收通道0使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P1,(u8*)RX_ ADDRESS1,RX_ADR_WIDTH);//接收设备接收通道1使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P2,(u8*)RX_ ADDRESS2,1);//接收设备接收通道2使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P3,(u8*)RX_ ADDRESS3,1);//接收设备接收通道3使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P4,(u8*)RX_ ADDRESS4,1);//接收设备接收通道4使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P5,(u8*)RX_ ADDRESS5,1);//接收设备接收通道5使用和发送设备相同的发送地址NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x3f);//使能通道0到5的自动应答NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x3f);//使能通道0到5的接收地址NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //设置RF通信频率NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_ WIDTH);//选择通道0的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P1,RX_PLOAD_ WIDTH);//选择通道1的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P2,RX_PLOAD_ WIDTH);//选择通道2的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P3,RX_PLOAD_ WIDTH);//选择通道3的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P4,RX_PLOAD_ WIDTH);//选择通道4的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P5,RX_PLOAD_ WIDTH);//选择通道5的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式NRF24L01_CE = 1; //CE为高,进入接收模式}void delay(unsigned int m){unsigned int n;n=m;for(;n>0;n--)NOP();}void spi_init(){TRISC=0x13;SSPSTAT=0xc0;SSPCON=0x20;}void INT1(){TRISB=0x00;PORTB=0xfc;INTEDG = 1;INTF = 0;INTE = 1;GIE = 1;}void main(){u8 x=3;spi_init();init_1602();INT1();NRF24L01_CE=0;// chip enableNRF24L01_CSN=1;// Spi disable//NRF24L01_SCK=0;// Spi clock line init highCGRAM(hz1,0x40);CGRAM(hz2,0x48);CGRAM(hz3,0x50);CGRAM(hz4,0x58);CGRAM(hz5,0x60);//将这五个字写到1602用户自定义CGRAM中while(1){RX_Mode();NOP();if(NRF24L01_RxPacket(data)==0){lcd_write_commend(0x80);//第一行第一个字lcd_write_data(0x52);//显示接收的字母Rlcd_1602_display_shu(4,2013,x,1);//显示4位数的年份lcd_write_data(2); //显示汉字年lcd_1602_display_shu(2,8,x+5,1);//显示月份lcd_write_data(1); //显示汉字月lcd_1602_display_shu(2,7,x+8,1);//显示日期lcd_write_data(0); //显示汉字日lcd_write_commend(0xc0);//第二行显示lcd_write_data(3); //显示汉字工lcd_write_data(4); //显示汉字号lcd_write_commend(0xc0|0x02);//隔两格lcd_write_data(0x3A);//显示封号for(i=0;i<13;i++)//显示工人编号{lcd_disp(i+3,1,data[i]);}if(data[12]==1)RB0=1;elseRB0=0;}}}void interrupt ISR(void) {u16 y;if(INTF == 1){INTF = 0;asm("NOP");for(y=0;y<4000;y++){BUZZER=1;delay(20);BUZZER=0;}}}发送部分:#include <pic.h> //调用头文件,可以去PICC软件下去查找PIC16F88X单片机的头文件__CONFIG(XT&WDTDIS&LVPDIS&BORDIS); //定义配置字,晶振类型:XT,关闭开门狗,禁止低电压编程,禁止欠压复位#define u8 unsigned char#define u16 unsigned int#define key RB0u8 test[13]={2,0,1,2,5,8,0,8,0,2,1,5};u16 i=0;#define NRF24L01_MISO RC4#define NRF24L01_MOSI RC5 //输出#define NRF24L01_SCK RC3 //输出#define NRF24L01_CE RC0 //使能控制设为输出#define NRF24L01_CSN RC2 //片选控制设为输出#define NRF24L01_IRQ RC1 //中断标志设为输入*/#define RS RE0 //数据/命令选择#define RW RE1 //读/写选择#define E RE2 //使能信号unsigned char SPIx_ReadWriteByte(unsigned char byte){unsigned char data;SSPBUF=byte;do{;}while(SSPIF==0);SSPIF=0;data=SSPBUF;return(data); // return read byte}#define READ_REG 0x00 //读配置寄存器,低5位为寄存器地址#define WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.发射模式下用#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送.#define pop 0xFF //空操作,可以用来读状态寄存器//SPI(NRF24L01)寄存器地址#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能#define EN_AA 0x01 //使能自动应答功能bit0~5,对应通道0~5#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时250*x+86us#define RF_CH 0x05 //RF通道,bit6:0,工作通道频#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发//bit5:数据发送完成中断;bit6:接收数据中断;#define MAX_TX 0x10 //达到最大发送次数中断#define TX_OK 0x20 //TX发送完成中断#define RX_OK 0x40 //接收到数据中断#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器#define CD 0x09 //载波检测寄存器,bit0,载波检测;#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法#define FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;///////////////////////////////////////////////////// ///////////////////////////////////////////////////////24L01发送接收数据宽度定义#define TX_ADR_WIDTH 5 //5字节的地址宽度#define RX_ADR_WIDTH 5 //5字节的地址宽度#define TX_PLOAD_WIDTH 32 //20字节的用户数据宽度#define RX_PLOAD_WIDTH 32 //20字节的用户数据宽度void NRF24L01_Init(void);//初始化void RX_Mode(void);//配置为接收模式void TX_Mode(void);//配置为发送模式u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//读数据区u8 NRF24L01_Read_Reg(u8 reg);//读寄存器u8 NRF24L01_Write_Reg(u8 reg, u8 value);//写寄存器u8 NRF24L01_Check(void);//检查24L01是否存在u8 NRF24L01_TxPacket(u8 *txbuf);//发送一个包的数据u8 NRF24L01_RxPacket(u8 *rxbuf);//接收一个包的数据//下面这里就是重点啦,看看我用线条标出的是32位公用的地址,红色部分是低八位,注意位置啊啊啊啊啊啊const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x35,0xc2,0xc2,0xc2,0xc 1}; //发送地址const u8 RX_ADDRESS0[RX_ADR_WIDTH]={0x35,0xc2,0xc2,0xc2,0x c1}; //接收3通道地址,就以通道3为例,其它都一个样//SPI写寄存器//reg:指定寄存器地址//value:写入的值u8 NRF24L01_Write_Reg(u8 reg,u8 value){u8 status;NRF24L01_CSN=0; //使能SPI传输status =SPIx_ReadWriteByte(reg);//发送寄存器号SPIx_ReadWriteByte(value); //写入寄存器的值NRF24L01_CSN=1; //禁止SPI传输return(status); //返回状态值}//读取SPI寄存器值//reg:要读的寄存器u8 NRF24L01_Read_Reg(u8 reg){u8 reg_val;NRF24L01_CSN = 0; //使能SPI传输SPIx_ReadWriteByte(reg); //发送寄存器号reg_val=SPIx_ReadWriteByte(0XFF);//读取寄存器内容NRF24L01_CSN = 1; //禁止SPI传输return(reg_val); //返回状态值}//在指定位置读出指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len){u8 status,u8_ctr;NRF24L01_CSN =0; //使能SPI传输status=SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_ReadWriteByte(0XFF);//读出数据NRF24L01_CSN=1; //关闭SPI传输return status; //返回读到的状态值}//在指定位置写指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len){u8 status,u8_ctr;NRF24L01_CSN = 0; //使能SPI传输status = SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //写入数据NRF24L01_CSN = 1; //关闭SPI传输return status; //返回读到的状态值}void delay(unsigned int n){for(;n>0;n--)NOP();}//启动NRF24L01发送一次数据//txbuf:待发送数据首地址//返回值:发送完成状况u8 NRF24L01_TxPacket(u8 *txbuf){u8 sta;//SPIx_SetSpeed(SPI_SPEED_8);//spi速度为9Mhz (24L01的最大SPI时钟为10Mhz)NRF24L01_CE=0; NRF24L01_IRQ=0;NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WID TH);//写数据到TX BUF 32个字节delay(5000);NRF24L01_CE=1;//启动发送delay(5000);while(NRF24L01_IRQ!=0);//等待发送完成sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值NRF24L01_Write_Reg(WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志if(sta&MAX_TX)//达到最大重发次数{NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器return MAX_TX;}if(sta&TX_OK)//发送完成{return TX_OK;}elsereturn 0xff;//其他原因发送失败}//该函数初始化NRF24L01到TX模式//设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR//PWR_UP,CRC使能//当CE变高后,即进入RX模式,并可以接收数据了//CE为高大于10us,则启动发送.void TX_Mode(void){NRF24L01_CE=0;NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(u8*)TX_ADD RESS,TX_ADR_WIDTH);//写TX节点地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)RX_ ADDRESS0,RX_ADR_WIDTH); //设置RX节点地址,主要为了使能ACK,TX_ADDRESS和RX_ADDRESS0一定要一致,不然就调不通的NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);//使能通道0的自动应答NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次NRF24L01_Write_Reg(WRITE_REG+RF_CH,40);//设置RF通道为40NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断NRF24L01_CE=1;//CE为高,10us后启动发送NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();}void delay1(unsigned int n){unsigned int m;for(;n>0;n--)for(m=0;m<100;m++){asm("NOP");}}void read_1602_bz()//测忙{TRISD7=1;RS=0;RW=1;E=1;while(RD7==1);E=0;TRISD7=0;}void write_1602_dat(u8 data_1)//写数据{read_1602_bz();RS=1;RW=0;PORTD=data_1;delay(5);E=1;delay(5);E=0;}void write_1602_com(u8 com)//写指令{read_1602_bz();RS=0;RW=0;PORTD=com;delay(5);E=1;delay(5);E=0;}void lcd_1602_ddram_add(u8 x,u8 y)//x是列,y是行,ddram是字符显示的地址{if(y==1){write_1602_com(0x80+x);}if(y==2){write_1602_com(0xc0+x);}}void lcd_disp(unsigned char x,unsigned char y,unsigned charl){x&=0x0f;//列地址限制在0-15y&=0x01;if(y==0x00)write_1602_com(x|0x80); //第一行的列地址写入elsewrite_1602_com((x+0x40)|0x80); //第二行的列地址写入write_1602_dat(l+0x30);}void lcd_1602_display_shu(u8 num,u16 shu,u8 x,u8 y)//在液晶的任何位置显示五位内的数字{u8 wan,qian,bai,shi,ge;if(num>=1) ge=shu%10;if(num>=2) shi=shu%100/10;if(num>=3) bai=shu%1000/100;if(num>=4) qian=shu%10000/1000;if(num==5) wan=shu/10000;lcd_1602_ddram_add(x,y);if(num==1)if(num==2){write_1602_dat(shi|0x30); write_1602_dat(ge|0x30); }if(num==3){write_1602_dat(bai|0x30); write_1602_dat(shi|0x30); write_1602_dat(ge|0x30); }if(num==4){write_1602_dat(qian|0x30); write_1602_dat(bai|0x30); write_1602_dat(shi|0x30); write_1602_dat(ge|0x30); }if(num==5){write_1602_dat(wan|0x30);write_1602_dat(bai|0x30);write_1602_dat(shi|0x30);write_1602_dat(ge|0x30);}}/**********************汉字显示的代码******************************/const u8 hz1[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x11,0x1F};//日const u8 hz2[]={0x0F,0x09,0x0F,0x09,0x0F,0x09,0x09,0x13};//月const u8 hz3[]={0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02};//年void CGRAM(const u8 *hz,const u8 temp) //自定义字符存储{u8 i;for(i=0;i<8;i++){write_1602_com(temp+i);write_1602_dat(*(hz+i));}void init_1602(){TRISE=0x00;TRISD=0x00;//ADCON1=0X82;PCFG3=0;PCFG2=1;PCFG1=1;PCFG0=1; //A端口全部数字化PORTE=0;PORTD=0;write_1602_com(0x38);delay(50);write_1602_com(0x38);delay(50);write_1602_com(0x38);delay(50);write_1602_com(0x0c);write_1602_com(0x06);write_1602_com(0x01);void spi_init(){TRISC=0x13;SSPCON=0x20;SSPSTAT=0xc0;PIR1=0;}void main(){u8 x=3;TRISB0=0;spi_init();init_1602();CGRAM(hz1,0x40);CGRAM(hz2,0x48);CGRAM(hz3,0x50);//将这三个字写到1602用户自定义CGRAM中NRF24L01_CE=0; //使能24L01NRF24L01_CSN=1;//SPI片选取消SPIx_ReadWriteByte(0xff);//启动传输while(1){TX_Mode();if(key==0){delay(1);if(key==0)test[12]=1;}elsetest[12]=0;if(NRF24L01_TxPacket(test)==TX_OK){write_1602_com(0x80);//第一行第一个位置write_1602_dat(0x53);//显示发送的字母Slcd_1602_display_shu(4,2013,x,1);//显示4位数的年份write_1602_dat(2); //显示汉字年lcd_1602_display_shu(2,8,x+5,1);//显示月份write_1602_dat(1); //显示汉字月lcd_1602_display_shu(2,7,x+8,1);//显示日期write_1602_dat(0); //显示汉字日write_1602_com(0xc0);//第二行显示write_1602_dat(0x49); //显示字母Iwrite_1602_dat(0x44); //显示字母Dwrite_1602_com(0xc0|0x02);//隔两格write_1602_dat(0x3A);//显示封号for(i=0;i<13;i++)//显示工人编号{lcd_disp(i+3,1,test[i]);}}}}。

nRF24L01无线模块讲解解读

nRF24L01无线模块讲解解读

数据通道
nRF24L01 在接收模式下可以接收6 路不同通道的数据。
数据通道
• 每一个数据通道使用不同的地址,但是共用相同的频道。 也就是说6 个不同的nRF24L01 设置为发送模式后可以与 同一个设置为接收模式的nRF24L01 进行通讯,而设置为 接收模式的nRF24L01 可以对这6 个发射端进行识别。 • 数据通道是通过寄存器EN_RXADDR 来设置的,默认状 态下只有数据通道0 和数据通道1 是开启状态的。 • nRF24L01在确认收到数据后记录地址,并以此地址为目 标地址发送应答信号,在发送端,数据通道0被用作接收 应答信号,因此属通道0 的接收地址要与发送地址端地址 相等,以确保接收到正确的应答信号。
封装引脚及其引脚功能
nRF单端50Ω射频输出原理图
nRF24L10与单片机应用电路图
举例:NRF24L01模块口与STM32连接原理图中断
• nRF24L01 的中断引脚(IRQ)为低电平触发,当状态寄 存器中TX_DS(数据发送完成中断位)、RX_DR(接收 数据中断位) 或MAX_RT(达到最多次重发中断位)为 高时触发中断。 • 当MCU 给中断源写‘1’时,中断引脚被禁止。可屏蔽中 断可以被IRQ 中断屏蔽。通过设置可屏蔽中断位为高,则 中断响应被禁止。默认状态下所有的中断源是被禁止的。
nRF24l01的SPI通信时序
增强型ShockBurstTM 发送模式
• 1、 配置寄存器位PRIM_RX 为低 • 2、 当MCU 有数据要发送时,接收节点地址(TX_ADDR) 和有效数据(TX_PLD)通过SPI 接口写入nRF24L01。发送 数据的长度以字节计数从MCU 写入TX FIFO。当CSN 为 低时数据被不断的写入。发送端发送完数据后,将通道0 设置为接收模式来接收应答信号,其接收地址 (RX_ADDR_P0)与接收端地址(TX_ADDR)相同。 例:在上图 中数据通道5 的发送端(TX5)及接收端(RX)地 址设置如下: TX5:TX_ADDR=0xB3B4B5B605 TX5:RX_ADDR_P0=0xB3B4B5B605 RX:RX_ADDR_P5=0xB3B4B5B605

NRF24L01--实用无线通信技术

NRF24L01--实用无线通信技术

NRF24L01是一款工作在2.4~2.5GHZ频段世界通用ISM频段(不受管制的频段)的单片无限收发器芯片,通信距离可达300米。

RF------------------------射频。

GFSK----------高斯频移键控。

一、模块介绍(1) 2.4Ghz 全球开放ISM 频段免许可证使用(2) 最高工作速率2Mbps ,高效GFSK 调制,抗干扰能力强,特别适合工业控制场合(3) 126 频道,满足多点通信和跳频通信需要(4) 内置硬件CRC 检错和点对多点通信地址控制(5) 低功耗1.9 - 3.6V 工作,待机模式下状态为22uA ;掉电模式下为900nA(6) 内置2.4Ghz 天线,体积小巧15 mm X 29 mm(7) 模块可软件设地址,只有收到本机地址时才会输出数据(提供中断指示) ,可直接接各种单片机使用,软件编程非常方便--------中断方式接收数据。

(8) 内置专门稳压电路,使用各种电源包括DC/DC 开关电源均有很好的通信效果(9) 2.54 MM 间距接口,DIP 封装(10) 工作于Enhanced ShockBurst 具有Automatic packet handling, Auto packet transaction handling, 具有可选的内置包应答机制,极大的降低丢包率。

二、注意事项(1) VCC 脚接电压范围为1.9V~3.6V 之间,不能在这个区间之外,超过3.6V 将会烧毁模块。

推荐电压3.3V 左右。

(2) 除电源VCC 和接地端,其余脚都可以直接和普通的5V 单片机IO直接相连,无需电平转换。

当然对3V 左右的单片机更加适用了。

三、NRF24L01模块蛇形部分应该为天线(无线通信);中间方形部分应该为NRF24L01芯片,上面跑道形状为晶振。

四、8个引脚GND,VCC(接3.3V)CE-----芯片使能CSN-----片选非SCK------SPI1 CLKMOSI,MISO------SPI数据线IRQ-------中断信号线VDD_PA 电源输出---------给RF的功率放大器提供的+1.8V电源ANT1------------------天线接口1ANT2------------------天线接口2五、工作模式---------软件编程部分。

基于模拟SPI的nrf24l01点对点通信说明

基于模拟SPI的nrf24l01点对点通信说明

基于模拟SPI的nrf24l01点对点通信说明基于模拟SPI的nrf24l01点对点通信通过阅读nrf24l01的中文手册大致了解其通信方式为SPI通信,上网查询SPI通信相关知识。

通过参考手册例程和网上例程完成程序的编写。

模拟SPI:使用单片机的IO口,利用函数来模拟SPI通信。

核心函数及个人的理解:uchar SPI_RW(uchar byte){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 循环8次{MOSI = (byte & 0x80); // byte的最高位输出到MOSI,取最高位发送byte = (byte << 1); // 左移一位SCK = 1; // 拉高SCK,24L01从MOSI中读入一位数据,同时从MISO输出一位数据byte |= MISO; // 读MISO的最低位SCK = 0; // SCK置低}return(byte); // 返回读出的数据(从机的答复)}个人对该函数的理解:①函数功能:发送一个八位数据(由高位向低位,一位一位的发送)并接受从从机返回的数据,函数最后的返回是接受的数据。

②通过MOSI = (byte & 0x80); 的与运算实现先发高位。

特别需要注意的是MOSI MISO 两个都是一位传输的③发送一位数据后,数据左移右侧补0,接受到的一位数据与原先的数据进行或运算,将接受的数据放到最后一位而不影响原数据中尚未发送位上的数据。

如此八个循环后就实现了数据的发送和接受。

SPI_RW()函数理解后,程序中的其他函数都是实现nrf24l01的寄存器的配置,需参见数据手册进行理解(PS中文手册中有一些有错误,必要时可参见英文手册)。

具体的注释在我上发的程序中有详细的注释,请参见该程序。

基于模拟SPI的nrf24l01点对点通信,是nrf24l01 入门的应用,下一步工作我将继续研究基于硬件SPI的nrf24l01点对点通信,以及nrf24l01的点对多通信。

nRF24L01寄存器地址与说明

nRF24L01寄存器地址与说明

nRF24L01寄存器地址与说明nRF24L01是一款新型单片射频收发器件,工作于2.4GHz~2.5GHzISM频段。

内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合了增强型ShockBurst技术,其中输出功率和通信频道可通过程序进行配置。

nRF24L01功耗低,在以-6dBm的功率发射时,工作电流也只有9mA;接收时,工作电流只有12.3mA,多种低功率工作模式,工作在100mw时电流为160mA,在数据传输方面实现相对WiFi距离更远,但传输数据量不如WiFi(掉电模式和空闲模式)使节能设计更方便。

nRF24L01所有的配置字都由配置寄存器来定义,这些配置寄存器可通过SPI口访问。

SPI接口设置SPI接口由SCK,MOSI,MISO及CSN组成。

(1)在配置模式下单片机通过SPI接口配置nRF24L01的工作参数。

(2)在发射或接收模式下单片机SPI接口发送或接收数据。

和SPI接口的指令共有8个,使用每个指令时必须使CSN变低,用完后将其变高。

单片机的控制指令从nRF24L01的MOSI引脚输入,而nRF24L01的状态信息和数据信息是从其MISO引脚输出并送给单片机的。

利用SPI传数时,他是先传低位字节,再传高位字节,并且在传每个字节时是从高位字节传起的。

指令分别是;读寄存器指令,格式是000A AAAA;写寄存器指令,格式是001AAAAA(A AAAA代表寄存器在内存中的地址;读Payload指令;写Payload指令;清发射堆栈指令;清接收堆栈指令;发射数据再利用;空操作。

中断当nRF24L01的中断源(TX_DS,RX_DR,MAX_RT)被置高时(TX_DS为发送成功标志位,RX_DR为接收数据成功标志位,MAX_RT为自动重发超上限标志位),就会使IRQ引脚置低。

可以向状态寄存器写1来清这些中断标志位。

通过设置CONFIG寄存器的某些位来屏蔽掉这些中断源,默认情况下,这三个中断源都是允许的。

NRF24L01通道使用(DOC)

网上面关于多通道通信的好多资源都可以去共享,我也下了好多去调试,结果发现基本上都是调不通的。

其实这个归根到底还是一个地址匹配问题,通道0和1还好说,它是默认开启的,一般没问题,但通道2至5,通道如何匹配,数据手册上也只是说地址要匹配,到底要怎么做它没讲。

下面什么都不说了,直接上程序,这是用PIC16F877A来控制的,我会把要注意的重点标记出来,当然主要是多通道地址匹配的,其它的我就不多说了自己领悟。

接收部分:#include <pic.h> //调用头文件,可以去PICC软件下去查找PIC16F88X单片机的头文件__CONFIG(XT&WDTDIS&LVPDIS&BORDIS); //定义配置字,晶振类型:XT,关闭开门狗,禁止低电压编程,禁止欠压复位#define u8 unsigned char#define u16 unsigned int#define BUZZER RB1u8 i=0,a=0,data[13]=0;#define NRF24L01_MISO RC4#define NRF24L01_MOSI RC5 //输出#define NRF24L01_SCK RC3 //输出#define NRF24L01_CE RC0 //使能控制设为输出#define NRF24L01_CSN RC2 //片选控制设为输出#define NRF24L01_IRQ RC1 //中断标志设为输入#define RS RE0#define RW RE1#define E RE2unsigned char SPIx_ReadWriteByte(unsigned char byte){unsigned char data;SSPBUF=byte;do{;}while(SSPIF==0);SSPIF=0;data=SSPBUF;return(data); // return read byte}//24L01操作线//#define NRF24L01_CE PAout(4) //24L01片选信号//#define NRF24L01_CSN PCout(4) //SPI片选信号//#define NRF24L01_IRQ PCin(5) //IRQ主机数据输入#define READ_REG 0x00 //读配置寄存器,低5位为寄存器地址#define WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字节#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.发射模式下用#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送.#define pop 0xFF //空操作,可以用来读状态寄存器//SPI(NRF24L01)寄存器地址#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能#define EN_AA 0x01 //使能自动应答功能bit0~5,对应通道0~5#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时250*x+86us#define RF_CH 0x05 //RF通道,bit6:0,工作通道频率;#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发//bit5:数据发送完成中断;bit6:接收数据中断;#define MAX_TX 0x10 //达到最大发送次数中断#define TX_OK 0x20 //TX发送完成中断#define RX_OK 0x40 //接收到数据中断#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器#define CD 0x09 //载波检测寄存器,bit0,载波检测;#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法#define FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RXFIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;///////////////////////////////////////////////////// /////////////////////////////////////////24L01发送接收数据宽度定义#define TX_ADR_WIDTH 5 //5字节的地址宽度#define RX_ADR_WIDTH 5 //5字节的地址宽度#define TX_PLOAD_WIDTH 32 //20字节的用户数据宽度#define RX_PLOAD_WIDTH 32 //20字节的用户数据宽度void NRF24L01_Init(void);//初始化void RX_Mode(void);//配置为接收模式void TX_Mode(void);//配置为发送模式u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//读数据区u8 NRF24L01_Read_Reg(u8 reg);//读寄存器u8 NRF24L01_Write_Reg(u8 reg, u8 value);//写寄存器u8 NRF24L01_Check(void);//检查24L01是否存在u8 NRF24L01_TxPacket(u8 *txbuf);//发送一个包的数据u8 NRF24L01_RxPacket(u8 *rxbuf);//接收一个包的数据const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x0 1}; //本地发送地址const u8 RX_ADDRESS0[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0 x01}; //接收0通道地址const u8 RX_ADDRESS1[RX_ADR_WIDTH]={0xc2,0xc2,0xc2,0xc2,0x c1}; //接收1通道地址const u8 RX_ADDRESS2[1]={0xb3}; //接收2通道地址const u8 RX_ADDRESS3[1]={0xa5}; //接收3通道地址const u8 RX_ADDRESS4[1]={0x35}; //接收4通道地址const u8 RX_ADDRESS5[1]={0x8f}; //接收5通道地址/********************************************/void delay1(unsigned char n){unsigned int m;for(;n>0;n--)for(m=0;m<100;m++){asm("NOP");}}void lcd_busy(){TRISD7=1; /*1602上DB7=1表明总线忙,同时RS=0 选择指令寄存器,RSS=1是选择数据寄存器*/RS=0;RW=1;E=1;while(RD7==1);E=0;TRISD7=0;}void lcd_write_commend(unsigned char u){lcd_busy();RS=0;RW=0;PORTD=u;E=1;asm("NOP");E=0;}void lcd_write_data(unsigned char k){lcd_busy();RS=1;RW=0;PORTD=k;E=1;asm("NOP");E=0;}void lcd_1602_ddram_add(u8 x,u8 y)//x是列,y是行,ddram是字符显示的地址{if(y==1){lcd_write_commend(0x80+x);}if(y==2){lcd_write_commend(0xc0+x);}}void lcd_disp(unsigned char x,unsigned char y,unsigned char l){x&=0x0f;//列地址限制在0-15y&=0x01;if(y==0x00)lcd_write_commend(x|0x80); //第一行的列地址写入elselcd_write_commend((x+0x40)|0x80); //第二行的列地址写入lcd_write_data(l+0x30);}void lcd_1602_display_shu(u8 num,u16 shu,u8 x,u8 y)//在液晶的任何位置显示五位内的数字{u8 wan,qian,bai,shi,ge;if(num>=1) ge=shu%10;if(num>=2) shi=shu%100/10;if(num>=3) bai=shu%1000/100;if(num>=4) qian=shu%10000/1000; if(num==5) wan=shu/10000;lcd_1602_ddram_add(x,y);if(num==1)lcd_write_data(ge|0x30);if(num==2){lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}if(num==3){lcd_write_data(bai|0x30);lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}if(num==4){lcd_write_data(qian|0x30);lcd_write_data(bai|0x30);lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}if(num==5){lcd_write_data(wan|0x30);lcd_write_data(qian|0x30);lcd_write_data(bai|0x30);lcd_write_data(shi|0x30);lcd_write_data(ge|0x30);}}void init_1602(){TRISD=0x00;TRISE=0x00;ADCON1=0X82;PORTE=0;PORTD=0;lcd_write_commend(0x38); /*这里的设置是更具需要,选择1602的各项配置,1602共有11条指令*/delay1(100);lcd_write_commend(0x38); /*这里的设置是更具需要,选择1602的各项配置,1602共有11条指令*/delay1(100);lcd_write_commend(0x38); /*这里的设置是更具需要,选择1602的各项配置,1602共有11条指令*/delay1(100);lcd_write_commend(0x38); //8位数据,双列,5*7字形lcd_write_commend(0x08);//显示功能关,无光标lcd_write_commend(0x01);//清屏指令lcd_write_commend(0x06);//写入新的数据后,光标右移,显示屏不移动lcd_write_commend(0x0c);//显示功能开,无光标,}/**********************汉字显示的代码******************************/const u8 hz1[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x11,0x1F};//日const u8 hz2[]={0x0F,0x09,0x0F,0x09,0x0F,0x09,0x09,0x13};//月const u8 hz3[]={0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02};//年const u8 hz4[]={0x1F,0x1F,0x04,0x04,0x04,0x04,0x1F,0x1F};//工const u8 hz5[]={0x0E,0x0A,0x0E,0x1F,0x04,0x07,0x03,0x01};//号void CGRAM(const u8 *hz,const u8 temp) //自定义字符存储{u8 i;for(i=0;i<8;i++){lcd_write_commend(temp+i);lcd_write_data(*(hz+i));}}/*******************************************///SPI写寄存器//reg:指定寄存器地址//value:写入的值u8 NRF24L01_Write_Reg(u8 reg,u8 value){u8 status;NRF24L01_CSN=0; //使能SPI传输status =SPIx_ReadWriteByte(reg);//发送寄存器号SPIx_ReadWriteByte(value); //写入寄存器的值NRF24L01_CSN=1; //禁止SPI传输return(status); //返回状态值}//读取SPI寄存器值//reg:要读的寄存器u8 NRF24L01_Read_Reg(u8 reg){u8 reg_val;NRF24L01_CSN = 0; //使能SPI传输SPIx_ReadWriteByte(reg); //发送寄存器号reg_val=SPIx_ReadWriteByte(0XFF);//读取寄存器内容NRF24L01_CSN = 1; //禁止SPI传输return(reg_val); //返回状态值}//在指定位置读出指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len){u8 status,u8_ctr;NRF24L01_CSN = 0; //使能SPI传输status=SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_Rea dWriteByte(0XFF);//读出数据NRF24L01_CSN=1; //关闭SPI传输return status; //返回读到的状态值}//在指定位置写指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len){u8 status,u8_ctr;NRF24L01_CSN = 0; //使能SPI传输status = SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //写入数据NRF24L01_CSN = 1; //关闭SPI传输return status; //返回读到的状态值}//启动NRF24L01发送一次数据//txbuf:待发送数据首地址//返回值:0,接收完成;其他,错误代码u8 NRF24L01_RxPacket(u8 *rxbuf){u8 sta;//SPIx_SetSpeed(SPI_SPEED_8); //spi速度为9Mhz (24L01的最大SPI时钟为10Mhz)sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值NRF24L01_Write_Reg(WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志if(sta&RX_OK)//接收到数据{NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WID TH);//读取数据NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器return 0;}return 1;//没收到任何数据}//该函数初始化NRF24L01到RX模式//设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR //当CE变高后,即进入RX模式,并可以接收数据了void RX_Mode(void){NRF24L01_CE=0;NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)TX_ ADDRESS,RX_ADR_WIDTH);//接收设备接收通道0使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P1,(u8*)RX_ ADDRESS1,RX_ADR_WIDTH);//接收设备接收通道1使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P2,(u8*)RX_ ADDRESS2,1);//接收设备接收通道2使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P3,(u8*)RX_ ADDRESS3,1);//接收设备接收通道3使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P4,(u8*)RX_ ADDRESS4,1);//接收设备接收通道4使用和发送设备相同的发送地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P5,(u8*)RX_ ADDRESS5,1);//接收设备接收通道5使用和发送设备相同的发送地址NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x3f);//使能通道0到5的自动应答NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x3f);//使能通道0到5的接收地址NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //设置RF通信频率NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_ WIDTH);//选择通道0的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P1,RX_PLOAD_ WIDTH);//选择通道1的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P2,RX_PLOAD_ WIDTH);//选择通道2的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P3,RX_PLOAD_ WIDTH);//选择通道3的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P4,RX_PLOAD_ WIDTH);//选择通道4的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RX_PW_P5,RX_PLOAD_ WIDTH);//选择通道5的有效数据宽度NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式NRF24L01_CE = 1; //CE为高,进入接收模式}void delay(unsigned int m){unsigned int n;n=m;for(;n>0;n--)NOP();}void spi_init(){TRISC=0x13;SSPSTAT=0xc0;SSPCON=0x20;}void INT1(){TRISB=0x00;PORTB=0xfc;INTEDG = 1;INTF = 0;INTE = 1;GIE = 1;}void main(){u8 x=3;spi_init();init_1602();INT1();NRF24L01_CE=0;// chip enableNRF24L01_CSN=1;// Spi disable//NRF24L01_SCK=0;// Spi clock line init highCGRAM(hz1,0x40);CGRAM(hz2,0x48);CGRAM(hz3,0x50);CGRAM(hz4,0x58);CGRAM(hz5,0x60);//将这五个字写到1602用户自定义CGRAM中while(1){RX_Mode();NOP();if(NRF24L01_RxPacket(data)==0){lcd_write_commend(0x80);//第一行第一个字lcd_write_data(0x52);//显示接收的字母Rlcd_1602_display_shu(4,2013,x,1);//显示4位数的年份lcd_write_data(2); //显示汉字年lcd_1602_display_shu(2,8,x+5,1);//显示月份lcd_write_data(1); //显示汉字月lcd_1602_display_shu(2,7,x+8,1);//显示日期lcd_write_data(0); //显示汉字日lcd_write_commend(0xc0);//第二行显示lcd_write_data(3); //显示汉字工lcd_write_data(4); //显示汉字号lcd_write_commend(0xc0|0x02);//隔两格lcd_write_data(0x3A);//显示封号for(i=0;i<13;i++)//显示工人编号{lcd_disp(i+3,1,data[i]);}if(data[12]==1)RB0=1;elseRB0=0;}}}void interrupt ISR(void) {u16 y;if(INTF == 1){INTF = 0;asm("NOP");for(y=0;y<4000;y++){BUZZER=1;delay(20);BUZZER=0;}}}发送部分:#include <pic.h> //调用头文件,可以去PICC软件下去查找PIC16F88X单片机的头文件__CONFIG(XT&WDTDIS&LVPDIS&BORDIS); //定义配置字,晶振类型:XT,关闭开门狗,禁止低电压编程,禁止欠压复位#define u8 unsigned char#define u16 unsigned int#define key RB0u8 test[13]={2,0,1,2,5,8,0,8,0,2,1,5};u16 i=0;#define NRF24L01_MISO RC4#define NRF24L01_MOSI RC5 //输出#define NRF24L01_SCK RC3 //输出#define NRF24L01_CE RC0 //使能控制设为输出#define NRF24L01_CSN RC2 //片选控制设为输出#define NRF24L01_IRQ RC1 //中断标志设为输入*/#define RS RE0 //数据/命令选择#define RW RE1 //读/写选择#define E RE2 //使能信号unsigned char SPIx_ReadWriteByte(unsigned char byte){unsigned char data;SSPBUF=byte;do{;}while(SSPIF==0);SSPIF=0;data=SSPBUF;return(data); // return read byte}#define READ_REG 0x00 //读配置寄存器,低5位为寄存器地址#define WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.发射模式下用#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送.#define pop 0xFF //空操作,可以用来读状态寄存器//SPI(NRF24L01)寄存器地址#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能#define EN_AA 0x01 //使能自动应答功能bit0~5,对应通道0~5#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时250*x+86us#define RF_CH 0x05 //RF通道,bit6:0,工作通道频#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发//bit5:数据发送完成中断;bit6:接收数据中断;#define MAX_TX 0x10 //达到最大发送次数中断#define TX_OK 0x20 //TX发送完成中断#define RX_OK 0x40 //接收到数据中断#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器#define CD 0x09 //载波检测寄存器,bit0,载波检测;#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法#define FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;///////////////////////////////////////////////////// ///////////////////////////////////////////////////////24L01发送接收数据宽度定义#define TX_ADR_WIDTH 5 //5字节的地址宽度#define RX_ADR_WIDTH 5 //5字节的地址宽度#define TX_PLOAD_WIDTH 32 //20字节的用户数据宽度#define RX_PLOAD_WIDTH 32 //20字节的用户数据宽度void NRF24L01_Init(void);//初始化void RX_Mode(void);//配置为接收模式void TX_Mode(void);//配置为发送模式u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//读数据区u8 NRF24L01_Read_Reg(u8 reg);//读寄存器u8 NRF24L01_Write_Reg(u8 reg, u8 value);//写寄存器u8 NRF24L01_Check(void);//检查24L01是否存在u8 NRF24L01_TxPacket(u8 *txbuf);//发送一个包的数据u8 NRF24L01_RxPacket(u8 *rxbuf);//接收一个包的数据//下面这里就是重点啦,看看我用线条标出的是32位公用的地址,红色部分是低八位,注意位置啊啊啊啊啊啊const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x35,0xc2,0xc2,0xc2,0xc 1}; //发送地址const u8 RX_ADDRESS0[RX_ADR_WIDTH]={0x35,0xc2,0xc2,0xc2,0x c1}; //接收3通道地址,就以通道3为例,其它都一个样//SPI写寄存器//reg:指定寄存器地址//value:写入的值u8 NRF24L01_Write_Reg(u8 reg,u8 value){u8 status;NRF24L01_CSN=0; //使能SPI传输status =SPIx_ReadWriteByte(reg);//发送寄存器号SPIx_ReadWriteByte(value); //写入寄存器的值NRF24L01_CSN=1; //禁止SPI传输return(status); //返回状态值}//读取SPI寄存器值//reg:要读的寄存器u8 NRF24L01_Read_Reg(u8 reg){u8 reg_val;NRF24L01_CSN = 0; //使能SPI传输SPIx_ReadWriteByte(reg); //发送寄存器号reg_val=SPIx_ReadWriteByte(0XFF);//读取寄存器内容NRF24L01_CSN = 1; //禁止SPI传输return(reg_val); //返回状态值}//在指定位置读出指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len){u8 status,u8_ctr;NRF24L01_CSN =0; //使能SPI传输status=SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_ReadWriteByte(0XFF);//读出数据NRF24L01_CSN=1; //关闭SPI传输return status; //返回读到的状态值}//在指定位置写指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len){u8 status,u8_ctr;NRF24L01_CSN = 0; //使能SPI传输status = SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //写入数据NRF24L01_CSN = 1; //关闭SPI传输return status; //返回读到的状态值}void delay(unsigned int n){for(;n>0;n--)NOP();}//启动NRF24L01发送一次数据//txbuf:待发送数据首地址//返回值:发送完成状况u8 NRF24L01_TxPacket(u8 *txbuf){u8 sta;//SPIx_SetSpeed(SPI_SPEED_8);//spi速度为9Mhz (24L01的最大SPI时钟为10Mhz)NRF24L01_CE=0; NRF24L01_IRQ=0;NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WID TH);//写数据到TX BUF 32个字节delay(5000);NRF24L01_CE=1;//启动发送delay(5000);while(NRF24L01_IRQ!=0);//等待发送完成sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值NRF24L01_Write_Reg(WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志if(sta&MAX_TX)//达到最大重发次数{NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器return MAX_TX;}if(sta&TX_OK)//发送完成{return TX_OK;}elsereturn 0xff;//其他原因发送失败}//该函数初始化NRF24L01到TX模式//设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR//PWR_UP,CRC使能//当CE变高后,即进入RX模式,并可以接收数据了//CE为高大于10us,则启动发送.void TX_Mode(void){NRF24L01_CE=0;NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(u8*)TX_ADD RESS,TX_ADR_WIDTH);//写TX节点地址NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)RX_ ADDRESS0,RX_ADR_WIDTH); //设置RX节点地址,主要为了使能ACK,TX_ADDRESS和RX_ADDRESS0一定要一致,不然就调不通的NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);//使能通道0的自动应答NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次NRF24L01_Write_Reg(WRITE_REG+RF_CH,40);//设置RF通道为40NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断NRF24L01_CE=1;//CE为高,10us后启动发送NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();}void delay1(unsigned int n){unsigned int m;for(;n>0;n--)for(m=0;m<100;m++){asm("NOP");}}void read_1602_bz()//测忙{TRISD7=1;RS=0;RW=1;E=1;while(RD7==1);E=0;TRISD7=0;}void write_1602_dat(u8 data_1)//写数据{read_1602_bz();RS=1;RW=0;PORTD=data_1;delay(5);E=1;delay(5);E=0;}void write_1602_com(u8 com)//写指令{read_1602_bz();RS=0;RW=0;PORTD=com;delay(5);E=1;delay(5);E=0;}void lcd_1602_ddram_add(u8 x,u8 y)//x是列,y是行,ddram是字符显示的地址{if(y==1){write_1602_com(0x80+x);}if(y==2){write_1602_com(0xc0+x);}}void lcd_disp(unsigned char x,unsigned char y,unsigned charl){x&=0x0f;//列地址限制在0-15y&=0x01;if(y==0x00)write_1602_com(x|0x80); //第一行的列地址写入elsewrite_1602_com((x+0x40)|0x80); //第二行的列地址写入write_1602_dat(l+0x30);}void lcd_1602_display_shu(u8 num,u16 shu,u8 x,u8 y)//在液晶的任何位置显示五位内的数字{u8 wan,qian,bai,shi,ge;if(num>=1) ge=shu%10;if(num>=2) shi=shu%100/10;if(num>=3) bai=shu%1000/100;if(num>=4) qian=shu%10000/1000;if(num==5) wan=shu/10000;lcd_1602_ddram_add(x,y);if(num==1)if(num==2){write_1602_dat(shi|0x30); write_1602_dat(ge|0x30); }if(num==3){write_1602_dat(bai|0x30); write_1602_dat(shi|0x30); write_1602_dat(ge|0x30); }if(num==4){write_1602_dat(qian|0x30); write_1602_dat(bai|0x30); write_1602_dat(shi|0x30); write_1602_dat(ge|0x30); }if(num==5){write_1602_dat(wan|0x30);write_1602_dat(bai|0x30);write_1602_dat(shi|0x30);write_1602_dat(ge|0x30);}}/**********************汉字显示的代码******************************/const u8 hz1[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x11,0x1F};//日const u8 hz2[]={0x0F,0x09,0x0F,0x09,0x0F,0x09,0x09,0x13};//月const u8 hz3[]={0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02};//年void CGRAM(const u8 *hz,const u8 temp) //自定义字符存储{u8 i;for(i=0;i<8;i++){write_1602_com(temp+i);write_1602_dat(*(hz+i));}void init_1602(){TRISE=0x00;TRISD=0x00;//ADCON1=0X82;PCFG3=0;PCFG2=1;PCFG1=1;PCFG0=1; //A端口全部数字化PORTE=0;PORTD=0;write_1602_com(0x38);delay(50);write_1602_com(0x38);delay(50);write_1602_com(0x38);delay(50);write_1602_com(0x0c);write_1602_com(0x06);write_1602_com(0x01);void spi_init(){TRISC=0x13;SSPCON=0x20;SSPSTAT=0xc0;PIR1=0;}void main(){u8 x=3;TRISB0=0;spi_init();init_1602();CGRAM(hz1,0x40);CGRAM(hz2,0x48);CGRAM(hz3,0x50);//将这三个字写到1602用户自定义CGRAM中NRF24L01_CE=0; //使能24L01NRF24L01_CSN=1;//SPI片选取消SPIx_ReadWriteByte(0xff);//启动传输while(1){TX_Mode();if(key==0){delay(1);if(key==0)test[12]=1;}elsetest[12]=0;if(NRF24L01_TxPacket(test)==TX_OK){write_1602_com(0x80);//第一行第一个位置write_1602_dat(0x53);//显示发送的字母Slcd_1602_display_shu(4,2013,x,1);//显示4位数的年份write_1602_dat(2); //显示汉字年lcd_1602_display_shu(2,8,x+5,1);//显示月份write_1602_dat(1); //显示汉字月lcd_1602_display_shu(2,7,x+8,1);//显示日期write_1602_dat(0); //显示汉字日write_1602_com(0xc0);//第二行显示write_1602_dat(0x49); //显示字母Iwrite_1602_dat(0x44); //显示字母Dwrite_1602_com(0xc0|0x02);//隔两格write_1602_dat(0x3A);//显示封号for(i=0;i<13;i++)//显示工人编号{lcd_disp(i+3,1,test[i]);}}}}。

nrf24l01通讯协议

竭诚为您提供优质文档/双击可除nrf24l01通讯协议篇一:nRF24l01无线通信模块使用手册12深圳市德普施科技有限公司nRF24l01无线通信模块使用手册一、模块简介该射频模块集成了noRdic公司生产的无线射频芯片nRF24l01:1.支持2.4ghz的全球开放ism频段,最大发射功率为0dbm2.2mbps,传输速率高3.功耗低,等待模式时电流消耗仅22ua4.多频点(125个),满足多点通信及跳频通信需求5.在空旷场地,有效通信距离:25m(外置天线)、10m(pcb天线)6.工作原理简介:发射数据时,首先将nRF24l01配置为发射模式,接着把地址tx_addR和数据tx_pld按照时序由spi口写入nRF24l01缓存区,tx_pld必须在csn为低时连续写入,而tx_addR在发射时写入一次即可,然后ce置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24l01在发射数据后立即进入接收模式,接收应答信号。

如果收到应答,则认为此次通信成功,tx_ds置高,同时tx_pld从发送堆栈中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(aRc_cnt)达到上限,max_Rt置高,tx_pld不会被清除;max_Rt或tx_ds 置高时,使iRq变低,以便通知mcu。

最后发射成功时,若ce为低,则nRF24l01进入待机模式1;若发送堆栈中有数据且ce为高,则进入下一次发射;若发送堆栈中无数据且ce为高,则进入待机模式2。

接收数据时,首先将nRF24l01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。

当接收方检测到有效的地址和cRc时,就将数据包存储在接收堆栈中,同时中断标志位Rx_dR置高,iRq变低,以便通知mcu去取数据。

若此时自动应答开启,接收方则同时进入发射状态回传应答信号。

最后接收成功时,若ce变低,则nRF24l01进入空闲模式1。

nRF24L01P产品说明书V1.0综述

nRF24L01+单片机2.4 GHz收发器产品说明书v1.0主要功能:全球通用的2.4 GHz ISM波段操作250kbps, 1Mbps and 2Mbps空中数据传输速率超低功率运行发射功率为0dBm(1.0mW)时,发射电流为11.3mA2Mbps空中数据传输速率,接收电流为13.5mA掉电电流为900nA待机-I电流26μA片内电压调整器1.9至3.6V电源供电范围增强型ShockBurst TM自动数据包处理自动包数据包事务处理6数据通道的MultiCeiver TM与nRF24L01嵌入式兼容空中数据速率250kbps 和1Mbps,与nRF2401A,nRF2402, nRF24E1和nRF24E2兼容低BOM成本±60ppm 16MHz晶振容许5V输入紧凑的20引脚4x4mm QFN封装应用无线 PC外围设备鼠标,键盘和遥控器三和一桌面捆绑先进的媒体中心遥控器网络电话耳机游戏控制器蓝牙模块运动手表和传感器消费电子产品射频遥控器家庭和商业自动化超低功率无线传感器网络RFID 射频识别资产跟踪系统玩具免责条款北欧半导体ASA有权做出随时更改,提高产品可靠性、功能或设计,不另行通知。

北欧半导体ASA不承担由于应用程序或使用任何所述产品或电路引起的责任。

所有应用程序的信息咨询,不构成说明书的组成部分。

极限值超过一个或多个限制的应力可能会造成设备永久性损坏。

这些应力等级只有在这样或那样的操作环境中提出,在规范中没有给出。

长时间暴露在限制值附近可能会影响设备的可靠性。

生命支持应用这些产品并非为因故障会引起人身伤害的维生装备,设备或系统设计的。

北欧半导体ASA客户使用或出售这些产品,他们将自担风险并同意完全赔偿北欧半导体ASA因使用不当或销售行为造成任何损害。

详细联系方式访问www.nordicsemi.no进入北欧半导体销售办事处和全世界的分销商网站总办公室:Otto Nielsens vei 127004 Trondheim电话: +47 72 89 89 00传真: +47 72 89 89 89www.nordicsemi.no写作惯例本产品规范遵循一套排版规则,文档一致,容易阅读。

【电子模块设计】NRF24L01使用说明书

NRF24L01使用说明1 NRF24L01功能框图Fig.1 NRF24L01 BLOCK DIAGRAMNRF24L01的框图如 Fig.1所示,从单片机控制的角度来看,我们只需要关注 Fig.1右面的六个控制和数据信号,分别为 CSN、SCK、MISO、MOSI、IRQ、CE。

CSN:芯片的片选线,CSN为低电平芯片工作。

SCK:芯片控制的时钟线(SPI时钟)MISO:芯片控制数据线(Master input slave output)MOSI:芯片控制数据线(Master output slave input)IRQ:中断信号。

无线通信过程中 MCU主要是通过 IRQ与 NRF24L01进行通信。

CE:芯片的模式控制线。

在 CSN为低的情况下,CE协同 NRF24L01的 CONFIG寄存器共同决定 NRF24L01的状态(参照 NRF24L01的状态机)。

2 NRF24L01状态机NRF24L01的状态机见 Fig.2所示,对于 NRF24L01的固件编程工作主要是参照NRF24L01的状态机。

主要有以下几个状态Power Down Mode:掉电模式Tx Mode:发射模式Rx Mode:接收模式Standby-1Mode:待机1模式Standby-2 Mode:待机2模式上面五种模式之间的相互切换方法以及切换所需要的时间参照 Fig.2。

Fig.2 NRF24L01 State Machine对 24L01的固件编程的基本思路如下:1)置 CSN为低,使能芯片,配置芯片各个参数。

(过程见 3.Tx与 Rx的配置过程)配置参数在 Power Down状态中完成。

2)如果是 Tx模式,填充 Tx FIFO。

3)配置完成以后,通过 CE与 CONFIG中的 PWR_UP与 PRIM_RX参数确定 24L01 要切换到的状态。

Tx Mode:PWR_UP=1; PRIM_RX=0; CE=1 (保持超过 10us就可以);Rx Mode: PWR_UP=1; PRIM_RX=1; CE=1;4) IRQ引脚会在以下三种情况变低:Tx FIFO发完并且收到 ACK(使能 ACK情况下)Rx FIFO收到数据达到最大重发次数将 IRQ接到外部中断输入引脚,通过中断程序进行处理。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档