基于NRF24L01+温度无线传输51单片机
- 格式:doc
- 大小:387.50 KB
- 文档页数:20
#include<reg52.h>#include<nfr2401.h>#define uchar unsigned char#define TX_ADR_WIDTH 5 // 5 bytes TX(RX) address width#define TX_PLOAD_WIDTH 2 // 20 bytes TX payloaduchar const TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // Define a static TX addressuchar rx_buf[TX_PLOAD_WIDTH];uchar tx_buf[TX_PLOAD_WIDTH]={0x12};uchar flag;sbit CE =P0^0 ;sbit CSN =P0^1 ;sbit SCK =P0^2 ;sbit MOSI =P0^3 ;sbit MISO =P0^4 ;sbit IRQ =P0^5 ;uchar spi_rw(uchar dat);uchar write_reg(uchar reg,uchar dat);uchar read_reg(uchar reg);uchar write_reg_bytes(uchar reg,uchar *pbuf,uchar x);uchar read_reg_bytes(uchar reg,uchar *pbuf,uchar x);void rx_mode();void tx_mode();void into_nfr();void delay(uchar m);//uchar cheeckRT();uchar cheeckAT();void send(uchar m);uchar spi_rw(uchar dat){uchar byt;for(byt=0;byt<8;byt++){MOSI=dat&0x80;dat=dat<<1;SCK=1;dat|=MISO;SCK=0;}return dat ; //用spi写入一个字节的时序}uchar write_reg(uchar reg,uchar dat){uchar byt;CSN=0;byt=spi_rw(reg);spi_rw(dat);return byt; //向某一个寄存器写入一个字节}uchar read_reg(uchar reg){uchar byt;CSN=0;spi_rw(reg);byt=spi_rw(0);return byt; //读某一个寄存器的内容}uchar write_reg_bytes(uchar reg,uchar *pbuf,uchar x){uchar byt,sta;CSN=0;sta=spi_rw(reg);for(byt=0;byt<x;byt++)spi_rw(*pbuf++);CSN=1;return sta; //向某一个寄存器写入x个字节}uchar read_reg_bytes(uchar reg,uchar *pbuf,uchar x){uchar byt,sta;CSN=0;sta=spi_rw(reg);for(byt=0;byt<x;byt++)pbuf[byt]=spi_rw(0);CSN=1;return sta; //从某一个寄存器读出x个字节}/**************************************************************** ***void rx_mode(){CE=0;write_reg_bytes(WRITE_REG+RX_ADDR_P0,TX_ADDR,TX_ADR_WID TH);write_reg(WRITE_REG+EN_AA,0x01);write_reg(WRITE_REG+EN_RXADDR,0x01);write_reg(WRITE_REG+RF_CH,0x40);write_reg(WRITE_REG+RX_ADDR_P0,TX_ADR_WIDTH);write_reg(WRITE_REG+RF_SETUP,0x07);write_reg(WRITE_REG+CONFIG,0x0f); //设置接收模式的寄存器CE=1;}***************************************************************** ****/void tx_mode(uchar *tx_buf){CE=0;write_reg_bytes(WRITE_REG+TX_ADDR,TX_ADDR,TX_ADR_WIDTH) ;write_reg_bytes(WRITE_REG+RX_ADDR_P0,TX_ADDR,TX_ADR_WID TH);write_reg_bytes(W_TX_PAYLAD,tx_buf,TX_PLOAD_WIDTH);write_reg(WRITE_REG+EN_AA,0x01);write_reg(WRITE_REG+EN_RXADDR,0x01);write_reg(WRITE_REG+RF_CH,0x40);write_reg(WRITE_REG+RX_ADDR_P0,TX_ADR_WIDTH);write_reg(WRITE_REG+SETUP_RETR,0x0a);write_reg(WRITE_REG+RF_SETUP,0x07);write_reg(WRITE_REG+CONFIG,0x0e);CE=1;delay(0x02);}void into_nfr(){CE=0;CSN=1;SCK=0;}uchar cheeckAT(){uchar sta;sta=spi_rw(READ_REG+STATUS);if(sta&0x30){write_reg(WRITE_REG+STATUS,0xff);CSN=0;spi_rw(FLUSH_TX);CSN=1;return (0);}elsereturn (1);}/**************************************************************** *uchar cheeckRT(){uchar sta;sta=spi_rw(READ_REG+STATUS);if(sta&0x20){CE=0 ;read_reg_bytes(R_RX_PAYLAD,rx_buf,TX_PLOAD_WIDTH);return 1;}write_reg(WRITE_REG+STATUS,0xff);return 0;}//**************************************************************** **void send(uchar m){SBUF=m;while(!TI);TI=0;}***************************************************************** ***/void allow() interrupt 4{if(RI){RI=0;tx_buf[0]=SBUF;flag=1;P1=tx_buf[0];}}void delay(uchar m){uchar i;while(m--){for(i=104;i>0;i--);}}void main(){into_nfr();TMOD=0x20;SCON=0x50;TH1=0xfd;// TR1=1;ES=1;// EA=1;// tx_mode();while(1){// if(flag==1)// {flag=0;//CE=0;//write_reg_bytes(W_TX_PAYLAD,tx_buf,TX_PLOAD_WIDTH);//CE=1;tx_mode(tx_buf);while(cheeckAT()); P2=0xf0;// }}}。
毕业设计(论文)基于NRF24L01无线温度测量系统的设计与实现教学系:信息工程系指导教师:专业班级:学生姓名:二零一二年六月附件1毕业设计(论文)任务书附件2毕业设计(论文)开题报告注:1. 开题报告应根据教师下发的毕业设计(论文)任务书,在教师的指导下由学生独立撰写,在学院规定时间内完成;2.设计的目的及意义至少800字,基本内容和技术方案至少400字;3.指导教师意见应从选题的理论或实际价值出发,阐述学生利用的知识、原理、建立的模型正确与否、学生的论证充分否、学生能否完成课题,达到预期的目标目录摘要 (1)ABSTRAC (2)1 绪论 (3)1.1 研究背景 (3)1.2 课题的国内外研究状况 (3)1.3 本课题的研究内容 (4)2系统方案分析与选择论证 (5)2.1 系统方案设计 (5)2.1.1 系统设计要求 (5)2.1.2 主控芯片方案 (5)2.1.3 无线通信模块方案 (5)2.1.4 温度传感方案 (5)2.1.5 显示模块方案 (6)2.1.6 单片机与PC机通信模块 (6)2.2 系统方案确定 (6)3 无线温度采集系统的硬件电路设计 (8)3.1 单片2.4GHz NRF24L01无线模块 (8)3.1.1 NRF24L01芯片概述 (8)3.1.2 引脚功能及描述 (8)3.1.3 工作模式 (9)3.1.4 工作原理 (9)3.1.5 配置字 (10)3.1.6 NRF24L01模块原理图 (10)3.2 温度采集端 (11)3.2.1 采集单元 (11)3.2.2 控制单元 (15)3.2.3 显示单元 (19)3.2.4 传输单元 (19)3.2.5 报警单元 (20)3.4 电源管理 (21)3.4.1 稳压电源的组成 (21)3.4.2 电源设计 (22)3.5 看门狗电路 (22)3.6 时钟电路和复位电路 (23)4 软件编制与程序实现 (25)4.1 系统软件设计 (25)4.1.1 上位机程序设计 (25)4.1.2 下位机程序设计 (25)4.2 程序设计语言的选用 (25)4.3 测温程序设计流程 (26)4.3.1 主程序 (26)4.3.2 读出温度子程序 (26)4.3.3 温度转换命令子程序 (28)4.3.4 计算温度子程序 (29)4.3.5 显示数据刷新子程序 (29)4.4 无线通信协议 (29)4.4.1 通信信道 (20)4.4.2 数据传输协议 (29)5 系统仿真 (31)5.1 电源电路的仿真 (31)5.1.1 +5V电源电路仿真 (31)5.2 发送端温度采集与显示仿真 (31)5.3 接收端LCD1602显示温度仿真 (32)6总结与展望 (33)6.1 系统调试 (33)6.2 温度对比 (33)6.3 总结与展望 (33)参考文献 (35)致谢 (39)摘要温度是一个非常重要的参数。
摘要当今,通过信息的采集、传输、处理和控制器作出相应的决策,进而实现对一定对象的监控和控制,是一个无论在民用、工业,还是军事领域,都被人们乐此不疲地研究着的热门技术。
而信息传输的可靠性无疑是控制器作出正确决策的重要前提。
无线传输以其成本廉价、占用空间小、环境适应性好、扩展性好和设备维护上更容易实现等优点正在逐步越来越受到人们的青睐。
RF24L01SE微功率无线通讯模块,采用Nordic公司的NRF24L01芯片,2.4G全球开发ISM频段免许可证使用,最高工作速率达2Mbps,125频道满足多点通信和跳频通信需要,体积小巧约31mm*17mm,尤其方便嵌入式开发与应用,高效GFSK调制,抗干扰能力强,特别适合无线音视频传输、工业控制领域等需要较大传输速率的无线通讯需求。
此外,采集到的信息和数据应能够使工作人员直观方便地读出,为此,配备质优价廉的显示设备成为必要。
常用的显示设备有LED点阵和LCD液晶显示,而LCD液晶显示由于具有低功耗、显示功能强大和编程简单而很好地符合了人们节约能源的要求,LCD1602和LCD12864是LCD系列中比较常见的模块化产品,它们含有齐全的字库,亦可根据自己的要求取模显示特殊的符号,这两种产品分别只引出16和20个插针,使用方便。
关键词:无线传输监控NRF24L01 工业控制LCD1602 LCD12864目录一.系统简介 (3)二.STC89C54RD+单片机 (3)三.4*4矩阵输入键盘 (4)四.无线nRF24L01模块 (4)1.模块性能及特点: (5)2. 工作方式: (5)2.1 收发模式 (5)2.2 空闲模式 (6)2.3 关机模式 (6)3.配置RF24L01模块 (7)四.LCD1602 (8)五.LCD12864(带字库) (8)六.系统原理图 (10)七.实物效果图 (11)八.部分程序代码 (12)九.课程设计心得体会 (20)十.参考文献 (20)一.系统简介本设计为两个STC89C54RD+单片机之间通过nRF24L01无线模块实现单工无线通信。
#include <reg52.h>#include <intrins.h>/********************************************************** *****************************//* NRF24L01 地管脚定义,以及在本程序中地应用,VCC接3.3V 电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途.本程序应用于51或者52单片机,是两个模块进行通讯/*成功地简单指示,现象是:模块1地 KEY1 对应模块1地LED1 和模块2地LED3 ,模块1地 KEY2 对应模/*块1地LED2 和模块2地LED4,发过来也对应./********************************************************** *****************************/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/sbit NC =P2^0; //没用,不接也可sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)sbit SCK =P1^7; //数字输入(SPI 时钟)sbit CE =P2^1; //数字输入(RX 或 TX 模式选择)sbit CSN =P2^2; //数字输入(SPI片选信号)sbit IRQ =P2^6; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P3^3;//按键S1sbit KEY2=P3^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************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); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);//数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf);//发送 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; //RX_DR 为 sta 地第六位sbit TX_DS =sta^5; //TX_DS 为 sta 地第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 地第四位/********************************************************** ********************************//*延时函数/********************************************************** ********************************/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/********************************************************** ******************************//*NRF24L01初始化/********************************************************** *****************************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=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, 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写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/********************************************************** ******************************************/uint SPI_RW(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat地最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低..then set SCK low again}return(dat); //返回读出地一字节 return read dat}/********************************************************** ******************************************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01地SPI时序-----------从reg寄存器读一字节/********************************************************** ******************************************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据 ..then read registervalueCSN = 1; //CSN拉高,结束数据传输CSN high, terminate SPI communicationreturn(reg_val); //返回寄存器数据 return register value}/********************************************************** ******************************************//*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/********************************************************** ******************************************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字select registerSPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输CSN high againreturn(status); // 返回状态寄存器 return nRF24L01 status uchar}/********************************************************** ******************************************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据地个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/********************************************************** ******************************************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字Select register to write to and read status uchar for(i=0;i<uchars;i++)pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器return nRF24L01 status uchar}/********************************************************** ***********************************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据地个数/*描述:把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/********************************************************** ***********************************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<uchars; i++)SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/********************************************************** ******************************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/********************************************************** ******************************************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC 校验,上电,接收模式CE = 1; // 拉高CE启动接收设备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,激发数据发送}/************************************主函数*********************************************************** */void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送地数组unsigned char RxBuf[20]={0}; // 接收地数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer dataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收地数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在地问题:反应不够灵敏,当在按键1和按键2之间切换地时候,对方地灯闪烁会有一定地延时,另外本程序没有消除按键地抖动.对部分函数地解释:uint SPI_RW(uint dat)最基本地函数,完成 GPIO模拟 SPI 地功能.将输出字节(MOSI)从 MSB 循环输出,同时将输入字节(MISO)从 LSB 循环移入.上升沿读入,下降沿输出. (从 SCK被初始化为低电平可以判断出)uchar SPI_Read(uchar reg); //从reg寄存器读一字节读取寄存器值地函数:基本思路就是通过 READ_REG命令(也就是 0x00+寄存器地址) ,把寄存器中地值读出来.对于函数来说也就是把 reg 寄存器地值读到reg_val 中去.uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器寄存器访问函数:用来设置 24L01 地寄存器地值.基本思路就是通过 WRITE_REG命令(也就是 0x20+寄存器地址)把要设定地值写到相应地寄存器地址里面去,并读取返回值.对于函数来说也就是把 value值写到 reg 寄存器中.需要注意地是,访问 NRF24L01 之前首先要 enable 芯片(CSN=0;) ,访问完了以后再 disable芯片(CSN=1;).uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址接收缓冲区访问函数:主要用来在接收时读取 FIFO 缓冲区中地值.基本思路就是通过READ_REG命令把数据从接收 FIFO(RD_RX_PLOAD)中读出并存到数组里面去.uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常//用来写入发发射缓冲区访问函数:主要用来把数组里地数放到发射 FIFO缓冲区中.基本思路就是通过WRITE_REG命令把数据存到发射 FIFO(WR_TX_PLOAD)中去.Tx 模式初始化过程1)写 Tx 节点地地址 TX_ADDR2)写 Rx 节点地地址(主要是为了使能 Auto Ack) RX_ADDR_P0 3)使能 AUTO ACK EN_AA4)使能 PIPE 0 EN_RXADDR5)配置自动重发次数 SETUP_RETR6)选择通信频率 RF_CH7)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 8 ) 选择通道0 有效数据宽度 Rx_Pw_P09)配置 24L01 地基本参数以及切换工作模式 CONFIG.Rx 模式初始化过程:初始化步骤 24L01 相关寄存器1)写 Rx 节点地地址 RX_ADDR_P02)使能 AUTO ACK EN_AA3)使能 PIPE 0 EN_RXADDR4)选择通信频率 RF_CH5) 选择通道0 有效数据宽度 Rx_Pw_P06)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 7)配置 24L01 地基本参数以及切换工作模式 CONFIG.。
nrf24l01无线通信模块与51单片机工作原理无线通信技术在现代社会中扮演着重要的角色,其中nrf24l01无线通信模块与51单片机也成为了无线通信的重要组成部分。
本文将探讨nrf24l01无线通信模块与51单片机的工作原理,以及它们之间的配合关系。
一、nrf24l01无线通信模块nrf24l01无线通信模块是一种低功耗的2.4GHz无线收发模块,广泛应用于物联网、无线传感器网络等领域。
其工作原理基于射频通信技术,通过无线信道进行数据的传输。
nrf24l01模块由无线收发器和嵌入式射频微控制器组成,具备高速率、长距离传输和多通道选择等特性。
1. 发射端工作原理nrf24l01发射端主要由收发器、天线和控制电路组成。
当51单片机通过SPI总线与nrf24l01通信时,可将要发送的数据通过控制电路和收发器转换成射频信号,并通过天线发送出去。
发送端的工作原理可简述为以下几个步骤:a. 初始化设置:通过配置寄存器进行初始化设置,包括工作频率、数据传输速率、天线增益等参数。
b. 数据准备与发送:将待发送的数据加载到发送缓冲区中,并通过发送指令启动数据的发送。
c. 发送前导码:在发送数据之前,发射端会先发送一段前导码作为同步信号,以确保接收端正确接收数据。
d. 数据传输与重发机制:发送端将数据以数据包的形式传输,接收端在接收到数据后会进行确认应答,发送端根据应答情况决定是否进行重发。
2. 接收端工作原理nrf24l01接收端与发送端相似,主要由收发器、天线和控制电路组成。
当发送端通过射频信号将数据发送过来时,接收端的工作原理如下:a. 初始化设置:与发送端类似,接收端也需要通过配置寄存器进行初始化设置,以匹配发送端的参数。
b. 接收与解码:接收端在接收到射频信号后,对信号进行解码,并将解码后的数据加载到接收缓冲区。
c. 数据处理与应答:通过与51单片机的交互,将接收到的数据进行处理,并向发送端发送确认应答,确保数据的可靠性。
基于无线传输模块NRF24L01的简易智能家居系统设计王玲;孙冬冬【期刊名称】《电子测试》【年(卷),期】2016(0)11【摘要】本文介绍了一个以STC公司的51系列单片机为控制器利用NRF24L01无线通信模块组建简易无线智能家居系统的设计。
该系统由控制显示模块、监测终端、执行终端组成。
系统可对各监测点的温度、光照强度、湿度等物理量进行自动检测,同时将测量结果实时传输给控制显示节点,控制显示节点可根据设定参量控制终端节点执行相应操作。
试验结果表明:所设计系统达到了预定的各项功能。
该系统具有低功耗、低成本、易于组网和维护、可扩展性好等特点,具有很好的实用价值与市场前景。
%This paper introduces a STC company's 51 series microcontroller as the controller using NRF24L01 wireless communication module to set up a simple wireless smart home system design.The system consists of a control display module,a monitoring terminal and an executive terminal.System of each monitoring point temperature,light illumination intensity,humidity and other physical quantities were automatically detected.At the same time,the measurement results of real-time transmission to control the display node,control and display nodes according to the set parameter control terminal nodes to execute the corresponding operation.The experimental results show that the designed system achieves the predetermined functions.The system has the characteristics of low power consumption,low cost,easy networking andmaintenance,good expansibility and so on.It has good practical value and market prospect.【总页数】2页(P25-25,34)【作者】王玲;孙冬冬【作者单位】山东科技大学,266590;山东科技大学,266590【正文语种】中文【相关文献】1.基于nRF24L01和STM32F407的无线传输系统设计 [J], 罗林锋2.基于nRF24L01芯片的图像无线传输系统设计 [J], 刘翔;周桢3.基于NRF24L01的简易病房呼救系统设计与实现 [J], 江琳4.基于PIC16F726和nRF24L01的短距离无线传输系统设计 [J], 张肖汉;陈以;李明伟5.基于nRF24L01模块无线传输的人体脉搏红外探测系统设计 [J], 罗箫;奚小东;吴晗平因版权原因,仅展示原文概要,查看原文内容请购买。
nrf24l01无线通信模块与51单片机工作原理
nRF24L01是一款低功耗的2.4GHz无线通信模块,适用于微
控制器和嵌入式系统之间的短距离数据传输。
它可以与51单
片机进行配合使用。
nRF24L01模块包括一个射频发射芯片和一个射频接收芯片。
模块通过SPI接口与51单片机连接。
其工作原理如下:
1. 初始化:首先,51单片机通过SPI接口向nRF24L01模块发送配置命令,包括设置通信频率、通信通道、发射功率等参数。
2. 发送数据:当需要发送数据时,51单片机将待发送的数据
通过SPI接口发送给nRF24L01模块的发送芯片。
发送芯片将
数据转换为无线信号,并通过天线发射出去。
3. 接收数据:当有数据被接收时,nRF24L01模块的接收芯片
会把接收到的数据通过SPI接口传递给51单片机。
单片机再
根据需要对接收到的数据进行处理。
4. 确认和重传:发送芯片在发送数据后会等待接收芯片的确认信号。
如果收到确认信号,发送芯片会继续发送下一个数据包。
如果未收到确认信号,发送芯片会进行多次重传,以确保数据的可靠传输。
5. 通信协议:nRF24L01模块支持多种通信协议,如无线串口、SPI、I2C等。
可以根据需要选择合适的通信协议进行数据传输。
通过上述工作原理,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();}}}。
基于51单片机与nRF24L01无线门禁控制系统设计1. 本文概述本文旨在探讨基于51单片机与nRF24L01无线门禁控制系统的设计。
随着科技的快速发展和智能化趋势的加强,门禁控制系统作为保障场所安全的重要手段,其设计与实现变得尤为重要。
传统的门禁系统多采用有线连接方式,布线复杂、成本较高且灵活性不足。
本文提出了一种基于51单片机与nRF24L01无线模块的门禁控制系统设计,旨在实现门禁系统的无线化、智能化和便捷化。
本文将首先介绍51单片机和nRF24L01无线模块的基本原理和特点,为后续的设计工作提供理论基础。
随后,将详细阐述系统的硬件设计,包括无线模块的选型、电路设计以及门禁控制器的实现等。
在此基础上,本文将进一步探讨软件设计的关键问题,包括无线通信协议的制定、门禁控制算法的实现以及用户界面的设计等。
通过本文的研究,旨在设计并实现一个稳定可靠、易于扩展的无线门禁控制系统,为各类场所提供高效便捷的门禁管理解决方案。
同时,本文的研究结果将为相关领域的研究人员提供有益的参考和借鉴,推动无线门禁控制技术的进一步发展。
2. 系统设计原理51单片机,作为一种经典的微控制器,其核心是基于Intel的8051架构。
它具备基本的输入输出控制能力,定时器计数器,中断系统以及一定的内存管理功能。
在本系统中,51单片机扮演着中央处理单元(CPU)的角色,负责接收传感器数据,处理输入信号,并根据预设的逻辑控制输出设备,如无线通信模块和门禁机构。
nRF24L01是一款高性能的无线传输模块,基于Nordic Semiconductor的 NRF24L01 芯片。
它工作在4GHz的ISM频段,支持点对点、点对多点的通信模式。
nRF24L01模块具有自动应答和自动重发功能,确保数据传输的可靠性。
在本系统中,nRF24L01用于无线传输门禁控制信号,包括身份验证数据和控制指令。
系统设计将51单片机和nRF24L01无线模块整合,形成一个高效、可靠的无线门禁控制系统。
nrf24l01无线通信模块与51单片机工作原理-回复nRF24L01无线通信模块与51单片机工作原理引言:随着物联网的快速发展,无线通信技术在各个领域中的应用越来越广泛。
而在无线通信领域中,nRF24L01无线通信模块和51单片机成为了常见的组合。
本文将详细介绍nRF24L01和51单片机的工作原理及其之间的通信过程。
第一部分:nRF24L01无线通信模块的工作原理nRF24L01是一款低功耗的单片机无线通信模块,广泛应用于无线传感器网络、智能家居等领域。
其工作原理可以分为硬件和软件两个方面。
硬件方面,nRF24L01模块由射频前端及基带部分两个主要部分组成。
射频前端部分包括射频收发器和RF增益模块,用于接收和发送射频信号。
基带部分包含SPI接口、调制解调器和数据缓存区,用于控制数据的传输及处理。
软件方面,nRF24L01模块的工作需要通过使用专用的库函数进行驱动。
这些库函数可以在编程环境中调用,以实现nRF24L01模块的相应功能。
软件通过SPI接口与模块进行通信,并通过设置寄存器、发送命令和接收状态等方式控制模块的工作。
第二部分:51单片机的工作原理51单片机,全称为AT89C51,是一种典型的8051架构的单片机。
在无线通信系统中,51单片机通常作为主控芯片,通过与nRF24L01模块进行交互,实现与其他设备的无线通信。
51单片机的工作原理主要包括四个方面:时钟与计时、IO口控制、中断系统和串行通信。
时钟与计时:51单片机内部由一个双字节的定时器/计数器组成,用于提供计时和延时功能。
通过设置计时器的时钟源和分频系数,可以实现不同频率和精度的计时与延时。
IO口控制:51单片机的IO口主要用于与其他设备进行数据交互。
通过设置相应的寄存器,可以控制IO口的输入输出、上拉电阻和工作模式等。
中断系统:51单片机内部集成了中断控制器,可以通过设置中断优先级和中断源等参数,实现对不同事件的响应。
在无线通信系统中,可以通过中断来处理接收数据、发送完成等事件。
温度无线传输南阳理工周渴望本次所做是基于2.4GNRF24L01+芯片的温度的无线传输,甲机作为发射机有DS18B20温度传感器、LCD1602液晶和NRE24L01+2.4G无线传输芯片。
乙机作为接收端有LCD1602液晶和NRE24L01+2.4G无线传输芯片。
甲机和乙机在硬件上是完全分开的。
工作过程:甲机将温度检测出来并显示在液晶上,然后通过NRF24L01将温度数据发送出去,然后乙机通过本机上的NRF24L01芯片将甲机发射的程序接手过来通过单片机处理显示在本机液晶上面。
实物图引脚图程序:注:本次程序基于之前所做“1602LCD液晶显示DS18B20温度”程序。
发射端#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int//************************************************************************* ****************sbit ds18b20=P2^3; //定义DS18B20的数据引脚bit crrent=1; //定义DS18B20初始化返回值,表示初始化是否成功sbit BEE=P3^5;sbit AD=P2^5;sbit DC=P2^7;sbit lcdrs=P2^0; //定义LCD引脚sbit lcdrw=P2^1;sbit lcden=P2^2;sbit LED=P1^0;uint HT=340;uint value=0;uchar code str[]={"Tempe:"};uchar code str1[]={"DS18B20 Error"};uchar code str2[]={"Please Check"};uchar tflag; // 是否正负uchar data disdat[6];uchar data setdat[4];void writelcdcmd(uchar);void writelcddat(uchar);//************************************************************************* ****************#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^0; //发射高电平大于10MS 接收高电平sbit CSN=P1^1; //低电平ISP使能sbit SCK=P1^2; //下降沿sbit MOSI=P1^3; //MCU出sbit MISO=P1^4; //MCU入sbit IRQ=P1^5; //中断uchar bdata sta;sbit RX_DR =sta^6; //接收数据准备就绪sbit TX_DS =sta^5; //已发送数据sbit MAX_RT =sta^4;sbit DQ=P2^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_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); /*接收模块的地址*/SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); /*通道0 接收数据地址*/SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); /*写待发数据指令a0*/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 ,发射功率0dBmSPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); //配置寄存器CE=1;}void checkflag(){ sta=SPI_Read(STA TUS);//读状态寄存器if(MAX_RT){SPI_RW_Reg(FLUSH_TX,0); /*冲洗发送FIFO指令*/}SPI_RW_Reg(WRITE_REG+STA TUS,sta);//清除中断}//以下是DS18B20的操作程序//************************************************************************/ void delay_18B20(unsigned int i)//延时1微秒{while(i--);}set18b20()/*ds1820复位*/{EA=0;ds18b20= 1; //复位delay_18B20(4); //延时ds18b20 = 0; //拉低delay_18B20(100); //精确延时大于480usds18b20 = 1; //拉高delay_18B20(10);crrent=ds18b20;while(!ds18b20);EA=1;return(crrent); //返回值}uchar read18b20() /*读数据*/{ uchar i;uchar dat = 0;EA=0;for(i=0x01; i!=0; i<<=1){ds18b20 = 0;_nop_();_nop_();ds18b20 = 1;_nop_();_nop_();if(!ds18b20)dat &= ~i;elsedat |= i;delay_18B20(8);}EA=1;return dat;}void write18b20(uchar wdata) /*写数据*/{unsigned char i=0;EA=0;for (i=8; i>0; i--){ ds18b20 = 0;_nop_();_nop_();ds18b20=wdata&0x01;delay_18B20(10);ds18b20 = 1;wdata>>=1;}EA=1;}//******************************LCD1602*********************************** *****************************void delayms(uint z) //不精确延时{uchar x;uint y;for(x=z;x>0;x--)for(y=125;y>0;y--);}void LCD_BUSY() //LCD忙检测{ uchar sta;P0=0xff;lcdrs=0;lcdrw=1;do{lcden=1;sta=P0;lcden=0;}while(sta & 0x80);}void writelcdcmd(uchar cmd) //LCD写命令{LCD_BUSY();delayms(1);lcdrs=0;lcdrw=0;lcden=0;P0=cmd;delayms(1);lcden=1;delayms(1);lcden=0;}void writelcddat(uchar dat) //LCD写数据{LCD_BUSY();delayms(1);lcdrs=1;lcdrw=0;lcden=0;P0=dat;delayms(1);lcden=1;delayms(1);lcden=0;}void inilcd() //LCD初始化{ delayms(15);writelcdcmd(0x38);delayms(5);writelcdcmd(0x0c);delayms(5);writelcdcmd(0x06);delayms(5);writelcdcmd(0x01);delayms(5);}void play(unsigned char *p)//显示//{while(*p!='\0'){writelcddat(*p);p++;delayms(1);}}//************************************************************************* *****************void readtemperature(void){ uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位set18b20();write18b20(0xcc);write18b20(0x44);set18b20();write18b20(0xcc);write18b20(0xbe);TL=read18b20(); //先读的是温度值低位TH=read18b20(); //接着读的是温度值高位distance_data[0]=TH ; //测量结果的高8位distance_data[1]=TL; //放入16位的高8位value=TH;value<<=8;value=value|TL;}/***********************************温度显示****************************************************/void disp18b20() //液晶显示温度{uint i,t;if(value<0x0fff) //是否是负值tflag=0;else{value=~value+1;tflag=1;}value=value*(0.625)+0.5; //扩大10倍方便读取小数i=65000;t=220;LED=1;if((value>HT)&&(crrent=0)) //这里设置温度上限值,来控制继电器,需加crrent=0,不然DS18B20在拔掉后会出错{while(t--)while(i--) //这里是继电器导通为3分钟左右,中间不读取温度{set18b20();LED=0;if((value<HT)&&(crrent=0))LED=0;}}/*改变设定温度*/DC=1;AD=1;if(AD==0) //设定温度加{HT++;while(!AD);}if(DC==0) //设定温度减{HT--;while(!DC);}/*************************//*读取上限值温度*/setdat[0]=HT/100+'0'; //十位setdat[1]=HT%100/10+0x30; //个位setdat[2]=HT%10+'0';/*************************//*读取当前温度*/disdat[0]=value/1000+0x30;//百位数disdat[1]=value%1000/100+0x30;//十位数disdat[2]=value%100/10+0x30;//个位数disdat[3]=value%10+0x30;//小数位if(tflag==0)disdat[4]=0x20;elsedisdat[4]=0x2d; //当最高位为0时,最高位不显示if(disdat[0]==0x30){disdat[0]=0x20;if(disdat[1]==0x30)disdat[1]=0x20;}/*显示当前温度*/writelcdcmd(0x86);writelcddat(disdat[4]); //符号位writelcdcmd(0x87);writelcddat(disdat[0]);writelcdcmd(0x88);writelcddat(disdat[1]);writelcdcmd(0x89);writelcddat(disdat[2]);writelcdcmd(0x8a);writelcddat(0x2e); //小数点writelcdcmd(0x8b);writelcddat(disdat[3]);writelcdcmd(0x8d); //单位℃writelcddat(0xdf);writelcdcmd(0x8e);writelcddat('C');/*显示设定温度温度*/writelcdcmd(0xc0);writelcddat('H');writelcdcmd(0xc1);writelcddat('T');writelcdcmd(0xc2);writelcddat(':');writelcdcmd(0xc3);writelcddat(setdat[0]);writelcdcmd(0xc4);writelcddat(setdat[1]);writelcdcmd(0xc5);writelcddat('.');writelcdcmd(0xc6);writelcddat(setdat[2]);}//**********************************主函数************************************************void main(void){uchar xx;init_io();inilcd();while(1){ readtemperature(); //实时更新温度writelcdcmd(0x01); //每次数据变化清屏显示do{readtemperature();checkflag();for(xx=0;xx<2;xx++){tx_buf[xx]= distance_data[xx];//发数据之前必须把要发送的数据装入它}TX_Mode(); //必须启动发送模块delay_ms(5);writelcdcmd(0x80);play(str);disp18b20();}while(!crrent); //检测DS18B20存在,显示温度do{readtemperature();writelcdcmd(0x80);play(str1);writelcdcmd(0x80+0x40);play(str2);BEE=1;}while(crrent);}}接收端:#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit lcdrs=P2^0; //定义LCD引脚sbit lcdrw=P2^1;sbit lcden=P2^2;uint value=0;uchar code str[]={"Tempe:"};uchar code str1[]={"No signal"};uchar code str2[]={"Please Check"};uchar tflag; // 是否正负uchar data disdat[6];uchar data setdat[4];void writelcdcmd(uchar);void writelcddat(uchar);//************************************************************************* *****************uchar tm[2];#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^0; //发射高电平大于10MS 接收高电平sbit CSN=P1^1; //低电平ISP使能sbit SCK=P1^2; //下降沿sbit MOSI=P1^3; //MCU出sbit MISO=P1^4; //MCU入sbit IRQ=P1^5; //中断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 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 ,发射功率0dBmSPI_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+STA TUS,sta);}//************************************************************************* *********************void delayms(uint z) //不精确延时{uchar x;for(x=z;x>0;x--)for(y=125;y>0;y--);}void LCD_BUSY() //LCD忙检测{ uchar sta;P0=0xff;lcdrs=0;lcdrw=1;do{lcden=1;sta=P0;lcden=0;}while(sta & 0x80);}void writelcdcmd(uchar cmd) //LCD写命令{LCD_BUSY();delayms(1);lcdrs=0;lcdrw=0;lcden=0;P0=cmd;delayms(1);lcden=1;delayms(1);lcden=0;}void writelcddat(uchar dat) //LCD写数据{LCD_BUSY();delayms(1);lcdrs=1;lcdrw=0;lcden=0;P0=dat;delayms(1);delayms(1);lcden=0;}void inilcd() //LCD初始化{ delayms(15);writelcdcmd(0x38);delayms(5);writelcdcmd(0x0c);delayms(5);writelcdcmd(0x06);delayms(5);writelcdcmd(0x01);delayms(5);}void play(unsigned char *p)//显示//{while(*p!='\0'){writelcddat(*p);p++;delayms(1);}}void xianshi(void){uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位TH=tm[0] ;TL=tm[1]; //这样得到的是温度小数部分的第一位数字(保留1位小数)value=TH;value<<=8;value=value|TL;if(value<0x0fff) //是否是负值tflag=0;else{value=~value+1;tflag=1;}value=value*(0.625)+0.5; //扩大10倍方便读取小数disdat[0]=value/1000+0x30;//百位数disdat[1]=value%1000/100+0x30;//十位数disdat[2]=value%100/10+0x30;//个位数disdat[3]=value%10+0x30;//小数位if(tflag==0)disdat[4]=0x20;elsedisdat[4]=0x2d; //当最高位为0时,最高位不显示if(disdat[0]==0x30){disdat[0]=0x20;if(disdat[1]==0x30)disdat[1]=0x20;}/*显示当前温度*/writelcdcmd(0x86);writelcddat(disdat[4]); //符号位writelcdcmd(0x87);writelcddat(disdat[0]);writelcdcmd(0x88);writelcddat(disdat[1]);writelcdcmd(0x89);writelcddat(disdat[2]);writelcdcmd(0x8a);writelcddat(0x2e); //小数点writelcdcmd(0x8b);writelcddat(disdat[3]);writelcdcmd(0x8d); //单位℃writelcddat(0xdf);writelcdcmd(0x8e);writelcddat('C');}void main(void){uchar xx;inilcd();init_io();RX_Mode();while(1){ flag=0;checkflag();if(flag!=1){ writelcdcmd(0x01);writelcdcmd(0x01);writelcdcmd(0x80);play(str1);writelcdcmd(0x80+0x40);play(str2);delayms(60000);}else if(flag){writelcdcmd(0x01);for(xx=0;xx<2;xx++){tm[xx]=rx_buf[xx];delay_ms(1);writelcdcmd(0x80);play(str);xianshi();delayms(60000);}}delayms(60000);delayms(60000);delayms(60000);delayms(60000);delayms(60000);delayms(60000);delayms(60000);delayms(60000);}}2014 8。