nRF24L01温度发送与接收程序
NRF24L01测试发送程序
NRF24L01测试发送程序/*对该程序做一下几点说明一、该程序仅用于测试是否发送成功,所以有两处的设置做出了调整1、SPI_RW_Reg(WRITE_REG + EN_AA, 0x00);//频道0自动ACK应答允许(此处禁止用于测试)2、SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x00);//允许接收地址只有频道0(此处禁止用于测试)二、其中P3口连接的是无线模块的引脚,P2口连接的是LED 是为了显示发送数据后STA TUS的状态若使用的开发板不同,需将P2口连接到其他口观察状态寄存器的状态三、P3口一定不要接其他外部设备,如使用的开发板有其他外接设备一定要断掉。
或侧换成最小系统板进行试验四、若发送仍不成功,可以用示波器观察发送数据时的MISO口的波形判断是否为硬件问题*///***************************************************发送程序*********************************//#include#includetypedef unsigned char uchar;//****************************************NRF24L01 IO端口定义*********************************//sbit CE =P3^2;sbit CSN =P3^3;sbit SCK =P3^4;sbit M OSI =P3^5;sbit M ISO =P3^6;sbit IRQ =P3^7;//***********************************发送缓冲区***********************************************//uchar TxBuf[3]={1,2,3};//发送的数据用数字存储//*****************************NRF24L01的接收和发送地址***************************************//#define TX_ADR_WIDTH 5 // 5个字节的TX地址长度#define RX_ADR_WIDTH 5 // 5个字节的TX地址长度#define TX_PLOAD_WIDTH 3 // 20个字节的TX数据长度#define RX_PLOAD_WIDTH 3 // 20个字节的TX数据长度uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uchar 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);uchar SPI_RW(uchar num);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uchar SPI_RW_Reg(uchar reg, uchar value);uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uchar 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 inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//*****************************************长延时*****************************************//void Delay(unsigned int s){unsigned int i;for(i=0; i<="" p="">for(i=0; i<="" p="">}//****************************************状态标志****************************************//uchar bdata sta;sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;//********************************NRF24L01初始化******************************************//void init_NRF24L01(void){inerDelay_us(100);CE=0; // 片选使能CSN=1; // SPI使能SCK=0; // SPI时钟拉低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, 0x00); // 频道0自动ACK 应答允许(此处禁止用于测试)SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x00); //允许接收地址只有频道0(此处禁止用于测试),如果需要多频道可以参考Page21 SPI_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,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送}/************************************************************** **************** **********************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/************************************************************** **************** **********************/uchar SPI_RW(uchar num){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (num & 0x80); // output 'uchar', MSB to MOSInum = (num << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..num |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again}return(num); // 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读写寄存器函数/************************************************************** **************** **********************/uchar SPI_RW_Reg(uchar reg, uchar value){uchar 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_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/****************************************************************** ************ ***************************/uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uchar status,uchar_ctr;CSN = 0; //SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<="" bdsfid="224" p="" uchar_ctr++)="">SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/************************************************************** **************** *****************************/*函数: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); // 装载数据CE=1; //置高CE激发数据发送inerDelay_us(10);}/************************************主函数************************************************************/ void main(void){init_NRF24L01() ;Delay(6000);while(1){nRF24L01_TxPacket(TxBuf); // 发送Tx buffer的数据Delay(15000); //可变P2=SPI_Read(STA TUS);Delay(10000); //可变}}。
NRF24L01的发送与接收程序
N R F24L01的发送与接收程序-CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIAN#include <>#include <>typedef unsigned char uchar;typedef unsigned char uint;SCK = 1;uchar |= MISO; then set SCK low again}return(uchar); .SPI_RW(reg);reg_val = SPI_RW(0); then read registervalueCSN = 1; and write value to it..CSN = 1;SCK = 1;uchar |= MISO; then set SCK low again}return(uchar); .SPI_RW(reg);reg_val = SPI_RW(0); then read registervalueCSN = 1; 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){uchar temp =0;init_NRF24L01() ;nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataDelay(6000);P0=0xBF;while(1){nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataLED=0;Delay(10000); //可变SPI_RW_Reg(WRITE_REG+STATUS,0XFF);LED=1;Delay(8000);}}。
nrf24l01工作原理
nrf24l01工作原理
NRF24L01是一种低功耗2.4GHz无线收发模块,工作于
2.4GHz~2.525GHz的ISM频段。
它是由Nordic Semiconductor
公司设计和制造的。
NRF24L01的工作原理如下:
1. 发送与接收:模块既可以作为发送器发送数据,也可以作为接收器接收数据。
发送器和接收器之间通过无线信道进行通信。
2. 通信协议:NRF24L01采用了专有的GFSK调制技术和
2.4GHz无线通信协议。
它支持1Mbps、2Mbps和250kbps的
数据传输速率。
3. 通信距离:NRF24L01的通信距离取决于多个因素,如工作
频率、功率级别、天线设计等。
一般情况下,它可以在室内环境下达到10-30米的通信距离。
4. 工作模式:NRF24L01有两种工作模式:发射模式和接收模式。
在发射模式下,模块将数据发送到接收器。
在接收模式下,模块接收来自发送器的数据。
5. 通信通道和地址:NRF24L01有125个不同的通信通道,可
以在这些通道中选择一个适合的通道进行通信。
另外,可以通过设置6个字节的地址来区别不同的模块。
6. 特点:NRF24L01具有低功耗和快速开启/关闭的特点。
在
不需要通信时,可以将模块设置为睡眠模式以节省能量。
综上所述,NRF24L01是一种通过2.4GHz无线信号进行通信的模块,适用于低功耗的应用场景,如无线传感器网络、遥控器、无线键盘鼠标等。
nrf24l01发送接收一体程序(以调通,解决了接收端只能接收一次的问题)
nrf24l01发送接收一体程序(以调通,解决了接收端只能接收一次的问题)/**************************************************基于单片机无线报警系统主机(机载设别)系统程序/**************************************************/#include#include#define uchar unsigned char/***************************************************/#define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址#define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址uchar RX_BUF[4]={0,0,0,0};uchar TX_BUF[4]={0x20,0x20,0x20,0x20};uchar flag; //无线模块接受数据标志uchar DATA = 0x01;uchar bdata sta;unsigned int a,k; //定时器延时参数uchar mark; //传感器响应标志位uchar mark1; // 延时标志位sbit RX_DR = sta^6; //接受数据成功标志位sbit TX_DS = sta^5; // 发送成功标志位sbit MAX_RT = sta^4; //最大重发上限标志位sbit HW=P2^0; //红外感应模块输入端sbit ZD=P1^7; //震动传感器输入端sbit LED=P2^1; //LED报警器输出端sbit SDA=P2^4; //语音模块数据控制端sbit ONN=P2^3; //语音芯片电源控制端口sbit FM =P2^5; //蜂鸣器/************************************************** 函数:delayus()描述:延迟x微秒/**************************************************/void delayus(unsigned int t){while(t--);}/************************************************** 函数:delayms()描述:延迟x毫秒/**************************************************/void delayms(unsigned int h){unsigned int j;while(h--)for(j=85;j>0;j--);}/************************************************** 函数:delays()描述:延迟x.xx秒/**************************************************/void delays( float h){unsigned int i,j;h*=100;while(h--){for(i=0;i<235;i++)for(j=0;j<3;j++);}}/************************************************** 函数:sendadd()描述:语音模块发送地址信号/**************************************************/ void sendadd(unsigned char addr){uchar i;delayms(5); /* 数据信号置于低电平5ms */for(i=0;i<8;i++){ SDA=1;if(addr & 1){delayus(60); /* 高电平比低电平为600us:200us,表示发送数据1 */SDA=0;delayus(20);}else{delayus(20);SDA=0; /* 高电平比低电平为200us:600us,表示发送数据0 */ delayus(60);}addr>>=1;}SDA=1;}/**************************************************函数:SPI_RW()描述:根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/**************************************************/uchar SPI_RW(uchar byte){for(i=0; i<8; i++) // 循环8次{MOSI = (byte & 0x80); // byte最高位输出到MOSIbyte <<= 1; // 低一位移位到最高位SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据byte |= MISO; // 读MISO到byte最低位SCK = 0; // SCK置低}return(byte); // 返回读出的一字节}/**************************************************//**************************************************函数:SPI_RW_Reg()描述:写数据value到reg寄存器/**************************************************/uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据status = SPI_RW(reg); // 选择寄存器,同时返回状态字SPI_RW(value); // 然后写数据到该寄存器CSN = 1; // CSN拉高,结束数据传输return(status); // 返回状态寄存器}/************************************************** 函数:clear()描述:清TX_FIFO寄存器/**************************************************/void clear(){CSN=0;SPI_RW(FLUSH_TX);CSN=1;}/************************************************** 函数:SPI_Read()描述:从reg寄存器读一字节/**************************************************/ uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN置低,开始传输数据SPI_RW(reg); // 选择寄存器reg_val = SPI_RW(0); // 然后从该寄存器读数据CSN = 1; // CSN拉高,结束数据传输return(reg_val); // 返回寄存器数据}/**************************************************//**************************************************函数:SPI_Read_Buf()描述:从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/**************************************************/ uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes) {uchar status, i;CSN = 0; // CSN置低,开始传输数据status = SPI_RW(reg); // 选择寄存器,同时返回状态字for(i=0; ipBuf[i] = SPI_RW(0); // 逐个字节从nRF24L01读出CSN = 1; // CSN拉高,结束数据传输return(status); // 返回状态寄存器}/**************************************************//**************************************************函数:SPI_Write_Buf()描述:把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/**************************************************/ uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes) {uchar status, i;CSN = 0; // CSN置低,开始传输数据status = SPI_RW(reg); // 选择寄存器,同时返回状态字for(i=0; iSPI_RW(pBuf[i]); // 逐个字节写入nRF24L01CSN = 1; // CSN拉高,结束数据传输return(status); // 返回状态寄存器}/**************************************************函数:RX_Mode()描述:这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包/**************************************************/void RX_Mode(void){CE = 0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0F); // CRC使能,16位CRC校验,上电,接收模式CE = 1;delayus(200); // 拉高CE启动接收设备}/**************************************************函数:TX_Mode()描述:这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),130us后启动发射,数据发送结束后,发送模块自动转入接收模式等待应答信号。
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接收和发送的问题
24L01是收发双方都需要编程的器件,这就对调试方法产生了一定的要求,如果两块一起调,那么通讯不成功,根本不知道是发的问题还是收的问题,不隐晦的说,我当时也是没理清调试思路才浪费了大半天时间看着模块干瞪眼。
正确的方法应该是先调试发送方,能保证发送正确,再去调接收,这样就可以有针对性的解决问题。
至于怎么去调发送方,先说下发送方的工作流程:•配置寄存器使芯片工作于发送模式后拉高CE端至少10us•读状态寄存器ST ATUS•判断是否是发送完成标志位置位•清标志•清数据缓冲网上的程序我也看过,大多都是成品,发送方发送-等应答-(自动重发)-触发中断。
可是这样的流程就已经把接收方给牵涉进来了,就是说一定要接收方正确收到数据并且回送应答信号之后发送方才能触发中断,结束一次完整的发送。
可是这跟我们的初衷不相符,我们想单独调试发送,完全抛开接收,这样就要去配置一些参数来取消自动应答,取消自动重发,让发送方达到发出数据就算成功的目的。
SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); // 失能通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RX ADDR, 0x00); // 失能接收通道0SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x00); // 失能自动重发(注:以下贴出的寄存器描述由于中文资料上有一个错误,故贴出原版英文资料)有了以上这三个配置,发送方的流程就变成了发送-触发中断。
这样就抛开了接收方,可以专心去调试发送,可是怎么样才知道发送是否成功呢,要用到另外两个寄存器,ST ATUS和FIFO_ST AT US。
这样就很清晰了,我们可以通过读取ST ATUS的值来判断是哪个事件触发了中断,寄存器4、5、6位分别对应自动重发完成中断,数据发送完成中断,数据接收完成中断。
也就是说,在之前的配置下,如果数据成功发送,那么ST ATUS的值应该为0x2e。
NRF24L01t调试程序 含发送和接收 可直接用
//***SPI(nRF24L01) 寄存器地址**************************************************** #define CONFIG #define EN_AA 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式 0x01 // 自动应答功能设置
说实话,对于一个初次调试这个模块的同学,想要找一个直接可用的程序不好找,同时是找到的片 段程序很多又是木有注释的,我们(菜鸟)没有很好的理解芯片资料的能力,看着都是一头雾水。 在这儿,我贴出发送和接收两部分,希望可以让学习者轻松一点理解和掌握其操作流程。同时声明 一下,下面的程序不是我写的,但是99%的注释是我写的,对于掌握的人来说,不需要这样多的注 释,我是面对需要学习的人而写的。这样也算是我对电子技术给我的乐趣的回馈。在没有和程序作 所 帮助! 注释的位置需要调整一下哦 以下是发送端程序: #include <reg52.h> #include <intrins.h> #define MODE 0 //MODE=1时为发送代码 typedef unsigned char uchar; //************************************************IO 端口定义***************** sbit MISO = P2^3; sbit MOSI = P2^2; sbit SCK = P2^1; sbit CE = P2^5; sbit CSN = P2^0; sbit IRQ = P3^2; sbit led = P1^2; //***************************************************************************** uchar bdata sta; //状态标志 sbit RX_DR = sta^6; sbit TX_DS = sta^5; sbit MAX_RT = sta^4; MODE=0时为接收代码
nRF24L01的工作原理
nRF24L01的工作原理nRF24L01是一种低功耗2.4GHz无线收发器,广泛应用于物联网、传感器网络和无线通信系统等领域。
它采用射频(RF)技术,能够在无线环境中实现高速数据传输和可靠的通信连接。
本文将详细介绍nRF24L01的工作原理,包括其硬件结构、通信协议和工作模式等。
一、硬件结构nRF24L01由射频前端、基带处理器和外围电路组成。
射频前端包括功率放大器、低噪声放大器和射频开关等,用于接收和发送无线信号。
基带处理器负责信号调制、解调和协议处理等功能。
外围电路包括晶振、电源管理和SPI接口等,用于提供稳定的时钟和电源,并与主控设备进行通信。
二、通信协议nRF24L01使用2.4GHz的ISM频段,采用射频通信协议来实现数据传输。
它支持多种通信模式,包括点对点模式、广播模式和多点模式等。
在点对点模式下,一个nRF24L01作为发送器,另一个nRF24L01作为接收器,它们之间通过射频信道进行数据交换。
在广播模式下,一个nRF24L01可以同时向多个接收器发送数据。
在多点模式下,多个nRF24L01可以互相通信,形成一个网络。
nRF24L01使用GFSK调制和解调技术,通过改变载波频率的相位和幅度来传输数字信号。
它还使用自适应频率跳频技术,可以在不同的射频信道上工作,以避免干扰和提高通信质量。
此外,nRF24L01还支持数据包重传、自动应答和信道切换等功能,以提高通信的可靠性和稳定性。
三、工作模式nRF24L01有两种工作模式:发送模式和接收模式。
在发送模式下,nRF24L01将待发送的数据加载到发送缓冲区,并通过射频信道发送给接收器。
在接收模式下,nRF24L01监听射频信道,接收来自发送器的数据,并将其存储在接收缓冲区中。
发送器和接收器之间通过射频信道进行双向通信,以实现数据的传输和交换。
nRF24L01还支持睡眠模式和待机模式,以降低功耗。
在睡眠模式下,nRF24L01关闭大部分电路,只保持少量的关键电路运行,以便快速唤醒和恢复正常工作。
NRF24L01参考程序(包含多个实例)
(相关人员如觉得本人水平低下,还请见谅)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。
nRF24L01无线通信模块使用手册
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。
三、模块引脚说明1 / 197 NC 空 8 CSN 芯片片选信号 I 9 CE 工作模式选择I 10+5V电源四、模块与AT89S52单片机接口电路注:上图为示意连接,可根据自己实际需求进行更改;使用AT89S52MCU 模块时,请将Nrf24L01通讯模块每个端口(MOSI 、SCK 、CSN 和CE )接4.7K 的排阻上拉到VCC 增强其驱动能力(如下图:)。
(完整版)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是一种低功耗、高性能的无线收发模块,广泛应用于物联网、智能家居、远程控制等领域。
它采用2.4GHz频段,支持多通道和自动重发机制,具有快速响应、稳定可靠的特点。
本文将详细介绍nRF24L01的工作原理,包括无线通信原理、硬件连接和通信协议。
1. 无线通信原理:nRF24L01采用射频通信技术,通过无线电波在发送端和接收端之间传输数据。
发送端将要发送的数据编码成数字信号,并通过射频发射天线发送出去。
接收端的射频接收天线接收到信号后,经过解码还原成原始数据。
这种无线通信方式可以实现远距离传输和双向通信。
2. 硬件连接:nRF24L01模块需要与主控芯片或者单片机进行连接。
普通情况下,连接需要以下几个引脚:- VCC:供电正极- GND:供电负极- CE:片选使能- CSN:SPI片选- SCK:SPI时钟- MOSI:SPI主机输出、从机输入- MISO:SPI主机输入、从机输出- IRQ:中断请求3. 通信协议:nRF24L01采用SPI接口进行数据传输,通信过程中需要使用一定的通信协议。
常用的协议包括:- 初始化配置:在使用nRF24L01之前,需要对其进行初始化配置,包括频道选择、地址设置、发射功率设置等。
- 发送数据:发送端将要发送的数据通过SPI接口发送给nRF24L01,nRF24L01将数据编码成射频信号并发送出去。
- 接收数据:接收端通过SPI接口接收到射频信号,并将其解码还原为原始数据。
4. 示例应用:nRF24L01广泛应用于各种物联网和远程控制场景。
例如,可以将nRF24L01模块连接到Arduino单片机上,实现无线传感器网络。
传感器节点通过nRF24L01与基站通信,将采集到的数据发送给基站进行处理和分析。
同时,基站也可以通过nRF24L01向传感器节点发送控制指令,实现远程控制。
5. 总结:nRF24L01是一种低功耗、高性能的无线收发模块,具有快速响应、稳定可靠的特点。
nrf24l01无线温度传输—51单片机
无线温度传输系统学校:安徽工业大学学院:电气信息学院由于最近要毕业设计了,老师让我做无线通信,然后我上网找了很多资料,决定用24L01做,经过一段时间的摸索,终于实现了24L01的无线温度传输。
以下是我的程序,可供大家参考(当中在贴吧中学到了很多关于24l01的知识)。
发射端程序:#include <reg52.h>#include <intrins.h>//#include "api.h"#define uchar unsigned char#define TX_ADR_WIDTH 5 // 发射地址的字节个数#define TX_PLOAD_WIDTH 2 //发射字节uchar const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};uchar rx_buf[TX_PLOAD_WIDTH];uchar tx_buf[TX_PLOAD_WIDTH];uchar distance_data[2];uchar flag;//标志sbit CE=P1^1; //发射高电平大于10MS 接收高电平sbit CSN=P1^2; //低电平ISP使能sbit SCK=P1^3; //下降沿sbit MOSI=P1^4; //MCU出sbit MISO=P1^5; //MCU入sbit IRQ=P1^6; //中断uchar bdata sta;sbit RX_DR =sta^6; //接收数据准备就绪sbit TX_DS =sta^5; //已发送数据sbit MAX_RT =sta^4;sbit DQ=P3^3;unsigned char time; //设置全局变量,专门用于严格延时//*********************************************NRF24L01*********************** **************//***************************************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 init_io(void){CE=0;CSN=1;SCK=0;}void delay_ms(unsigned int x){unsigned int i,j;for(i=0;i<x;i++){j=108;while(j--);}}uchar SPI_RW(uchar byte)//发送指令,接受状态,返回值为状态值{uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++){MOSI = (byte&0x80);byte = (byte<<1);SCK = 1;byte|=MISO;SCK=0;}return(byte);}uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0;status = SPI_RW(reg);SPI_RW(value);CSN = 1;return(status);}uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0;SPI_RW(reg); //写指令reg_val = SPI_RW(0); //读reg的内容CSN = 1;return(reg_val);}uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes){uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)pBuf[byte_ctr] = SPI_RW(0);CSN = 1;return(status);}uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes){uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)SPI_RW(*pBuf++);CSN = 1;return(status);}void TX_Mode(void){CE=0;SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS/*接收模块的地址*/, TX_ADR_WIDTH/*地址宽度5*/);SPI_Write_Buf(WRITE_REG + RX_ADDR_P0/*通道0 接收数据地址*/, TX_ADDRESS, TX_ADR_WIDTH);SPI_Write_Buf(WR_TX_PLOAD,/*写待发数据指令a0*/ tx_buf, TX_PLOAD_WIDTH/*20*/);SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //数据通道0应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //接收数据通道0允许SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);//等待500+86us 自动重发10次SPI_RW_Reg(WRITE_REG + RF_CH,40);SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps ,发射功率0dBm SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); //配置寄存器CE=1;}void checkflag(){ sta=SPI_Read(STA TUS);//读状态寄存器// if(RX_DR)// {// SPI_Read_Buf(RD_RX_PLOAD/*读取接收数据指令*/,rx_buf/*数组[20]*/,TX_PLOAD_WIDTH/*20*/);// flag=1;// }if(MAX_RT){SPI_RW_Reg(FLUSH_TX/*冲洗发送FIFO指令*/,0);}SPI_RW_Reg(WRITE_REG+STATUS,sta);//清除中断}//以下是DS18B20的操作程序//************************************************************************/ void delay1ms(){unsigned char i,j;for(i=0;i<4;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*****************************************************函数功能:将DS18B20传感器初始化,读取应答信号出口参数:flag***************************************************/bit Init_DS18B20(void){bit flag; //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在DQ = 1; //先将数据线拉高for(time=0;time<2;time++) //略微延时约6微秒;DQ = 0; //再将数据线从高拉低,要求保持480~960usfor(time=0;time<200;time++) //略微延时约600微秒; //以向DS18B20发出一持续480~960us的低电平复位脉冲DQ = 1; //释放数据线(将数据线拉高)for(time=0;time<10;time++); //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)flag=DQ; //让单片机检测是否输出了存在脉冲(DQ=0表示存在)for(time=0;time<200;time++) //延时足够长时间,等待存在脉冲输出完毕;return (flag); //返回检测成功标志}/*****************************************************函数功能:从DS18B20读取一个字节数据出口参数:dat***************************************************/unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat; //储存读出的一个字节数据for (i=0;i<8;i++){DQ =1; // 先将数据线拉高_nop_(); //等待一个机器周期DQ = 0; //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序_nop_(); //等待一个机器周期DQ = 1; //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备for(time=0;time<2;time++); //延时约6us,使主机在15us内采样dat>>=1;if(DQ==1)dat|=0x80; //如果读到的数据是1,则将1存入datelsedat|=0x00;//如果读到的数据是0,则将0存入dat//将单片机检测到的电平信号DQ存入r[i]for(time=0;time<8;time++); //延时3us,两个读时序之间必须有大于1us的恢复期}return(dat); //返回读出的十六进制数据}/*****************************************************函数功能:向DS18B20写入一个字节数据入口参数:dat***************************************************/WriteOneChar(unsigned char dat){unsigned char i=0;for (i=0; i<8; i++){DQ =1; // 先将数据线拉高_nop_(); //等待一个机器周期DQ=0; //将数据线从高拉低时即启动写时序DQ=dat&0x01; //利用与运算取出要写的某位二进制数据,//并将其送到数据线上等待DS18B20采样for(time=0;time<10;time++);//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样DQ=1; //释放数据线for(time=0;time<1;time++);//延时3us,两个写时序间至少需要1us的恢复期dat>>=1; //将dat中的各二进制位数据右移1位}for(time=0;time<4;time++); //稍作延时,给硬件一点反应时间}/*****************************************************函数功能:做好读温度的准备***************************************************/void ReadyReadTemp(void){Init_DS18B20(); //将DS18B20初始化WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delaynms(150); //转换一次需要延时一段时间Init_DS18B20(); //将DS18B20初始化WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位}void dwend(void){ uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位TL=ReadOneChar(); //先读的是温度值低位TH=ReadOneChar(); //接着读的是温度值高位distance_data[0]=TH ; //测量结果的高8位distance_data[1]=TL; //放入16位的高8位}void main(void){uchar xx;init_io();while(1){ReadyReadTemp() ;dwend();checkflag();for(xx=0;xx<2;xx++){tx_buf[xx]= distance_data[xx];//发数据之前必须把要发送的数据装入它}TX_Mode(); //必须启动发送模块delay_ms(5);}}接收端程序:#include <reg52.h>#include <intrins.h>#define uchar unsigned charuchar code digit[11]={"0123456789-"}; //定义字符数组显示数字uchar code Str[]={"RICHMCU DS18B20"}; //说明显示的是温度//unsigned char code Error[]={" DS18B20 ERROR"}; //说明没有检测到DS18B20 //unsigned char code Error1[]={" PLEASE CHECK"}; //说明没有检测到DS18B20 uchar code Temp[]={"WENDU:"}; //说明显示的是温度uchar code Cent[]={"Cent"}; //温度单位uchar tm[2];uchar flg=0; //负温度标志和临时暂存变量uchar tltemp;#define TX_ADR_WIDTH 5#define TX_PLOAD_WIDTH 2uchar const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};uchar rx_buf[TX_PLOAD_WIDTH];uchar tx_buf[TX_PLOAD_WIDTH];uchar flag;//标志int cout;sbit CE=P1^1; //发射高电平大于10MS 接收高电平sbit CSN=P1^2; //低电平ISP使能sbit SCK=P1^3; //下降沿sbit MOSI=P1^4; //MCU出sbit MISO=P1^5; //MCU入sbit IRQ=P1^6; //中断uchar bdata sta;sbit RX_DR =sta^6; //接收数据准备就绪sbit TX_DS =sta^5; //已发送数据sbit MAX_RT =sta^4;sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚//***************************************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 delay1ms(){unsigned char i,j;for(i=0;i<4;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}bit BusyTest(void){bit result;RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态RW=1;E=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultE=0; //将E恢复低电平return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void WriteInstruction (unsigned char dictate){while(BusyTest()==1); //如果忙就等待RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令RW=0;E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,// 就是让E从0到1发生正跳变,所以应先置"0"_nop_();_nop_(); //空操作两个机器周期,给硬件反应时间P0=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:指定字符显示的实际地址入口参数:x***************************************************/void WriteAddress(unsigned char x){WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"}/*****************************************************函数功能:将数据(字符的标准ASCII码)写入液晶模块入口参数:y(为字符常量)***************************************************/void WriteData(unsigned char y){while(BusyTest()==1);RS=1; //RS为高电平,RW为低电平时,可以写入数据RW=0;E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,// 就是让E从0到1发生正跳变,所以应先置"0"P0=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:对LCD的显示模式进行初始化设置***************************************************/void LcdInitiate(void){delaynms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x38);delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x38); //连续三次,确保初始化成功delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x06); //显示模式设置:光标右移,字符不移delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除delaynms(5); //延时5ms,给硬件一点反应时间}/*****************************************************函数功能:显示说明信息***************************************************/void display_explain(void){unsigned char i;WriteAddress(0x00); //写显示地址,将在第1行第1列开始显示i = 0; //从第一个字符开始显示while(Str[i] != '\0') //只要没有写到结束标志,就继续写{WriteData(Str[i]); //将字符常量写入LCDi++; //指向下一个字符delaynms(100); //延时100ms较长时间,以看清关于显示的说明}}/*****************************************************函数功能:显示温度符号***************************************************/void display_symbol(void){unsigned char i;WriteAddress(0x40); //写显示地址,将在第2行第1列开始显示i = 0; //从第一个字符开始显示while(Temp[i] != '\0') //只要没有写到结束标志,就继续写{WriteData(Temp[i]); //将字符常量写入LCDi++; //指向下一个字符delaynms(50); //延时1ms给硬件一点反应时间}}/*****************************************************函数功能:显示温度的小数点***************************************************/void display_dot(void){WriteAddress(0x49); //写显示地址,将在第2行第10列开始显示WriteData('.'); //将小数点的字符常量写入LCDdelaynms(50); //延时1ms给硬件一点反应时间}/*****************************************************函数功能:显示温度的单位(Cent)***************************************************/void display_cent(void){unsigned char i;WriteAddress(0x4c); //写显示地址,将在第2行第13列开始显示i = 0; //从第一个字符开始显示while(Cent[i] != '\0') //只要没有写到结束标志,就继续写{WriteData(Cent[i]); //将字符常量写入LCDi++; //指向下一个字符delaynms(50); //延时1ms给硬件一点反应时间}}/*****************************************************函数功能:显示温度的整数部分入口参数:x***************************************************/void display_temp1(uchar x){uchar j,k,l; //j,k,l分别储存温度的百位、十位和个位j=x/100; //取百位k=(x%100)/10; //取十位l=x%10; //取个位WriteAddress(0x46); //写显示地址,将在第2行第7列开始显示if(flg==1) //负温度时显示“—”{WriteData(digit[10]); //将百位数字的字符常量写入LCD}else{WriteData(digit[j]); //将十位数字的字符常量写入LCD}WriteData(digit[k]); //将十位数字的字符常量写入LCDWriteData(digit[l]); //将个位数字的字符常量写入LCDdelaynms(5); //延时1ms给硬件一点反应时间}/*****************************************************函数功能:显示温度的小数数部分入口参数:x***************************************************/void display_temp2(uchar x){WriteAddress(0x4a); //写显示地址,将在第2行第11列开始显示WriteData(digit[x]); //将小数部分的第一位数字字符常量写入LCD delaynms(5); //延时1ms给硬件一点反应时间}void init_io(void){CE=0;CSN=1;SCK=0;}void delay_ms(unsigned int x){unsigned int i,j;for(i=0;i<x;i++){j=108;while(j--);}}uchar SPI_RW(uchar byte){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++){MOSI = (byte&0x80);byte = (byte<<1);SCK = 1;byte|=MISO;SCK=0;}return(byte);}uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0;status = SPI_RW(reg);SPI_RW(value);CSN = 1;return(status);}uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0;SPI_RW(reg);reg_val = SPI_RW(0);CSN = 1;return(reg_val);}uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes) {uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)pBuf[byte_ctr] = SPI_RW(0);CSN = 1;return(status);}uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) {uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)SPI_RW(*pBuf++);CSN = 1;return(status);}void RX_Mode(void){CE=0;SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //数据通道0应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);//接收数据通道0允许SPI_RW_Reg(WRITE_REG + RF_CH, 40);SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);// 接收频道0 接收数据长度设置SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps ,发射功率0dBm SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); //配置寄存器CE = 1;}void checkflag(){sta=SPI_Read(STA TUS);if(RX_DR){SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);flag=1;}if(MAX_RT){SPI_RW_Reg(FLUSH_TX,0);}SPI_RW_Reg(WRITE_REG+STATUS,sta);}void yejinchu(void){LcdInitiate(); //将液晶初始化delaynms(5); //延时5ms给硬件一点反应时间display_explain();display_symbol(); //显示温度说明display_dot(); //显示温度的小数点display_cent(); //显示温度的单位}void xianshi(void){uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位uchar TN; //储存温度的整数部分uchar TD; //储存温度的小数部分TH=tm[0] ;TL=tm[1];if((TH&0xf8)!=0x00)//判断高五位得到温度正负标志{flg=1;TL=~TL; //取反TH=~TH; //取反tltemp=TL+1; //低位加1TL=tltemp;if(tltemp>255) TH++; //如果低8位大于255,向高8位进1TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16//这样得出的是温度的整数部分,小数部分被丢弃了TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,}TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16//这样得出的是温度的整数部分,小数部分被丢弃了TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,//这样得到的是温度小数部分的第一位数字(保留1位小数)display_temp1(TN); //显示温度的整数部分display_temp2(TD); //显示温度的小数部分delaynms(5);}void main(void){uchar xx;yejinchu();init_io();RX_Mode();while(1){checkflag();if(flag){flag=0;for(xx=0;xx<2;xx++){tm[xx]=rx_buf[xx];delay_ms(1);}xianshi();}}}。
NRF24L01的发送与接收程序
#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//****************************************NRF24L01端口定义sbit MISO =P1^5;sbit MOSI =P1^1;sbit SCK =P1^6;sbit CE =P1^7;sbit CSN =P1^2;sbit IRQ =P1^0;//************************************按键sbit KEY1=P3^4;//************************************蜂明器sbit LED=P3^5;//**************#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 32 // 20 uints TX payload#define RX_PLOAD_WIDTH 32 // 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 clock line init highSPI_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,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收}/******************************************************************************/*函数: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 StartUART( void ){ //波特率4800SCON = 0x50;TMOD = 0x20;TH1 = 0xFA;TL1 = 0xFA;PCON = 0x00;TR1 = 1;}//************************************通过串口将接收到数据发送给PC端void R_S_Byte(uchar R_Byte){SBUF = R_Byte;while( TI == 0 ); //查询法TI = 0;}//************************************主函数void main(void){uchar i,temp;uchar RxBuf[32];init_NRF24L01() ;StartUART();Delay(6000);while(1){SetRX_Mode();if(nRF24L01_RxPacket(RxBuf)){LED=0;temp++;for(i=0;i<32;i++){R_S_Byte(RxBuf[i]);Delay(600);}}LED=1;Delay(600);}}#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//****************************************NRF24L01端口定义sbit MISO =P1^5;sbit MOSI =P1^1;sbit SCK =P1^6;sbit CE =P1^7;sbit CSN =P1^2;sbit IRQ =P1^0;//************************************按键sbit KEY1=P3^4;//************************************蜂明器sbit LED=P3^5;//***********************************发送缓冲区uchar TxBuf[32]={0x01,0x02,0x03,0x4,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32,}; ////*********************************************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 32 // 20 uints TX payload#define RX_PLOAD_WIDTH 32 // 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 clock line init highSPI_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,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送}/**************/*函数: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 MOSI uchar = (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 ,主接收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){uchar temp =0;init_NRF24L01() ;nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataDelay(6000);P0=0xBF;{nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data LED=0;Delay(10000); //可变SPI_RW_Reg(WRITE_REG+STATUS,0XFF);LED=1;Delay(8000);}}。
nRF24L01的工作原理
nRF24L01的工作原理nRF24L01是一种低功耗2.4GHz无线收发器,广泛应用于无线通信领域。
它采用射频(RF)技术,能够在2.4GHz频段进行无线通信,并具备较高的数据传输速率和较低的功耗。
nRF24L01工作原理主要包括无线信号传输、数据编码和解码、频率选择和信号调制等关键步骤。
下面将详细介绍nRF24L01的工作原理。
1. 无线信号传输nRF24L01通过天线接收或发送无线信号。
在发送端,待发送的数据通过SPI (串行外设接口)与nRF24L01进行通信,nRF24L01将数据转换为无线信号并通过天线发送出去。
在接收端,nRF24L01通过天线接收到的无线信号,将其转换为数字信号,并通过SPI与微控制器进行通信,将接收到的数据传输给用户。
2. 数据编码和解码nRF24L01使用一种称为Enhanced ShockBurst™的编码技术,用于提高数据传输的可靠性和抗干扰能力。
发送端将待发送的数据分为多个数据包,并对每个数据包进行编码和校验,以确保数据的完整性和准确性。
接收端对接收到的数据包进行解码和校验,以还原原始数据。
3. 频率选择nRF24L01可以在2.4GHz频段的多个不重叠的信道中进行通信。
通过选择不同的信道,可以避免与其他无线设备的干扰。
nRF24L01支持2.4GHz频段的125个信道,其中2.4GHz到2.525GHz范围内有16个信道,每个信道之间的频率间隔为1MHz。
4. 信号调制nRF24L01使用高级调制技术,将数字信号转换为模拟信号进行无线传输。
它采用高级调制方式,如GFSK(高斯频移键控)调制,以提高数据传输的可靠性和抗干扰能力。
GFSK调制技术通过改变载波频率的相位,将数字信号转换为模拟信号,并通过天线进行传输。
5. 功耗控制nRF24L01具有低功耗特性,能够在不同的功耗模式之间进行切换,以满足不同应用场景的需求。
它支持多种低功耗模式,如睡眠模式、待机模式和接收模式等。
NRF24L01的发送与接收程序
#include <> #include <>typedef unsigned char uchar;typedef unsigned char uint;SCK = 1;uchar |= MISO; then set SCK low again}return(uchar); .SPI_RW(reg);reg_val = SPI_RW(0); then read registervalueCSN = 1; and write value to it..CSN = 1;SCK = 1;uchar |= MISO; then set SCK low again}return(uchar); .SPI_RW(reg);reg_val = SPI_RW(0); then read registervalueCSN = 1; and write value to it..CSN = 1; // CSN high again/* 函数: 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 tranaction return(status); }// return nRF24L01 status ucharstatus = 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); 接收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 frombuffer// IRQ 收发完成中断响应, 16 位 CRC,主 FIFOSPI_RW_Reg(WRITE_REG+STATUS,sta); // 接收到数据后RX_DR,TX_DS,MAX_P都置高为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, OxOe); // IRQ 收发完成中断响应,16 位CRC 主发送CE=1; //置高CE激发数据发送inerDelay_us(1O);}//************************************ void main(void){uchar temp =O;init_NRF24LO1() ;nRF24LO1_TxPacket(TxBuf);Delay(6OOO);PO=OxBF;主函数// Transmit Tx buffer datawhile(1)nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataLED=0;Delay(10000); // 可变SPI_RW_Reg(WRITE_REG+STATUS,0XFF);LED=1;Delay(8000);}。
NRF24L01功能使用文档
NRF24L01功能使用文档一、NRF24L01的功能特点:1.双向通信:NRF24L01可以同时作为发送器和接收器,实现双向通信。
这意味着可以用它构建各种无线传感器网络。
2. 高速数据传输:NRF24L01的最大数据传输速率为2Mbps,这使得它可以用于高速数据传输的应用场景,如视频传输。
3.高可靠性:NRF24L01具有自动重复传输和错误检测功能。
当传输数据时,NRF24L01会自动重复发送数据,并在接收端检测错误。
这提高了数据传输的可靠性。
4.小尺寸和低功耗:NRF24L01的尺寸小,只有20针的QFN封装,适用于各种空间受限的应用场景。
同时,它的工作电压范围广,只需1.9-3.6V,功耗低。
5.多通道:NRF24L01支持多达125个通道,这使得它可以与其他无线设备同时工作,避免干扰。
二、NRF24L01的使用方法:1. 引脚连接:首先,将NRF24L01的引脚连接到主控制器(如Arduino)上。
连接时需要注意引脚的对应关系,如CE(引脚1)连接到主控制器的数字引脚9上,CSN(引脚2)连接到数字引脚10上,SCK (引脚3)连接到数字引脚13上,等等。
2.配置寄存器:NRF24L01有多个寄存器,用于配置各种参数。
可以通过SPI接口向这些寄存器写入数据来配置NRF24L01、例如,可以通过写入到寄存器地址0x00的数据来配置NRF24L01的发射功率、数据传输速率、等等。
3.发送数据:在发送数据之前,需要将NRF24L01设置为发送模式。
首先,将CE置高,然后向TXFIFO寄存器中写入数据。
NRF24L01会自动将数据传输给接收器,并等待接收器的确认。
4.接收数据:在接收数据之前,需要将NRF24L01设置为接收模式。
首先,将CE置高,然后等待数据的接收。
一旦接收到数据,可以从RXFIFO寄存器中读取数据。
5.错误处理:当数据传输过程中出现错误时,NRF24L01会自动重复发送数据。
NRF24L01无线模块收发程序(实测成功多图)
NRF24L01无线模块收发程序(实测成功多图)本模块是NRF24L01无线传输模块,用于无线传输数据,距离不远,一般只是能够满足小距离的传输,目测是4-5m,价格一般是4元左右,可以方便的买到。
51最小系统学习板就可以,当时是用了两块学习板,一块用于发送,一块用于接收。
小车也是比较容易购到的,四个端口控制两个电机,两个控制一个电机,当两个端口高低电平不同时电机就会转动,即为赋值1和0是电机转动,赋值可以用单片机作用,当然这是小车启动部分,前进后退左转右转就是你赋值0和1的顺序问题了。
整体思路是用发射端的按键控制小车,即为按键按下就前进,再按其他按键实现其他功能,本次程序是在用NRF24L01发射数据在接收端用1602显示的基础上改变。
下面是程序源码(有好几个文件,分别创建)1.//////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////2.#include3.4.#include5.6.#include'1602.h'7.#include'delay.h'8.#include 'nrf24l01.h'9.#define uint unsigned int10.#define uchar unsigned char11.uint Weight_Shiwu=1234;12.unsigned char KeyScan(void);//键盘扫描13.// unsigned char KeyScan(void);//键盘扫描14.15.//#define KeyPort P016.sbit KEY1 = P0^0;17.sbit KEY2 = P0^1;18.sbit KEY3 = P0^2;19.sbit KEY4 = P0^3;20.sbit KEY5 = P0^4;21.void main()22.{23.// char TxDate[4];24.// LCD_Init(); //初始化液晶屏25.// LCD_Clear(); //清屏26.// NRF24L01Int(); //初始化LCD160227.// LCD_Write_String(4,0,'welcome');28.while(1)29.{30.KeyScan();31.32.}33.}34.35.36.37.38.unsigned char KeyScan(void)39.{40./******************************************************** /42.{43.if(!KEY1) //如果检测到低电平,说明按键按下44.{45.DelayMs(10); //延时去抖,一般10-20ms46.if(!KEY1) //再次确认按键是否按下,没有按下则退出47.{48.while(!KEY1);//如果确认按下按键等待按键释放,没有则退出49.{50.TxDate[0] = 1;//向左转51.TxDate[1] = 0;52.TxDate[2] = 1;53.TxDate[3] = 1;54.NRFSetTxMode(TxDate);//发送数据·55.while(CheckACK()); //检测是否发送完毕56.}57.}58.}59./******************************************************** /60.else if(!KEY2) //如果检测到低电平,说明按键按下61.{62.DelayMs(10); //延时去抖,一般10-20ms63.if(!KEY2) //再次确认按键是否按下,没有按下则退出64.{65.while(!KEY2);//如果确认按下按键等待按键释放,没有则退出66.{67.TxDate[0] = 1;//向右转69.TxDate[2] = 1;70.TxDate[3] = 0;71.NRFSetTxMode(TxDate);//发送数据72.while(CheckACK()); //检测是否发送完毕73.}74.}75.}76./******************************************************** /77.else if(!KEY3) //如果检测到低电平,说明按键按下78.{79.DelayMs(10); //延时去抖,一般10-20ms80.if(!KEY3) //再次确认按键是否按下,没有按下则退出81.{82.while(!KEY3);//如果确认按下按键等待按键释放,没有则退出83.{84.TxDate[0] = 1;//前进85.TxDate[1] = 0;86.TxDate[2] = 1;87.TxDate[3] = 0;88.NRFSetTxMode(TxDate);//发送数据89.while(CheckACK()); //检测是否发送完毕90.}91.}92.}93./******************************************************** /94.else if(!KEY4) //如果检测到低电平,说明按键按下96.DelayMs(10); //延时去抖,一般10-20ms97.if(!KEY4) //再次确认按键是否按下,没有按下则退出98.{99.while(!KEY4);//如果确认按下按键等待按键释放,没有则退出100.{101.TxDate[0] = 0;//后退102.TxDate[1] = 1;103.TxDate[2] = 0;104.TxDate[3] = 1;105.NRFSetTxMode(TxDate);//发送数据106.while(CheckACK()); //检测是否发送完毕107.}108.}109.}110.else if(!KEY5)111.{112.DelayMs(10);113.if(!KEY5)114.{115.while(!KEY5)116.{117.TxDate[0] = 1;118.TxDate[1] = 1;119.TxDate[2] = 1;120.TxDate[3] = 1;121.NRFSetTxMode(TxDate);122.while(CheckACK());123.}125.}126.}127.}1.//////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////2.#include3.4.#include5.6.#include'1602.h'7.#include'delay.h'8.#include 'nrf24l01.h'9.#define uint unsigned int10.#define uchar unsigned char11.uint Weight;12.sbit a = P2^0;13.sbit b = P2^1;14.sbit c = P2^2;15.sbit d = P2^3;16.void main()17.{18.LCD_Init(); //初始化液晶屏19.LCD_Clear(); //清屏20.*(RevTempDate+4)=*\0*;21.NRF24L01Int();22.while(1)23.{25.NRFSetRXMode();//设置为接收模式26.GetDate();//开始接受数;27.//Weight=RevTempDate[0]*1000+RevTempDate[1]*100+RevTemp Date[2]*10+RevTempDate[3];28.LCD_Write_Char(7,0,RevTempDate[0]+0x30);29.LCD_Write_Char(8,0,RevTempDate[1]+0x30);30.LCD_Write_Char(9,0,RevTempDate[2]+0x30);31.LCD_Write_Char(10,0,RevTempDate[3]+0x30);32. a = RevTempDate[0];//根据接受数据来设置高低电平(目测仅限传输1.0两种数值)33. b = RevTempDate[1];34. c = RevTempDate[2];35. d = RevTempDate[3];36.}37.}38.39.///////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////1.#include2.3.#include 'nrf24l01.h'4.#define uchar unsigned char5.#define uint unsigned int6.sbit IRQ =P1^2;//输入7.sbit MISO =P1^3; //输入8.sbit MOSI =P1^1;//输出9.sbit SCLK =P1^4;//输出10.sbit CE =P1^5;//输出11.sbit CSN =P1^0;//输出12.uchar code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址13./*****************状态标志*****************************************/14.uchar bdata sta; //状态标志15.sbit RX_DR=sta^6;16.sbit TX_DS=sta^5;17.sbit MAX_RT=sta^4;18./*****************SPI时序函数******************************************/19.uchar NRFSPI(uchar date)20.{21.uchar i;22.for(i=0;i<8;i++)>23.{24.if(date&0x80)25.MOSI=1;26.else27.MOSI=0; // byte最高位输出到MOSI28.date<=1;>29.SCLK=1;30.if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据31.date|=0x01; // 读MISO到byte最低位32.SCLK=0; // SCK置低33.}34.return(date); // 返回读出的一字节35.}36./**********************NRF24L01初始化函数*******************************/37.void NRF24L01Int()38.{39.DDelay(2);//让系统什么都不干40.CE=0; //待机模式141.CSN=1;42.SCLK=0;43.IRQ=1;44.}45./*****************SPI读寄存器一字节函数*********************************/46.uchar NRFReadReg(uchar RegAddr)47.{48.uchar BackDate;49.CSN=0;//启动时序50.NRFSPI(RegAddr);//写寄存器地址51.BackDate=NRFSPI(0x00);//写入读寄存器指令52.CSN=1;53.return(BackDate); //返回状态54.}55./*****************SPI写寄存器一字节函数*********************************/56.uchar NRFWriteReg(uchar RegAddr,uchar date)57.{58.uchar BackDate;59.CSN=0;//启动时序60.BackDate=NRFSPI(RegAddr);//写入地址61.NRFSPI(date);//写入值62.CSN=1;63.return(BackDate);64.}65./*****************SPI读取RXFIFO寄存器的值********************************/66.uchar NRFReadRxDate(uchar RegAddr,uchar *RxDate,uchar DateLen)67.{ //寄存器地址//读取数据存放变量//读取数据长度//用于接收68.uchar BackDate,i;69.CSN=0;//启动时序70.BackDate=NRFSPI(RegAddr);//写入要读取的寄存器地址71.for(i=0;i72.{73.RxDate[i]=NRFSPI(0);74.}75.CSN=1;76.return(BackDate);77.}78./*****************SPI写入TXFIFO寄存器的值**********************************/79.uchar NRFWriteTxDate(uchar RegAddr,uchar *TxDate,uchar DateLen)80.{ //寄存器地址//写入数据存放变量//读取数据长度//用于发送81.uchar BackDate,i;82.CSN=0;83.BackDate=NRFSPI(RegAddr);//写入要写入寄存器的地址84.for(i=0;i85.{86.NRFSPI(*TxDate++);87.}88.CSN=1;89.return(BackDate);90.}91./*****************NRF设置为发送模式并发送数据******************************/92.void NRFSetTxMode(uchar *TxDate)93.{//发送模式94.CE=0;95.NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_A DDR_WITDH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度96.NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同97.NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WIT DH);//写入数据98./******下面有关寄存器配置**************/99.NRFWriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答100.NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0101.NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等待250us+86us,自动重发10次102.NRFWriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40103.NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益104.NRFWriteReg(W_REGISTER+CONFIG,0x0e); // CRC使能,16位CRC校验,上电105.CE=1;106.DDelay(5);//保持10us秒以上107.}108./*****************NRF设置为接收模式并接收数据******************************/109.//主要接收模式110.void NRFSetRXMode()111.{112.CE=0;113.NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址114.NRFWriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答115.NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0116.NRFWriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40117.NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WIT DH); // 接收通道0选择和发送通道相同有效数据宽度118.NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/119.NRFWriteReg(W_REGISTER+CONFIG,0x0f); // CRC使能,16位CRC校验,上电,接收模式120.CE = 1;121.DDelay(5);//保持10us秒以上122.}123./****************************检测应答信号******************************/124.uchar CheckACK()125.{ //用于发射126.sta=NRFReadReg(R_REGISTER+STATUS); // 返回状态寄存器127.if(TX_DS||MAX_RT) //发送完毕中断128.{129.NRFWriteReg(W_REGISTER+STATUS,0xff); // 清除TX_DS或MAX_RT中断标志130.CSN=0;131.NRFSPI(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现意想不到的后果大家记住!!132.CSN=1;133.return(0);134.}135.else136.return(1);137.}138./******************判断是否接收收到数据,接到就从RX 取出*********************/139.//用于接收模式140.uchar NRFRevDate(uchar *RevDate)141.{142.uchar RevFlags=0;143.sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器144.if(RX_DR) // 判断是否接收到数据145.{146.CE=0; //SPI使能147.NRFReadRxDate(R_RX_PAYLOAD,RevDate,RX_DATA_WI TDH);// 从RXFIFO读取数据148.RevFlags=1; //读取数据完成标志149.}150.NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标151.return(RevFlags);152.}153.void DDelay(uint t)154.{155.uint x,y;156.for(x=t;x>0;x--)157.for(y=110;y>0;y--);158.}159.///////////////////////////////////////////////////////////// ///////////////////////////////////////////1.#include 'delay.h'2./*------------------------------------------------延时函数,含有输入参数 unsigned char t,无返回值4.unsigned char 是定义无符号字符变量,其值的范围是5.0~255 这里使用晶振12M,精确延时请使用汇编,大致延时6.长度如下 T=tx2+5 uS7.------------------------------------------------*/8.void DelayUs2x(unsigned char t)9.{10.while(--t);11.}12./*------------------------------------------------13.mS延时函数,含有输入参数 unsigned char t,无返回值14.unsigned char 是定义无符号字符变量,其值的范围是15.0~255 这里使用晶振12M,精确延时请使用汇编16.------------------------------------------------*/17.void DelayMs(unsigned char t)18.{19.20.while(t--)21.{22.//大致延时1mS23.DelayUs2x(245);24.DelayUs2x(245);25.26.}27.}28.///////////////////////////////////////////////////////////// //////////////////////////////1.下面是接收的NRF24L01的程序。
nrf24l01的收发信号资料
2014无线电电子设计大赛题目:NRF24L01的收发信号队号:三个烙铁匠队员:王晖曹恒万东胜摘要随着现代电子技术的飞速发展,通信技术也取得了长足的进步。
在无线通信领域,越来越多的通信产品大量涌现出来。
但设计无线数据传输产品往往需要相当的无线电专业知识和价格高昂的专业设备,因而影响了用户的使用和新产品的开发。
nRF24L01是一个为433MHz ISM频段设计的无线收发芯片,它为短距离无线数据传输应用提供了较好的解决办法, 使用nRF24L01降低了开发难度,缩短了开发周期,使产品能更快地推向市场。
本文提出了一种应用于无线数据收发系统的设计思路及实现方案,给出了基于无线射频芯片nRF24L01和STC89C52单片机的无线数据传输模块的设计方法,详细分析了各部分实现原理,并对系统的传输距离、传输数据的正确性进行了测试。
试验表明,该系统性能稳定,具有较强的抗干扰能力,有较强的实用价值。
关键词:无线通信;无线数据传输模块;单片机;射频AbstractWith the rapid development of modern electronic technology, communication technology has also made great progress. In the field of wireless communication, more and more communication products have sprung up in large quantities. But the design of wireless data transmission products often require considerable radio of the high price of professional knowledge and professional equipment, thus affecting the user's use and development of new products. NRF24L01 is a designed for 433 MHZ ISM band wireless transceiver chip, it for the short distance wireless data transmission application provides a better solution, using nRF24L01 reduces the development difficulty, shorten the development cycle, can make the product to market faster. This paper puts forward a kind of applied to wireless data transceiver system design idea and implementation scheme, and is given based on wireless rf chip nRF24L01 and STC89C52 single-chip wireless data transmission module, the design method of the realization principle of each part are analyzed in detail, and the transmission distance of the system, the correctness of the data transmission was tested. Tests show that the system performance is stable, stronganti-interference ability, a strong practical value.Keywords:Wireless communication;Wireless data transmission module;Single chip microcomputer;Radio frequency目录前言 (1)1系统设计 (1)1.1系统设计 (2)1.2实现过程 (2)2系统组成 (3)2.1 射频收发控制模块 (3)2.1.1 无线收发芯片nRF24L01介绍 (3)2.1.2 稳压部分 (5)2.2单片机控制部分 (5)2.2.1 STC89C52RC功能介绍 (6)2.2.2 内部结构 (6)2.2.3 串口通信 (8)2.3 显示部分 (9)3软件设计 (10)3.1 主程序流程图 (11)3.2 数据收发子程序流程图 (11)4测试结果及分析 (12)4.1 硬件电路测试 (13)4.2 系统测试 (13)4.2.1 测试方法 (13)4.2.2 功能测试及分析 (13)5结论 (14)6参考文献 (15)附录1:无线发射系统电路图 (16)附录 2:发送程序 (17)前言伴随着短距离、低功率无线数据传输技术的成熟,无线数据传输被越来越多地应用到新的领域。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command
#define NOP 0xFF // Define No Operation, might be used to read status register
sbit IRQ = P1^2; // Interrupt signal, from nRF24L01 (input)
sbit MISO= P1^3; // Master In, Slave Out pin (input)
sbit SCLK= P1^4; // Serial Clock pin, (output)
#define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址
#define TX_PLOAD_WIDTH 4 //数据通道有效数据宽度
uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; //定义一个静态发送地址
#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
Byte |=MISO; //读MISO到byte最低位
SCLK=0; // SCK置低
}
return Byte; //返回读出的一字节
}
/*写数据value到reg寄存器*/
uchar SPI_Write_Read_Register(uchar Reg,uchar value)
{
uchar Status;
SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x01); //使能接收通道0
SPI_Write_Read_Register(WRITE_REG + RF_CH, 0x00); //选择射频通道0x00
SPI_Write_Read_Register(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); //接收通道0选择和发送通道相同有效数据宽度
for(i=0;i<Bytes;i++)
{
SPI_Write_Read(Buf[i]); //逐个字节写入nRF24L01
}
CSN=1; // CSN拉高,结束数据传输
return Status; //返回状态寄存器
}
/*设置nRF24L01为接收模式,等待接收发送设备的数据包*/
/*void RX_Mode(void)
#include <reg52.h>
#include <mБайду номын сангаасth.h>
#include <stdio.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
/***************************************************/
/*uchar SPI_Read(uchar Reg)
{
uchar result;
CSN=0; // CSN置低,开始传输数据
SPI_Write_Read(Reg); //选择寄存器
result=SPI_Write_Read(0); //然后从该寄存器读数据
CSN=1; // CSN拉高,结束数据传输
#define RD_RX_PLOAD 0x61 // Define RX payload register address
#define WR_TX_PLOAD 0xA0 // Define TX payload register address
#define FLUSH_TX 0xE1 // Define flush TX register command
SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式
CE=1;//拉高CE启动接收设备
#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address
#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address
#define TX_ADDR 0x10 // 'TX address' register address
#define RF_CH 0x05 // 'RF channel' register address
#define RF_SETUP 0x06 // 'RF setup' register address
#define STATUS 0x07 // 'Status' register address
#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address
#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address
#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address
{
CE=0;
SPI_Write_Buffer(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);//接收设备接收通道0使用和发送设备相同的发送地址
SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x01); //使能接收通道0自动应答
#define EN_RXADDR 0x02 // 'Enabled RX addresses' register address
#define SETUP_AW 0x03 // 'Setup address width' register address
#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
return result; //返回寄存器数据
} */
/*从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址*/
/*uchar SPI_Read_Buffer(uchar Reg,uchar *Buf,uchar Bytes)
{
uchar Status,i;
CSN=0; // CSN置低,开始传输数据
uchar SPI_Write_Read(uchar Byte)
{
uchar i;
for(i=0;i<8;i++) //循环8次
{
MOSI=(Byte&0x80); // byte最高位输出到MOSI
Byte<<=1; //低一位移位到最高位
SCLK=1; //拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
sbit CE = P1^5; // Master Out, Slave In pin (output)
// SPI(nRF24L01) commands
#define READ_REG 0x00 // Define read command to register
#define WRITE_REG 0x20 // Define write command to register
#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address
uchar bdata Sta;
uchar code Dis[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阳数码管花数。
// SPI(nRF24L01) registers(addresses)
#define CONFIG 0x00 // 'Config' register address
#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address
Status=SPI_Write_Read(Reg); //选择寄存器,同时返回状态字
for(i=0;i<Bytes;i++)
{
Buf[i]=SPI_Write_Read(0);//逐个字节从nRF24L01读出