NRF24L01参考程序(包含多个实例)
最新nrf24L01工作流程图型

n r f24L01工作流程
图型
NRF24L01流程图、引脚定义
N Y Y
N
N 开始
时钟IC 、LCD 液晶、温度传nRF24L01配置模式
判断键盘
数据采集 将采集到的数启动发射 发射是否完成? 按键处理子程是否处理
开始上电 待机模式I
CE=1有数据发射处理 发射模式
自动重NO_AC
K 有接收处理 置位置位CE=1有数据有数据CE=1待机模式
应答是应答 把ACK 加
置位TX_DS 发射处理
发射模式 接收模式 待机模式I CE=1CE=1接收处理 开始上电 接收接收到 自动应
是新数把数据包放入接收
FIFO 并置位RX_DR 丢弃该数据
把数据包放入接收FIFO 并置位RX_DR
开始
初始化串
数据发送结
把数据装载到
结束
S T C 89C 58
nRF24L01无线模块 LCD 液晶显示模块
键盘模块。
NRF24L01详细教程

NRF24L01详细教程近来课程的项目需要用到NRF24L01,用来做基本的收发,虽然资料拿到不少,但是,很多资料并不是很清晰、所带的例程并不够简洁或有不少冗余的部分,再加上对应的中文数据手册部分没翻译出来,翻译出来的不够有条理,很多地方模糊,甚至关键的地方看一两次还看不出来,导致了在学NRF24L01时花费了较多时间,所以,学完NRF24L01后,萌生了写个尽量清晰的教程的想法。
教程中的例程虽然是库开发方式,但基本都是最底层的操作才用到库函数譬如发一字节数据、GPIO置位等,虽然用的STM32,但我在看其他板子的例程时,发觉内容与流程都是差不多的,只是不同板引脚不同所导致的引脚配置的不同,不管用什么方式开发,用什么芯片,了解清楚NRF24L01如何配置,了解清楚其收发流程,基本上就会开发了,所以此文档虽然写的是以STM32为例,但看完此文档用NRF24L01基本也没什么大问题了。
教程说明:这教程是基于STMF103ZET6的,是野火的板子,例程也是从野火提供修改例程得来,用的是库开发的方式。
学习NRF24L01的步骤:1.学习SPI,SPI就是NRF24L01传送数据到单片机的一种协议,类似于USB,当然USB还是比较有难度的。
2.了解NRF24L01相关寄存器,结合中文数据手册了解NRF24L01的基本配置,收发数据前后的操作(如何启动发送接收、寄存器清空、标志位重置等)。
3.分析具体代码SPI的简介:具体的SPI教程,大家可以去野火的教程进行学习,在此只是简略介绍一下,SPI是一种一对多协议:一个主机(MCU)对应对多个从机,可以分时与多个从机通讯SPI 总线包含4 条总线,分别为SS、SCK、MOSI、MISO,其含义分别为SS:Slave Select,片选信号线,主机借此信号线选择一个从机,低电平有效。
MOSI:Master Output,Slave Input,主机数据从此线输出到从机,数据方向从主机到从机。
NRF24L01模块写论文可以用到的

(2)无线模块的选择模块方案一:采用nRF24L01无线收发芯片组成智能家庭安全系统的自适应无线传感和控制网络,网络拓扑图如图所示。
nRF24L01是一款新型单片射频收发器件。
工作于2.4 GHz~2。
5 GHz ISM频段。
内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合了增强型ShockBurst技术,其中输出功率和通信频道可通过程序进行配置。
nRF24L01功耗低,在以一6 dBm的功率发射时,工作电流也只有9 mA;接收时,工作电流只有12.3 mA,多种低功率工作模式(掉电模式和空闲模式)使节能设计更方便。
nRF24L01主要特性如下:GFsK调制:硬件集成OSI链路层;具有自动应答和自动再发射功能:片内自动生成报头和CRC校验码;数据传输率为l Mb/s或2 Mb/s;SPI速率为0 Mb/s~10 Mb/s;125个频道:与其他nRF24系列射频器件相兼容;QFN20引脚4 mmx4 rain封装;供电电压为1.9 V~3.6 V。
而且nRF24L01价格在20元左右,性价比高。
为有效的实现对全局环境的检测,系统建立了无线传感网络,无线传感器网络拓扑图如图2-2所示。
图2-2 无线传感器网络拓扑图方案二:CC1100 是原Ch ipcon 公司推出的一种低成本、真正单片的超高频无线收发器, 为低功耗无线应用而设计。
整个应用电路的无线频率主要设定在315MHz、433MHz、868MHz 和915MHz 四个ISM (工业、科学和医学) 频段上, 也可以容易地设置为300MHz~348MHz、400MHz~ 464MHz 和800MHz~ 928MHz 的其它频率上。
芯片低电压(217V~ 316V ) 供电并且功耗较低(接收数据时为1516mA、214kbö s、433MHz)、灵敏度高(112kbös 下为110dBm ) , 可编程控制的数据传输率最高可达500kbö s。
NRF24L01无线模块C语言程序

NRF24L01无线模块C语言法式之巴公井开创作24MHz晶振#include#include#include#include#include#include#define U8 unsigned char#define U16 unsigned int#define TX_ADDR_WITDH 5 //发送地址宽度设置为5个字节#define RX_ADDR_WITDH 5 //接收地址宽度设置为5个字节#define TX_DATA_WITDH 1//发送数据宽度1个字节#define RX_DATA_WITDH 1//接收数据宽度1个字节#define R_REGISTER 0x00//读取配置寄存器#define W_REGISTER 0x20//写配置寄存器#define R_RX_PAYLOAD 0x61//读取RX有效数据#define W_TX_PAYLOAD 0xa0//写TX有效数据#define FLUSH_TX 0xe1//清除TXFIFO寄存器#define FLUSH_RX 0xe2//清除RXFIFO寄存器#define REUSE_TX_PL 0xe3//重新使用上一包有效数据#define NOP 0xff//空把持#define CONFIG 0x00//配置寄存器#define EN_AA 0x01//使能自动应答#define EN_RXADDR 0x02//接收通道使能0-5个通道#define SETUP_AW 0x03//设置数据通道地址宽度3-5#define SETUP_RETR 0x04//建立自动重发#define RF_CH 0x05//射频通道设置#define RF_SETUP 0x06//射频寄存器#define STATUS 0x07//状态寄存器#define OBSERVE_TX 0x08//发送检测寄存器#define CD 0x09//载波#define RX_ADDR_P0 0x0a//数据通道0接收地址#define RX_ADDR_P1 0x0b//数据通道1接收地址#define RX_ADDR_P2 0x0c//数据通道2接收地址#define RX_ADDR_P3 0x0d//数据通道3接收地址#define RX_ADDR_P4 0x0e//数据通道4接收地址#define RX_ADDR_P5 0x0f//数据通道5接收地址#define TX_ADDR 0x10//发送地址#define RX_PW_P0 0x11//P0通道数据宽度设置#define RX_PW_P1 0x12//P1通道数据宽度设置#define RX_PW_P2 0x13//P2通道数据宽度设置#define RX_PW_P3 0x14//P3通道数据宽度设置#define RX_PW_P4 0x15//P4通道数据宽度设置#define RX_PW_P5 0x16//P5通道数据宽度设置#define FIFO_STATUS 0x17//FIFO状态寄存器//NRF24L01U8 NRFACK();U8 NRFSPI(U8 date);U8 NRFReadReg(U8 RegAddr);U8 NRFWriteReg(U8 RegAddr,U8 date);U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen);U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen);U8 NRFRevDate(U8 *RevDate);void NRFSetTxMode(U8 *TxDate);void NRF24L01Int();void NRFSetRXMode();U8 CheckACK();void Delay(U16 t);U8 bdata sta;//mainvoid Delay_10ms(U16 del);bit CE=P1^4; //RX/TX模式选择端sbit IRQ=P1^1; //可屏蔽中断端sbit CSN=P1^6; //SPI片选端//就是SSsbit MOSI=P1^0; //SPI主机输出从机输入端1sbit MISO=P1^2; //SPI主机输入从机输出端sbit SCLK=P1^3; //SPI时钟端U8 code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址U8 bdata sta; //状态标识表记标帜sbit RX_DR=sta^6;sbit TX_DS=sta^5;sbit MAX_RT=sta^4;void Delay(U16 t){ U16 x,y; for(x=t;x>0;x--) for(y=110;y>0;y--);}U8 NRFSPI(U8 date){U8 i; for(i=0;i<8;i++) // 循环8次{ if(date&0x80) MOSI=1; else MOSI=0; // byte最高位输出到MOSI date<<=1; // 低一位移位到最高位 SCLK=1; if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据, 同时从MISO输出1位数据 date|=0x01; // 读MISO 到byte最低位 SCLK=0; // SCK置低} return(date); // 返回读出的一字节}void NRF24L01Int(){ Delay(2);//让系统什么都不干CE=0; //待机模式1 CSN=1; SCLK=0; IRQ=1; }U8 NRFReadReg(U8 RegAddr){ U8 BackDate; CSN=0;//启动时序NRFSPI(RegAddr);//写寄存器地址BackDate=NRFSPI(0x00);//写入读寄存器指令CSN=1; return(BackDate); //返回状态}U8NRFWriteReg(U8 RegAddr,U8 date){ U8 BackDate; CSN=0;//启动时序BackDate=NRFSPI(RegAddr);//写入地址NRFSPI(date);//写入值CSN=1; return(BackDate);}U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen){ //寄存器地址//读取数据寄存变量//读取数据长度//用于接收U8 BackDate,i; CSN=0;//启动时序BackDate=NRFSPI(RegAddr);//写入要读取的寄存器地址for(i=0;i { RxDate[i]=NRFSPI(0); } CSN=1; return(BackDate);}U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen){ //寄存器地址//写入数据寄存变量//读取数据长度//用于发送U8 BackDate,i; CSN=0; BackDate=NRFSPI(RegAddr);//写入要写入寄存器的地址 for(i=0;i { NRFSPI(*TxDate++); }CSN=1; return(BackDate);}void NRFSetTxMode(U8 *TxDate){//发送模式 CE=0; NRFWriteTxDate(W_REGISTER+TX_ADDR,Tx Addr,TX_ADDR_WITDH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);//写入数据NRFWriteReg(W_REGISTER+EN_AA,0x01);// 使能接收通道0自动应答NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0 NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等候250us+86us,自动重发10次NRFWriteReg(W_REGISTER+RF_CH,0x40);// 选择射频通道0x40 NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放年夜器增益NRFWriteReg(W_REGISTER+CONFIG,0x0e); // CRC 使能,16位CRC校验,上电CE=1; Delay(5);//坚持10us秒以上}//主要接收模式void NRFSetRXMode(){ CE=0; NRFWriteTxDate(W_REGISTER+RX _ADDR_P0,TxAddr,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址NRFWriteReg(W_REGISTER+EN_AA,0x01);// 使能接收通道0自动应答NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);// 使能接收通道0 NRFWriteReg(W_REGISTER+RF_CH,0x40);// 选择射频通道0x40 NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH);// 接收通道0选择和发送通道相同有效数据宽度NRFWriteReg(W_REGISTER+RF_SETUP,0x07);// 数据传输率1Mbps,发射功率0dBm,低噪声放年夜器增益*/ NRFWriteReg(W_REGISTER+CONFIG,0x0f);// CRC使能,16位CRC校验,上电,接收模式CE = 1; Delay(5);//坚持10us秒以上}U8 CheckACK(){ //用于发射sta=NRFReadReg(R_REGISTER+STATUS);// 返回状态寄存器if(TX_DS||MAX_RT) //发送完毕中断{ NRFWriteReg(W_REGISTER+STATUS,0xff); // 清除TX_DS或MAX_RT中断标识表记标帜CSN=0; NRFSPI(FLUSH_TX);//用于清空FIFO !!关键!!否则会呈现意想不到的后果!!!年夜家记住!! CSN=1; return(0); } else return(1);}//用于接收模式U8 NRFRevDate(U8 *RevDate){ U8RevFlags=0; sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器 if(RX_DR) // 判断是否接收到数据{ CE=0; //SPI使能NRFReadRxDate(R_RX_PAYLOAD,RevDate,RX_DATA_WITDH);/ / 从RXFIFO读取数据RevFlags=1; //读取数据完成标识表记标帜} NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标 return(RevFlags);}void Delay_10ms(U16 del){ U16 i,j; for(i=0; i<del; i++) for(j=0; j<1827; j++) //这个是通过软件仿真得出的数;}// 做发射main(){ U8 TxDate[1]={0}; NRF24L01Int(); Delay(6000); while(1) { if(KEY==0) { if(KEY==0) { Delay_1 0ms(2); TxDate[0]=0x08;//发射按键标识值NRFSetTxMode(TxDate); while(CheckACK());TxDate[0]=0; } } }}//// 做接收:一直处于接受模式查询所获得的值是不是0x08main(){ U8 x; U8 RxBuf[1]={0}; NRF24L01Int(); Delay(6000);while(1) { NRFSetRXMode(); NRFRevDate(RxBuf); x=RxBuf[0]; if(x==0x08)//0x08为发射部份所发送的按键标识{ // //加入所要执行的功能函数 //固然了这里用到单片机io口的时候需要在之前界说//还有就是发送法式中的KEY也需要之前界说好 RxBuf[0]=0; } }}。
基于NRF24L01的程序

/*****************************************************************************概述:电气工程及其自动化2009级毕业设计课题:无线信息采集系统的设计与实现文件:无线信息采集系统数据接收端功能:接收数据存储、处理、显示、报警等。
编译:Keil uVision4硬件:AT89C52RC日期:2013年5月作者:蒋海鹏(广西大学行健文理学院)注:代码有些杂乱,头文件封装不建议用“类”封装(有显摆嫌疑,此设计只为练习该封装模式)该形式对普通函数调用是个麻烦。
在写管理器时建议采用该模式*****************************************************************************/ #include "StdC52.h"#define DATA_SIZE 6#define SENDTIME 100#define CHANGEDISPLAY 1#define RETURNDISPLAY 0static UCHAR m_BH1750RxBuff[DATA_SIZE];static UCHAR m_DHT11RxBuff[DA TA_SIZE];static UCHAR m_RxBuff[DATA_SIZE];static void LCD_Display_Init(void){C52LCDGET()->LCD_Display_String(LINE_ONE,0,"RH:"); //湿度C52LCDGET()->LCD_Display_String(LINE_ONE,5,"%");C52LCDGET()->LCD_Display_String(LINE_ONE,7,"TEMP:"); //温度C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0E,0XDF-0x30); //0xdf='°',0x43='C'C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0F,0X43-0x30); //0xdf='°',0x43='C'C52LCDGET()->LCD_Display_String(LINE_TWO,0,"LIGHT:"); //光强C52LCDGET()->LCD_Display_String(LINE_TWO,0X0B,"Lx"); //光强单位}static void LCD_Display_MODE(void){UINT TempData;UINT CalData;UCHAR RH1,RH2,TP1,TP2;CalData = (m_BH1750RxBuff[0]<<8) + m_BH1750RxBuff[1]; //合成数据,即光照数据TempData = (CalData*100)/120;C52LCDGET()->LCD_Display_Single(LINE_TWO,6,TempData/10000);C52LCDGET()->LCD_Display_Single(LINE_TWO,7,TempData%10000/1000);C52LCDGET()->LCD_Display_Single(LINE_TWO,8,TempData%1000/100);C52LCDGET()->LCD_Display_Single(LINE_TWO,9,TempData%100/10);C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,TempData%10);RH1 = m_DHT11RxBuff[0]/10;RH2 = m_DHT11RxBuff[0]%10;TP1 = m_DHT11RxBuff[2]/10;TP2 = m_DHT11RxBuff[2]%10;C52LCDGET()->LCD_Display_Single(LINE_ONE,3,RH1);C52LCDGET()->LCD_Display_Single(LINE_ONE,4,RH2);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,TP1);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,TP2);}//接收数据static void NRF_RecvSystemData(UCHAR *pUersBuf){static UCHAR l_uCount = NULL;if(C52NRFGET()->NRF_RevDate(pUersBuf)) //读取接受到的数据{switch(l_uCount){case 0X00:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X01:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X02:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X03:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X04:m_BH1750RxBuff[0] = pUersBuf[l_uCount];l_uCount++;break;case 0X05:m_BH1750RxBuff[1] = pUersBuf[l_uCount];l_uCount = NULL;break;default:l_uCount = NULL;break;}C52LCDGET()->LCD_Display_String(LINE_TWO,0X0E,"Rx"); //接受成功C52LEDGET()->TP_Waring();C52LEDGET()->RH_Waring();C52LEDGET()->LX_Waring();}else{C52LEDGET()->Close_Waring();}}//主要实现各按键功能static void Key_Mode(void){UCHAR uReKey = NULL;static UCHAR m_StroeBuff[10];static UCHAR l_uFlag = NULL;//初始光标地址为3static UCHAR uCursor = 3;static UCHAR Store;uReKey = Key_Scan();if(NULL == l_uFlag){C52NRFGET()->NRF_SetRxMode(); //设置为接受模式NRF_RecvSystemData(m_RxBuff);LCD_Display_MODE();}if(DIS_CHANGE == uReKey){l_uFlag = CHANGEDISPLAY;C52IICGET()->C52IIC_Free(TRUE); //释放总线C52LCDGET()->LCD_Display_Single(LINE_ONE,3,C52IIC_Read(0X01)/10);C52LCDGET()->LCD_Display_Single(LINE_ONE,4,C52IIC_Read(0X01)%10);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,C52IIC_Read(0X11)/10);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,C52IIC_Read(0X11)%10);C52LCDGET()->LCD_Display_Single(LINE_TWO,6,C52IIC_Read(0X21));C52LCDGET()->LCD_Display_Single(LINE_TWO,7,C52IIC_Read(0X22));C52LCDGET()->LCD_Display_Single(LINE_TWO,8,C52IIC_Read(0X23));C52LCDGET()->LCD_Display_Single(LINE_TWO,9,C52IIC_Read(0X24));C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,C52IIC_Read(0X25));C52LEDGET()->Close_Waring();}switch(l_uFlag){case LINE_ONE:C52LCDGET()->LCD_Write_Com(0X80+uCursor);C52LCDGET()->LCD_Write_Com(0X0F);if(CURSOR_ADD == uReKey){uCursor++;if(uCursor==5){uCursor = 0X0C;}if(uCursor==0X0E){uCursor = 6;l_uFlag++;}}if(CURSOR_DEC == uReKey){if((uCursor<=4)&&(uCursor>=3)) //4位置时候回3{uCursor--;if(uCursor<3) //如果在3位置回下行末尾{uCursor = 0X0A;l_uFlag++;}}if((uCursor<=0X0D)&&(uCursor>=0X0C)){uCursor--;if(uCursor<0X0C){uCursor = 4;}}}break;case LINE_TWO:C52LCDGET()->LCD_Write_Com(0X80+0X40+uCursor);C52LCDGET()->LCD_Write_Com(0X0F);if(CURSOR_ADD == uReKey){uCursor++;if(uCursor == 0X0B){uCursor = 3;l_uFlag = CHANGEDISPLAY;}}if(CURSOR_DEC == uReKey){if(uCursor>=0X06&&uCursor<=0X0A){uCursor--;if(uCursor<0X06){uCursor = 0X0D;l_uFlag = CHANGEDISPLAY;}}}break;}if(NUM_ADD == uReKey){switch(uCursor){case 0X03:if(++m_StroeBuff[0]>=10) //测量湿度范围20%-95%{m_StroeBuff[0] = 2;}C52LCDGET()->LCD_Display_Single(LINE_ONE,3,m_StroeBuff[0]);break;case 0X04:if(m_StroeBuff[0]!=9){if(++m_StroeBuff[1]>=10){m_StroeBuff[1] = NULL;}}else{if(++m_StroeBuff[1]>=6){m_StroeBuff[1] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_ONE,4,m_StroeBuff[1]);break;case 0X0C:if(++m_StroeBuff[2]>=6) //测量温度范围0-50{m_StroeBuff[2] = NULL;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,m_StroeBuff[2]);break;case 0X0D:if(++m_StroeBuff[3]>=10){m_StroeBuff[3] = NULL;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,m_StroeBuff[3]);break;case 0X06: //光强测量范围1-65535lxif(++m_StroeBuff[4]>=7) //万位最大为6{m_StroeBuff[4] = NULL;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X06,m_StroeBuff[4]);break;case 0X07:if(m_StroeBuff[4] == 6){if(++m_StroeBuff[5]>=6){m_StroeBuff[5] = NULL;}}else{if(++m_StroeBuff[5]>=10){m_StroeBuff[5] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X07,m_StroeBuff[5]);break;case 0X08:if((m_StroeBuff[4]==6)&&(m_StroeBuff[5]==5)){if(++m_StroeBuff[6]>=6){m_StroeBuff[6] = NULL;}}else{if(++m_StroeBuff[6]>=10){m_StroeBuff[6] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X08,m_StroeBuff[6]);break;case 0X09:if((m_StroeBuff[4]==6)&&(m_StroeBuff[5]==5)&&(m_StroeBuff[6]==5)) {if(++m_StroeBuff[7]>=4){m_StroeBuff[7] = NULL;}}else{if(++m_StroeBuff[7]>=10){m_StroeBuff[7] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X09,m_StroeBuff[7]);break;case 0X0A:if((m_StroeBuff[4]==6)&&(m_StroeBuff[5]==5)\&&(m_StroeBuff[6]==5)&&(m_StroeBuff[7]==3)){if(++m_StroeBuff[8]>=6){m_StroeBuff[8] = NULL;}}else{if(++m_StroeBuff[8]>=10){m_StroeBuff[8] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,m_StroeBuff[8]);break;}}if(NUM_DEC ==uReKey){switch(uCursor){case 0X03:if(m_StroeBuff[0]>2) //测量湿度范围20%-95%{m_StroeBuff[0]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,3,m_StroeBuff[0]);break;case 0X04:if(m_StroeBuff[1]>0){m_StroeBuff[1]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,4,m_StroeBuff[1]);break;case 0X0C:if(m_StroeBuff[2]>0) //测量温度范围0-50{m_StroeBuff[2]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,m_StroeBuff[2]);break;case 0X0D:if(m_StroeBuff[3]>0){m_StroeBuff[3]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,m_StroeBuff[3]);break;case 0X06: //光强测量范围1-65535lxif(m_StroeBuff[4]>0) //万位最大为6{m_StroeBuff[4]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X06,m_StroeBuff[4]);break;case 0X07:if(m_StroeBuff[5]>0){m_StroeBuff[5]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X07,m_StroeBuff[5]);break;case 0X08:if(m_StroeBuff[6]>0){m_StroeBuff[6]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X08,m_StroeBuff[6]);break;case 0X09:if(m_StroeBuff[7]>0){m_StroeBuff[7]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X09,m_StroeBuff[7]);break;case 0X0A:if(m_StroeBuff[8]>0){m_StroeBuff[8]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,m_StroeBuff[8]);break;}}if(NUM_AFFIRM == uReKey) //确定数值存入{l_uFlag = RETURNDISPLAY;uCursor = 3; //光标清回三C52LCDGET()->LCD_Write_Com(0x0C); //不显示光标C52IICGET()->C52IIC_Free(TRUE);Store = m_StroeBuff[0]*10 + m_StroeBuff[1]; //存入数值C52IIC_Write(0X01,Store);Store = NULL;Store = m_StroeBuff[2]*10 + m_StroeBuff[3];C52IIC_Write(0X11,Store);Store = NULL;C52NRFGET()->NRF_SetRxMode(); //设置为接受模式C52IIC_Write(0X21,m_StroeBuff[4]);C52IIC_Write(0X22,m_StroeBuff[5]);C52IIC_Write(0X23,m_StroeBuff[6]);C52IIC_Write(0X24,m_StroeBuff[7]);C52IIC_Write(0X25,m_StroeBuff[8]);}}int main(void){C52NRFGET()->NRF_Init();C52LCDGET()->LCD_Init(); //液晶初始化LCD_Display_Init();C52IICGET()->C52IIC_Init(); //IIC初始化C52IICGET()->C52IIC_SetID(0XA0); //设置器件IDC52IICGET()->C52IIC_SetRate(3);C52IICGET()->C52IIC_Free(TRUE); //释放IIC总线while(TRUE){C52NRFGET()->NRF_SetRxMode(); //设置为接受模式Key_Mode();DelayMs(SENDTIME);}}#include "..\StdC52.h"#include "LCD1602.h"static LCD1602 *hLCDBus = NULL;static LCD1602 m_Instance;static void LCD_Write_Com(UCHAR Com){LCDRS = FALSE;GPIOA = Com;DelayMs(5);LCDEN = TRUE;DelayMs(5);LCDEN= FALSE;}static void LCD_Write_Data(UCHAR Date){LCDRS = TRUE;GPIOA = Date;DelayMs(5);LCDEN = TRUE;DelayMs(5);LCDEN = FALSE;}static void LCD_Display_Single(UCHAR Line, UCHAR Address,UCHAR InData) {switch(Line){case 0x01:LCD_Write_Com(0X80+Address);break;case 0x02:LCD_Write_Com(0X80+0X40+Address);break;default:break;}LCD_Write_Data(0X30+InData);}static void LCD_Display_String(UCHAR Line,UCHAR Address,UCHAR *pBuff){switch(Line){case LINE_ONE:LCD_Write_Com(0X80+Address);break;case LINE_TWO:LCD_Write_Com(0X80+0X40+Address);break;default:break;}while(*pBuff!='\0'){LCD_Write_Data(*pBuff++);}}void LCD_Init(void){C52LCDGET()->LCD_Write_Com(0x38); //设置16X2显示,5X7点阵,8位数据接口C52LCDGET()->LCD_Write_Com(0x0c); //设置开显示,不显示光标C52LCDGET()->LCD_Write_Com(0x06); //写一个字符后地址指针加1C52LCDGET()->LCD_Write_Com(0x01); //显示清零,数据指针清零}static void NEW(void){hLCDBus = &m_Instance;hLCDBus->LCD_Init = LCD_Init;hLCDBus->LCD_Write_Com = LCD_Write_Com;hLCDBus->LCD_Write_Data = LCD_Write_Data;hLCDBus->LCD_Display_Single = LCD_Display_Single;hLCDBus->LCD_Display_String = LCD_Display_String;}LCD1602 *C52LCDGET(void){NEW();return hLCDBus;}----------------------------------------------------------------------------------------------------------------------#include "..\StdC52.h"#include "Globle.h"void DelayMs(UINT TimeMs){UCHAR Time;UINT Count;for(Count = TimeMs; Count>0; Count--)for(Time = 0;Time<110;Time++);}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "NRF24L01.h"//状态标志static UCHAR BDA TA m_Status;sbit RX_DR = m_Status^6;sbit TX_DS = m_Status^5;sbit MAX_RT = m_Status^4;//NRF对象指针static NRF *hNRFBus = NULL;//NRF实例static NRF m_Instance;//发送地址static UCHAR code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//NRF24L01初始化函数void NRF_Init(void){DelayMs(2); //让系统什么都不干CE = FALSE; //待机模式1CSN = TRUE;SCK = FALSE;IRQ = TRUE;}//SPI时序函数static UCHAR NRF_SPI(UCHAR uDate){UCHAR i;for(i=0;i<8;i++){if(uDate&0x80){MOSI = TRUE;}else{MOSI = FALSE; // byte最高位输出到MOSI}uDate<<=1; // 低一位移位到最高位SCK = TRUE;if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据{uDate|=0x01; // 读MISO到byte最低位}SCK = FALSE; // SCK置低}return(uDate); // 返回读出的一字节}//SPI读寄存器一字节函数static UCHAR NRF_ReadReg(UCHAR RegAddr){UCHAR BackDate;CSN = FALSE; //启动时序NRF_SPI(RegAddr); //写寄存器地址BackDate=NRF_SPI(R_REGISTER); //写入读寄存器指令CSN = TRUE;return(BackDate); //返回状态}//SPI写寄存器一字节函数static UCHAR NRF_WriteReg(UCHAR RegAddr,UCHAR uDate){UCHAR BackDate;CSN = FALSE; //启动时序BackDate = NRF_SPI(RegAddr); //写入地址NRF_SPI(uDate); //写入值CSN = TRUE;return(BackDate);}//SPI读取RXFIFO寄存器的值//寄存器地址,读取数据存放变量,读取数据长度, 用于接收static UCHAR NRF_ReadRxDate(UCHAR RegAddr,UCHAR *RxDate,UCHAR Len){UCHAR BackDate,i;CSN = FALSE; //启动时序BackDate=NRF_SPI(RegAddr); //写入要读取的寄存器地址for(i=0;i<Len;i++) //读取数据{RxDate[i] = NRF_SPI(R_REGISTER);}CSN = TRUE;return(BackDate);}//SPI写入TXFIFO寄存器的值寄存器地址,写入数据存放变量,读取数据长度,用于发送static UCHAR NRF_WriteTxDate(UCHAR RegAddr,UCHAR *TxDate,UCHAR Len){UCHAR BackDate,i;CSN = FALSE;BackDate=NRF_SPI(RegAddr); //写入要写入寄存器的地址for(i=0;i<Len;i++) //写入数据{NRF_SPI(*TxDate++);}CSN = TRUE;return(BackDate);}//NRF设置为发送模式并发送数据/*void NRF_SetTxMode(UCHAR *TxDate){CE = FALSE;NRF_WriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH); //写寄存器指令+接收地址使能指令+接收地址+地址宽度NRF_WriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); //为了应答接收设备,接收通道0地址和发送地址相同NRF_WriteTxDate(W_TX_PAYLOAD,TxDate,TX_DA TA_WITDH); //写入数据NRF_WriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答NRF_WriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRF_WriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等待250us+86us,自动重发10次NRF_WriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40NRF_WriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益NRF_WriteReg(W_REGISTER+CONFIG,0x0e); // CRC 使能,16位CRC校验,上电CE = TRUE;DelayMs(5); //保持10us秒以上} *///NRF设置为接收模式void NRF_SetRxMode(void){CE = FALSE;NRF_WriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址NRF_WriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答NRF_WriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRF_WriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40NRF_WriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH); // 接收通道0选择和发送通道相同有效数据宽度NRF_WriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/NRF_WriteReg(W_REGISTER+CONFIG,0x0f); // CRC 使能,16位CRC校验,上电,接收模式CE = TRUE;DelayMs(5); //保持10us 秒以上//检测应答信号/*BOOL NRF_CheckACK(void){ //用于发射m_Status = NRF_ReadReg(R_REGISTER+STATUS); // 返回状态寄存器if(TX_DS||MAX_RT) //发送完毕中断{NRF_WriteReg(W_REGISTER+STA TUS,NOP); // 清除TX_DS或MAX_RT中断标志CSN = FALSE;NRF_SPI(FLUSH_TX); //用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!CSN = TRUE;return(FALSE);}elsereturn(TRUE);} *///判断是否接收收到数据,接到就从RX取出用于接收模式UCHAR NRF_RevDate(UCHAR *RevDate){BOOL l_bRevFlags = NULL;m_Status = NRF_ReadReg(R_REGISTER+STATUS); //发送数据后读取状态寄存器if(RX_DR) // 判断是否接收到数据{CE = FALSE; //SPI使能NRF_ReadRxDate(R_RX_PAYLOAD,RevDate,RX_DA TA_WITDH); // 从RXFIFO读取数据l_bRevFlags = TRUE; //读取数据完成标志}else{l_bRevFlags = FALSE;}NRF_WriteReg(W_REGISTER+STA TUS,NOP); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标return(l_bRevFlags);}//创建static void New(void){hNRFBus = &m_Instance;hNRFBus->NRF_Init = NRF_Init;// hNRFBus->NRF_SetTxMode = NRF_SetTxMode;hNRFBus->NRF_SetRxMode = NRF_SetRxMode;hNRFBus->NRF_RevDate = NRF_RevDate;}//获取NRF实例句柄NRF *C52NRFGET(void){New();return hNRFBus;}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "C52IIC.h"#define ReWrTime 10//IIC对象指针static IIC *hIICBus = NULL;//IIC实例static IIC m_Instance;//IIC速率static UINT m_Baudrate = 3;//器件地址static UCHAR m_DeviceID = 0X00;//IIC总线延时static void IICBusDelay(UINT uTime){while(uTime--);}//模拟IIC总线的起始位static void IICBusStart(void){SDA = TRUE; //SDA = 1SCL = TRUE; //SCK = 1IICBusDelay(20);SDA = FALSE; //SDA = 0IICBusDelay(20);}//模拟IIC总线的停止位static void IICBusStop(){SDA = FALSE; //SDA = 0SCL = FALSE; //SCK = 0IICBusDelay(20);SCL = TRUE; //SCK = 1IICBusDelay(20);SDA = TRUE; //SDA = 1IICBusDelay(20);}//读IIC_SDA引脚电平static BOOL SDARead(void){UCHAR i;SCL = TRUE;IICBusDelay(20);while((TRUE == SDA)&&(i<0XFF))i++;if(SDA){return TRUE;}return FALSE;}//模拟IIC总线写一个字节数据(返回ACK)static BOOL IICBusWriteByte(UCHAR WRData){UCHAR i,ACK;for(i=0;i<8;i++){SCL = FALSE; //SCK = 0if( WRData&0x80 ){SDA = TRUE;}else{SDA = FALSE;}IICBusDelay(m_Baudrate);SCL = TRUE; // SCK = 1IICBusDelay(m_Baudrate);WRData = WRData<<1;}SCL = FALSE; //SCK = 0IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1ACK = SDARead(); //读取SDA口高无响应,低响应IICBusDelay(m_Baudrate);SCL = FALSE; //SCK = 0SDA = TRUE; //SDA = 1IICBusDelay(m_Baudrate);return ACK;}//模拟IIC总线读一个字节数据static UCHAR IICBusReadByte(BOOL bIsACK){UCHAR i,RDData = NULL;for(i=0;i<8;i++){RDData = RDData<<1;SCL = FALSE; //SCK = 0IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1if( SDARead() == TRUE ){RDData = RDData|0x01;}IICBusDelay(m_Baudrate);}if(bIsACK){SCL = FALSE; //SCK = 0SDA = FALSE; //SDA = 0IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1IICBusDelay(m_Baudrate);SCL = FALSE; //SCK = 0 }else{SCL = FALSE; //SCK = 0SDA = TRUE; //SDA = 1IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1IICBusDelay(m_Baudrate);SCL = FALSE; //SCK = 0 }return RDData;}//设置IIC速度void C52IIC_SetRate(UINT Rate){m_Baudrate = Rate;}//设置IIC器件地址void C52IIC_SetID(UCHAR ID){m_DeviceID = ID;}//写IIC数据BOOL C52IIC_Write(UCHAR Adress,UCHAR DATA) {UCHAR Vale = TRUE;UINT16 i = 0;IICBusStart();if(IICBusWriteByte(m_DeviceID)){Vale = FALSE;goto Exit;}if(IICBusWriteByte(Adress)){Vale = FALSE;goto Exit;}if(IICBusWriteByte(DATA)){Vale = FALSE;goto Exit;}Exit:IICBusStop();//根据不同芯片特性,设置读取速率DelayMs(ReWrTime);return Vale;}//读IIC数据UCHAR C52IIC_Read(UCHAR Adress) {UCHAR InData;IICBusStart();if(IICBusWriteByte(m_DeviceID)){goto Exit;}if(IICBusWriteByte(Adress)){goto Exit;}IICBusStart();if(IICBusWriteByte(m_DeviceID+1)){goto Exit;}InData = IICBusReadByte(FALSE); Exit:IICBusStop();//根据不同芯片特性,设置读取速率DelayMs(ReWrTime);return InData;}//初始化IICvoid C52IIC_Init(void){SDA = TRUE;IICBusDelay(20);SCL = TRUE;IICBusDelay(20);}//释放\占用IIC总线void C52IIC_Free(BOOL bIsFree){if(bIsFree){SCL = TRUE;SDA = TRUE;}else{SCL = FALSE;SDA = FALSE;}}//创建IICstatic void new(void){hIICBus = &m_Instance;hIICBus->C52IIC_SetRate = C52IIC_SetRate;hIICBus->C52IIC_SetID = C52IIC_SetID;hIICBus->C52IIC_Init = C52IIC_Init;hIICBus->C52IIC_Free = C52IIC_Free;}//获取IIC实例句柄IIC *C52IICGET(void){new();return hIICBus;}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "C52KEY.h"//读取IO口static UCHAR Read_GPIO(void){UCHAR uByte = NULL;uByte |= GPIO_KEY1;uByte = uByte << 1;uByte |= GPIO_KEY2;uByte = uByte << 1;uByte |= GPIO_KEY3;uByte = uByte << 1;uByte |= GPIO_KEY4;uByte = uByte << 1;uByte |= GPIO_KEY5;uByte = uByte << 1;uByte |= GPIO_KEY6;uByte = uByte << 2;return uByte;}static BOOL Key_Press(void){UCHAR uTemp;uTemp = Read_GPIO();uTemp &= 0XFC;if(uTemp!=0XFC)DelayMs(10);if(uTemp!=0XFC){return TRUE;}else{return FALSE;}}UCHAR Key_Scan(void){UCHAR KeyCode;DelayMs(10);if(Key_Press()){KeyCode = Read_GPIO();switch(KeyCode){case 0XF8:KeyCode = 0X01;break;case 0XF4:KeyCode = 0X02;break;case 0XEC:KeyCode = 0X03;break;case 0XDC:KeyCode = 0X04;break;case 0XBC:KeyCode = 0X05;break;case 0X7C:KeyCode = 0X06;break;default:KeyCode = NULL;break;}while(Key_Press());}else{KeyCode = NULL;}return KeyCode;}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "C52W ARING.h"static LED *hLEDBus = NULL;static LED m_Instance;static void TP_Waring(void){LED_TP = FALSE;}static void TP_Close(void){LED_TP = TRUE;}static void RH_Waring(void){LED_RH = FALSE;}static void RH_Close(void){LED_RH = TRUE;}static void LX_Waring(void){LED_LX = FALSE;}static void LX_Close(void){LED_LX = TRUE;}static void Close_Waring(void){LED_TP = TRUE;LED_RH = TRUE;LED_LX = TRUE;}static void New(void){hLEDBus = &m_Instance;hLEDBus->TP_Waring = TP_Waring;hLEDBus->RH_Waring = RH_Waring;hLEDBus->LX_Waring = LX_Waring;hLEDBus->TP_Close = TP_Close;hLEDBus->TP_Close = RH_Close;hLEDBus->TP_Close = LX_Close;hLEDBus->Close_Waring = Close_Waring;LED *C52LEDGET(void) {New();return hLEDBus;}。
(完整版)NRF24l01无线温度传感_毕业设计

A Dissertation Submitted toNanjing Institute of TechnologyFor the Academic Degree of Bachelor of ScienceBysupervised byCollege of Communication EngineeringNanjing Institute of TechnologyJune 2010NRF24l01无线温度传感摘要随着工农业生产对温度的要求越来越高,准确测量温度变得至关重要。
本系统的设计主要是针对恶劣环境下的工业现场以及高科技大范围的农业现场,布线困难,浪费资源,占用空间,可操作性差等问题做出的一个解决方案。
本文对上述问题提出一种无线解决方案,即基于SoC无线温度采集系统的设计。
该系统采用低功耗、高性能单片机及单总线数字式测温器件DS18B20构成测温系统,并且通过无线收发,最后在PC机上完成配置、显示和报警的功能。
在这次的设计中采用的单片机STC89C52RC的内核和MCS-51系列单片机一样,引脚也相同。
但是STC89C52RC可以通过STC_ISP软件下载进行烧录。
无线数据通信收发芯片NRF24L01是一款工业级内置硬件链路层协议的低成本无线收发器,工作于2.4 GHz全球开放ISM频段。
此外,温度传感器DS18B20以"一线总线"的数字方式传输,可大大提高系统的抗干扰性。
关键词:SoC;STC89C52RC;NRF24L01;温度传感器DS18B20;无线AbstractWith the industrial and agricultural production the temperature, accurate temperature measurement becomes critical.This system is a solution designed for wiring difficulties, wasting resources,taking up the space and poor maneuverability of the above mentioned problems is proposed, which is based on wireless solutions of SoC design of wireless temperature gathering system. This system USES low power consumption, PC complete configuration, display and alarm function.Used in the design of the microcontroller STC89C52RC and MCS-51 MCU core . But STC_ISP through STC89C52RC can burn to download software.Wireless data communication transceiver chip is an industrial grade NRF24L01 the 2.4 GHz band global open ISM. In addition, the temperature sensor DS18B20 to "bus line" digital mode transmission, greatly improves the power system.Key words:SoC,STC89C52RC,NRF24L01,Temperature sensor DS18B20,Wireless目录第一章绪论 (1)1.1概述 (1)1.2系统设计任务分析 (2)第二章总体方案设计与选择的论证 (2)2.1单片机最小系统 (2)2.1.1单片机的说明 (2)2.1.2单片机的应用 (2)2.1.3单片机的结构特点 (4)2.1.4单片机引脚配置 (4)2.2无线收发模块介绍 (6)2.2.1nRF24L01概述 (6)2.2.2 引脚功能及描述 (7)2.2.3工作模式 (7)2.2.4工作原理 (8)2.2.5配置字 (9)2.2.6nRF24L01应用原理框图 (10)2.3数码管温度显示和运行指示灯电路 (10)2.3.1LED数码管的基本结构 (10)2.3.2数码管动态显示的工作原理 (11)2.3.3运行指示灯说明 (12)2.4温度采集电路 (12)2.4.1 DS18B20概述 (12)2.4.2 DS18B20的管脚配置和内部结构 (13)2.4.3单总线介绍 (14)2.4.4DS18B20的工作原理 (14)2.5声报警电路设计 (20)2.6无线温度采集软件界面(MFC) (20)第三章软件设计报告 (24)3.1单片机软件设计 (24)3.1.1发送部分软件设计 (24)3.1.1.1温度传感DS18B20 (24)3.1.1.2 LED数码管显示 (29)3.1.1.3无线模块NRF24L01(发送) (29)3.1.2接收部分软件设计 (30)3.1.2.1无线模块NRF24L01(接收) (30)3.1.2.2 LED数码管显示 (30)3.1.2.3串口通信 (30)3.1.3无线温度采集软件设计 (32)3.1.3.1串口设置 (32)3.1.3.2温度上下限设置 (33)3.1.3.3曲线显示 (34)3.2流程图设计 (34)3.2.1发送部分流程图 (34)3.2.2接收部分流程图 (34)3.2.3 MFC程序流程图 (34)3.3操作说明(附图) (34)第四章总结与展望 (36)致谢 (38)参考文献 (39)附录 (40)第一章绪论1.1概述随着社会的进步和生产的需要,利用无线通信进行温度数据采集的方式应用已经渗透到生活各个方面。
nrf24l01的调试测试程序

nrf24l01的调试测试程序参考了很多程序,经过测试,才看懂nrf24l01的状态机,在看数据手册时很多地方都不懂后来看了关于调试的文章再自己测试了一下某些功能,只测试了一边发送,一边接收的功能,做的很妥跟网上的程序相差无几。
#include <REG51.H>#include 'NRF24L01.h'#define TX_ADDR_WIDTH 5 //本地发射地址宽度#define RX_ADDR_WIDTH 5 //本地接收地址宽度#define TX_DATA_WIDTH 3 //发送数据字节数最大字节数为32字节#define RX_DATA_WIDTH 3 //接收数据字节数unsigned char code TX_ADDRESS[TX_ADDR_WIDTH]={0x78,0x78,0x78,0x78,0x78}; //发射通道地址unsigned char code RX_ADDRESS_P0[RX_ADDR_WIDTH]={0x78,0x78,0x78,0x78,0x78 }; //接收通道地址unsigned char bdata status; //定义一个位与字节都可以访问的变量用来监控IRQ中断信号sbit RX_DR=status^6; //当接收到有效数据后变为1sbit TX_DR=status^5; //当数据发送完成后产生中断,在自动应答模式中接收到应答信号后为1sbit MAX_RT=status^4; //当达到最大重发次数后变为1,产生此中断后必须清零后才能再次通讯void usdelay(void) //误差 -0.149305555556us 12us{unsigned char a,b;for(b=1;b>0;b--)for(a=2;a>0;a--);}void usdelay130(void) //误差 -0.451388888889us{unsigned char a,b;for(b=11;b>0;b--)for(a=4;a>0;a--);}unsigned char SPI_RW(unsigned char uchar) //SPI协议{unsigned char i;for(i=0;i<8;i++){SCK=0;MOSI=uchar&0x80; //从字节高位向NRF24L01写数据uchar=uchar<<1;SCK=1;uchar=uchar|MISO; //接收从NRF24L01发过来的数据SCK=0;}return uchar; //返回读取的值}unsigned char SPI_read(unsigned char reg) //SPI读操作两个字节完成读一次 reg:读指令{unsigned char bl;CSN=0;SPI_RW(reg); //第一个字节写读某个寄存器的指令此时返回值为状态寄存器的值bl=SPI_RW(0); //第二个字节返回所需要的寄存器的值CSN=1;return bl;unsigned char SPI_write(unsigned char reg,unsigned char value) //SPI写操作写一个字节的数据先写指令说明往哪个寄存器写数据,reg:指令,value:数据{unsigned char status;CSN=0;status=SPI_RW(reg); //写指令并返回状态寄存器的值SPI_RW(value); //写数据CSN=1;return status; //返回状态寄存器的值}unsigned char SPI_read_more(unsigned char reg,unsigned char *puf_read,unsigned char width) //读取多个数据 reg:指令,*puf 存储数据的指针,width:要读取数据的长度{unsigned char i,status;CSN=0;status=SPI_RW(reg); //写指令并返回状态寄存器的值for(i=0;i<width;i++) //循环读出数据puf_read[i]=SPI_RW(0); //将循环读出的数据存储在一个数组中}CSN=1;return status;}unsigned char SPI_write_more(unsigned char reg,unsigned char *puf_write,unsigned char width) //写多个数据 reg:指令,*puf:要写的数据,width:数据长度{unsigned char i,status;CSN=0;status=SPI_RW(reg); //写指令并返回状态寄存器的值for(i=0;i<width;i++) //循环写入数据{SPI_RW(*puf_write++);}CSN=1;return status;}void receive_model() //接收模式初始化配置{CE=0; //掉电模式此时PWR_UP为0CSN=1; //停止寄存器读写SCK=0; //时钟信号停止读写IRQ=1; //中断复位SPI_write_more(WRITE_REG+RX_ADDR_P0,RX_ADDRESS_P0, RX_ADDR_WIDTH); //写本地接收的地址SPI_write(WRITE_REG+EN_AA,0x00); //失能自动应答SPI_write(WRITE_REG+EN_RXADDR,0x01); //接收通道0允许SPI_write(WRITE_REG+RF_CH,0x00); //通信频率 2.4GSPI_write(WRITE_REG+RX_PW_P0,TX_DATA_WIDTH); //设置数据通道0传输数据宽度为3个字节SPI_write(WRITE_REG+RF_SETUP,0x09); //设置发射参数:传输速率,发射功率SPI_write(WRITE_REG+CONFIG,0x0F); //配置寄存器,设置CRC 和工作模式(接收模式)CE=1; //启动}void send_model() //发射模式初始化配置{CE=0; //掉电模式此时PWR_UP为0CSN=1; //停止寄存器读写SCK=0; //时钟信号停止读写IRQ=1; //中断复位SPI_write_more(WRITE_REG+TX_ADDR,TX_ADDRESS,TX_AD DR_WIDTH); //写本地发射地址SPI_write_more(WRITE_REG+RX_ADDR_P0,RX_ADDRESS_P0,RX_ADDR_WIDTH); //写本地接收(主要用来使能自动应答) SPI_write(WRITE_REG+EN_AA,0x00); //失能自动应答功能SPI_write(WRITE_REG+EN_RXADDR,0x00); //失能接收通道0 SPI_write(WRITE_REG+SETUP_RETR,0x00); //失能自动重发SPI_write(WRITE_REG+RF_CH,0x00); //通信频率 2.4GSPI_write(WRITE_REG+RX_PW_P0,RX_DATA_WIDTH); //设置接收数据长度为3个字节SPI_write(WRITE_REG+RF_SETUP,0x09); //设置发射参数:传输速率2MHZ,发射功率SPI_write(WRITE_REG+CONFIG,0x0e); //配置寄存器,设置CRC 和工作模式(发射模式)CE=1; //启动}void send_data(unsigned char *pArray) //发送数据{CE=0; //停止射频工作,待机模式1//SPI_write_more(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADD R_WIDTH); //装载接收端地址此地址单对单发送时可只初始化一次SPI_write_more(WR_TX_PLOAD,pArray,3); //向nrf24l01传入要发送的数据// SPI_write(WRITE_REG+CONFIG,0x0e); //IRQ收发完成中断响应,16位CRC,发送模式此功能在但对单发送时可初始化一次CE=1; //置高CE,激发数据usdelay(); //10us的延时}unsigned char read_data(unsigned char *pArray) //读取接收的数据 *pArray:传入存放数据的数组{unsigned char mark;CE=1; //接收模式usdelay130(); //等待130usstatus=SPI_read(STATUS); //读取状态寄存器的值来判断数据的接收情况if(RX_DR==1){CE=0; //接收完数据变成待机模式1SPI_read_more(RD_RX_PLOAD,pArray,RX_DATA_WIDTH); //读取数据并将其存放在RX_DATA中mark=1; //读取完成标志}SPI_write(WRITE_REG+STATUS,status); //清除中断标志位return mark;}/************************************************************** ************************************************/void main(){unsigned char mark,i; //接收完成标志delay(1000);receive_model(); //接收模式初始化配置delay(1000);while(1){mark=read_data(RX_DATA);if(mark==1){i++;SPI_write(FLUSH_RX,0); //清空RX_FIFO 中的缓存数据接受不像发送会自动清空缓存区的数据if(RX_DATA[0]==0&&RX_DATA[1]==1&&RX_DATA[2]==2) {led0=0;delay(100);RX_DATA[0]=0;RX_DATA[1]=0;RX_DATA[2]=0;}mark=0;}SPI_read(STATUS); //读状态寄存器SPI_read(FIFO_STATUS); //读FIFO状态led0=1;}}。
NRF24L01无线串口开发板程序详解

1.源程序开发环境建立1.1程序编译软件编译软件用keil C51,打开安装文件,一路点击下一步即可完成。
1.2程序下载软件使用STC ISP下载软件。
2.源程序文件整体结构工程中,只有一个main.c文件,所有程序都写在这个文件里面。
Reg51.h是包含的头文件。
是不是非常简单!3.源程序执行流程无线数据处理程序:串口数据处理程序:4.串口配置函数void serial_open(void){SCON = 0X50;AUXR |= 0X04;TL2 = 0Xc0; // 9600TH2 = 0Xfd;AUXR|=0X10;}此串口配置函数,利用单片机内部的定时器2作为波特率发生器。
共用到4个寄存器:SCON AUXR TL2 TH2SM0和SM1的位决定串口工作的4种方式:程序中,SCON=0X50,即SM0=0 SM1=1,即串口工作在“方式1”;REN=1,允许串口接收数据。
TL2和TH2是定时器2的高位和低位寄存器。
程序中,首先AUXR|=0X40,最后AUXR|=0X10。
即首先把T2x12置1,然后把T2R置1。
即首先把定时器2设置为1T模式,然后把定时器打开。
5.串口发送数据函数void senddata(uchar data_buf){SBUF = data_buf;while(!TI);TI = 0;}用到了寄存器SBUF和寄存器SCON中的TI位。
SBUF寄存器是串口收发数据缓存寄存器,放到这个寄存器中的数据,会通过串口发送出去,接收到的串口数据,也会放到这个寄存器中。
也就是串口接收和发送都是使用这个寄存器。
程序中,SBUF=data_buf,就是把data_buf给了SBUF,单片机自动把SBUF里面的数据发送到串口。
TI是串口发送数据完成标志位,当串口发送完一个数据,此位置1,置位后,需要通过软件清0。
所以通过while(!TI),来检测TI位,达到检测串口是否发送完数据的目的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(相关人员如觉得本人水平低下,还请见谅)Nrf24L01的使用程序和使用方法和简单操作:功能:无线对发程序。
两个模块a,b,实现按下一个按键,会在对方的数码管上显示3或4,在本机上显示1,2。
当一个模块,比如a模块。
当两个按键按下其中一个,则会在另一个模块b上显示数字3,4(具体根据按下哪个按键)。
以上功能描述,B模块按键按下,如同a模块一样的功能,不做系统性描述了。
下面给出程序中几个地方的解释:#define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接收数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 // 冲洗发送FIFO指令#define FLUSH_RX 0xE2 // 冲洗接收FIFO指令#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令#define NOP 0xFF // 保留类似这种的描述,可以等同于READ_REG =0x00;这个是经过实际程序测试出来的,比如以下程序:#include<reg51.h>#define k 0xfevoid main(){P1=k;}则会出现此类结果:MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0;此处为spi的核心,是spi协议的编程,其中uchar |= MISO; 表示uchar |= MISO | uchar; MOSI = (uchar & 0x80);其中0x80是1000 0000,与上uchar,这种&,是按位与,故可以从uchar提取出一个电平给mosi。
MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1);这两句组合起来用,就实现了把uchar编程8位2进制数后的每一位都可以发送给mosi;Uchar的只待对象,就是上面的诸如#define FLUSH_TX 0xE1这样的数,或者是相关的发送数据。
*pBuf这个并不是一个主要的问题,实际这个是涉及指针问题的,带*的跟地址有关系,但是我们其实不需要很关心编译的时候数据被具体存入哪个地址,即使是很重要的数据。
void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; //SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB}在整个初始化中我们看到:CE=0; // chip enableCSN=1; // Spi disable这是设置整个的状态。
如过状态设置成待机,则引脚可能变为高阻。
(以上并非全部引脚)SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址类似以上两句,这是应用spi的子程序,将寄存器指令放入nrf24l01。
如果需深究,请参考说明书,手册等。
或者可以通过#define READ_REG 0x00 // 读寄存器指令等了解大概流程。
在整个无线通信过程中,初始化只需设置一次。
TxBuf[]存放的是发送的数据。
并且此数据被发送时,是将这个数组的数全部发送的。
对方也全部接收。
RxBuf[]接收数组,用于存放对方发来的数据。
SetRX_Mode();nRF24L01_RxPacket(RxBuf);当主程序中包含这两个子函数时,且这时某个数据被发送过来,则会被接收到。
且被存放到了RxBuf[];反之包含nRF24L01_TxPacket(TxBuf);且TxBuf[]已经存入你想要的数据的时候,这个数据将被发送。
程序部分:下面给出程序,由于收发双方程序是完全一样的,所以只粘贴一份。
程序虽然不是自己写的,但是经过实际测试的,没有任何诡异的问题。
#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//****************************************NRF24L01端口定义***************************************sbit MISO =P1^3;sbit MOSI =P1^4;sbit SCK =P1^2;sbit CE =P1^1;sbit CSN =P3^2;sbit IRQ =P3^3;//************************************按键***************************************************sbit KEY1=P3^6;sbit KEY2=P3^7;//************************************数码管位选*********************************************sbit led3=P2^0;sbit led2=P2^1;sbit led1=P2^2;sbit led0=P2^3;//************************************蜂明器***************************************************sbit BELL=P3^4;//***********************************数码管0-9编码*******************************************uchar seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9段码//*********************************************NRF24L01*********************** **************#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 20 // 20 uints TX payload#define RX_PLOAD_WIDTH 20 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//***************************************NRF24L01寄存器指令*******************************************************#define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接收数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 // 冲洗发送FIFO指令#define FLUSH_RX 0xE2 // 冲洗接收FIFO指令#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令#define NOP 0xFF // 保留//*************************************SPI(nRF24L01)寄存器地址****************************************************#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 // 自动应答功能设置#define EN_RXADDR 0x02 // 可用信道设置#define SETUP_AW 0x03 // 收发地址宽度设置#define SETUP_RETR 0x04 // 自动重发功能设置#define RF_CH 0x05 // 工作频率设置#define RF_SETUP 0x06 // 发射速率、功耗功能设置#define STATUS 0x07 // 状态寄存器#define OBSERVE_TX 0x08 // 发送监测功能#define CD 0x09 // 地址检测#define RX_ADDR_P0 0x0A // 频道0接收数据地址#define RX_ADDR_P1 0x0B // 频道1接收数据地址#define RX_ADDR_P2 0x0C // 频道2接收数据地址#define RX_ADDR_P3 0x0D // 频道3接收数据地址#define RX_ADDR_P4 0x0E // 频道4接收数据地址#define RX_ADDR_P5 0x0F // 频道5接收数据地址#define TX_ADDR 0x10 // 发送地址寄存器#define RX_PW_P0 0x11 // 接收频道0接收数据长度#define RX_PW_P1 0x12 // 接收频道0接收数据长度#define RX_PW_P2 0x13 // 接收频道0接收数据长度#define RX_PW_P3 0x14 // 接收频道0接收数据长度#define RX_PW_P4 0x15 // 接收频道0接收数据长度#define RX_PW_P5 0x16 // 接收频道0接收数据长度#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置//***************************************************************************** *********void Delay(unsigned int s);void inerDelay_us(unsigned char n);void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);//*****************************************长延时*****************************************void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}//***************************************************************************** *************uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/****************************************************************************** ************/*延时函数/****************************************************************************** ************/void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//***************************************************************************** ***********/*NRF24L01初始化//***************************************************************************** **********/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; //SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB}/****************************************************************************** **********************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/****************************************************************************** **********************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again}return(uchar); // return read uchar}/****************************************************************************** **********************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI时序/****************************************************************************** **********************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN low, initialize SPI communication...SPI_RW(reg); // Select register to read from..reg_val = SPI_RW(0); // ..then read registervalueCSN = 1; // CSN high, terminate SPI communicationreturn(reg_val); // return register value}/****************************************************************************** **********************//*功能:NRF24L01读写寄存器函数/****************************************************************************** **********************/uint SPI_RW_Reg(uchar reg, uchar value){uint status;CSN = 0; // CSN low, init SPI transactionstatus = SPI_RW(reg); // select registerSPI_RW(value); // ..and write value to it..CSN = 1; // CSN high againreturn(status); // return nRF24L01 status uchar}/****************************************************************************** **********************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/****************************************************************************** **********************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; // Set CSN low, init SPI tranactionstatus = SPI_RW(reg); // Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/****************************************************************************** ***************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/****************************************************************************** ***************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; //SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/****************************************************************************** **********************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/****************************************************************************** **********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1;inerDelay_us(130);}/****************************************************************************** ************************//*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/*功能:数据读取后放如rx_buf接收缓冲区中/****************************************************************************** ************************/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf){unsigned char revale=0;sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;}/****************************************************************************** *****************************/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送tx_buf中数据/****************************************************************************** ****************************/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}//************************************主函数************************************************************void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; //unsigned char RxBuf[20]={0};init_NRF24L01() ;led0=0;led1=0;led2=0;led3=0;P0=0x00;TxBuf[1] = 1 ;TxBuf[2] = 1 ;nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataDelay(6000);P0=0xBF;while(1){if(KEY1 ==0 ){P0=seg[1];TxBuf[1] = 1 ;tf = 1 ;}if(KEY2 ==0 ){P0=seg[2];TxBuf[2] =1 ;tf = 1 ;}if (tf==1){nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataTxBuf[1] = 0x00;TxBuf[2] = 0x00;tf=0;Delay(1000);}//***************************************************************************** ******************SetRX_Mode();nRF24L01_RxPacket(RxBuf);if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){P0=seg[3];}if( RxBuf[2]==1){P0=seg[4];}Delay(1000);}RxBuf[1] = 0x00;RxBuf[2] = 0x00;}}如需要利用程序做nrf24l01改动应用在其他设计中。