基于NRF24L01+温度无线传输51单片机
基于51的无线芯片NFR24L01通信主机程序
![基于51的无线芯片NFR24L01通信主机程序](https://img.taocdn.com/s3/m/1736d039580216fc700afdbe.png)
#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无线温度测量系统的设计与实现
![毕业论文——基于NRF24L01无线温度测量系统的设计与实现](https://img.taocdn.com/s3/m/d24fb716ba1aa8114431d9b0.png)
毕业设计(论文)基于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)摘要温度是一个非常重要的参数。
基于nRF24L01的无线信息传输设计
![基于nRF24L01的无线信息传输设计](https://img.taocdn.com/s3/m/868c00afc850ad02df804117.png)
摘要当今,通过信息的采集、传输、处理和控制器作出相应的决策,进而实现对一定对象的监控和控制,是一个无论在民用、工业,还是军事领域,都被人们乐此不疲地研究着的热门技术。
而信息传输的可靠性无疑是控制器作出正确决策的重要前提。
无线传输以其成本廉价、占用空间小、环境适应性好、扩展性好和设备维护上更容易实现等优点正在逐步越来越受到人们的青睐。
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无线模块实现单工无线通信。
无线模块NRF24L01基于C51单片机双向通讯C语言程序(中文详解)
![无线模块NRF24L01基于C51单片机双向通讯C语言程序(中文详解)](https://img.taocdn.com/s3/m/1523ee8d172ded630a1cb64e.png)
#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单片机工作原理](https://img.taocdn.com/s3/m/5ff51f2b0a1c59eef8c75fbfc77da26924c59670.png)
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的简易智能家居系统设计
![基于无线传输模块NRF24L01的简易智能家居系统设计](https://img.taocdn.com/s3/m/ae7c1bd8710abb68a98271fe910ef12d2af9a9f2.png)
基于无线传输模块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无线通信模块与51单片机工作原理](https://img.taocdn.com/s3/m/fef2ea7a0812a21614791711cc7931b765ce7b8b.png)
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单片机进行可靠的通信。
它被广泛应用于无线遥控、传感器网络、智能家居等领域。
nrf24l01无线温度传输—51单片机
![nrf24l01无线温度传输—51单片机](https://img.taocdn.com/s3/m/5c8f1a40e45c3b3567ec8bee.png)
无线温度传输系统学校:安徽工业大学学院:电气信息学院由于最近要毕业设计了,老师让我做无线通信,然后我上网找了很多资料,决定用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无线门禁控制系统设计
![基于51单片机与nRF24L01无线门禁控制系统设计](https://img.taocdn.com/s3/m/bf16ebbc4bfe04a1b0717fd5360cba1aa8118cfb.png)
基于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单片机工作原理 -回复](https://img.taocdn.com/s3/m/236a220a777f5acfa1c7aa00b52acfc789eb9f91.png)
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单片机内部集成了中断控制器,可以通过设置中断优先级和中断源等参数,实现对不同事件的响应。
在无线通信系统中,可以通过中断来处理接收数据、发送完成等事件。
nRF24l01无线模块 发送端程序for 51单片机
![nRF24l01无线模块 发送端程序for 51单片机](https://img.taocdn.com/s3/m/969586d084254b35eefd3498.png)
#define Data P0//数据端口
//=============================================================================================
#define MODE 0//MODE=1时为发送代码 为0则是接受代码
#define uchar unsigned char
#define RX_ADR_WIDTH 5
#define TX_ADR_WIDTH 5 // 5 bytes TX(RX) address width
#define TX_PLOAD_WIDTH 1 // 20 bytes TX payload
/******************************************************************/
void WriteCommand(unsigned char c)
{
DelayMs(5);//操作前短暂延时,保证信号稳定
E=0;
RS=0;
RW=0;
/* 写入字符串函数 */
/******************************************************************/
void ShowString (unsigned char line,char *ptr)
char data TimeNum[]=" ";
/******************************************************************/
【免费下载】nRF24L01无线模块在单片机
![【免费下载】nRF24L01无线模块在单片机](https://img.taocdn.com/s3/m/8e51c1a883d049649b665868.png)
有2类寄存器是用户可以根据自己的需求所确定的,那就是地址的长度以及内容、发送 与接收数据的长度,但无线模块一次最多可以发送32个字节,这两类寄存器一般设置为3~4 个字节。
1#define TX_PLOAD_WIDTH 4 2#define RX_PLOAD_WIDTH 4 3unsignedchar TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10};//本地地址 4unsignedchar RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10};//接收地址
对全部高中资料试卷电气设备,在安装过程中以及安装结束后进行高中资料试卷调整试验;通电检查所有设备高中资料电试力卷保相护互装作置用调与试相技互术关,系电,力根通保据过护生管高产线中工敷资艺设料高技试中术卷资,配料不置试仅技卷可术要以是求解指,决机对吊组电顶在气层进设配行备置继进不电行规保空范护载高与中带资负料荷试下卷高问总中题体资,配料而置试且时卷可,调保需控障要试各在验类最;管大对路限设习度备题内进到来行位确调。保整在机使管组其路高在敷中正设资常过料工程试况中卷下,安与要全过加,度强并工看且作护尽下关可都于能可管地以路缩正高小常中故工资障作料高;试中对卷资于连料继接试电管卷保口破护处坏进理范行高围整中,核资或对料者定试对值卷某,弯些审扁异核度常与固高校定中对盒资图位料纸置试,.卷保编工护写况层复进防杂行腐设自跨备动接与处地装理线置,弯高尤曲中其半资要径料避标试免高卷错等调误,试高要方中求案资技,料术编试交写5、卷底重电保。要气护管设设装线备备置敷4高、调动设中电试作技资气高,术料课中并3中试、件资且包卷管中料拒含试路调试绝线验敷试卷动槽方设技作、案技术,管以术来架及避等系免多统不项启必方动要式方高,案中为;资解对料决整试高套卷中启突语动然文过停电程机气中。课高因件中此中资,管料电壁试力薄卷高、电中接气资口设料不备试严进卷等行保问调护题试装,工置合作调理并试利且技用进术管行,线过要敷关求设运电技行力术高保。中护线资装缆料置敷试做设卷到原技准则术确:指灵在导活分。。线对对盒于于处调差,试动当过保不程护同中装电高置压中高回资中路料资交试料叉卷试时技卷,术调应问试采题技用,术金作是属为指隔调发板试电进人机行员一隔,变开需压处要器理在组;事在同前发一掌生线握内槽图部内 纸故,资障强料时电、,回设需路备要须制进同造行时厂外切家部断出电习具源题高高电中中源资资,料料线试试缆卷卷敷试切设验除完报从毕告而,与采要相用进关高行技中检术资查资料和料试检,卷测并主处且要理了保。解护现装场置设。备高中资料试卷布置情况与有关高中资料试卷电气系统接线等情况,然后根据规范与规程规定,制定设备调试高中资料试卷方案。
单片机基于2.4G无线收发模块NRF24L01的无线通信(基本测试通过)续
![单片机基于2.4G无线收发模块NRF24L01的无线通信(基本测试通过)续](https://img.taocdn.com/s3/m/d96f630c53d380eb6294dd88d0d233d4b14e3f72.png)
单片机基于2.4G无线收发模块NRF24L01的无线通信(基本测试通过)续二、软件部分1>接收方程序:主函数:#include <reg52.h>#include <stdio.h>#include'NRF24L01.h'#include <intrins.h>void main(){ unsigned char i=0;unsigned char data_RX[32]={1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, 2,2,3,3,3,3,3,3,3,3,3,3,3,3};//接收到的32字节存放数组设置初值SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1,8位收发,波特率可变TMOD|= 0x20; //定时器工作方式 2 ,自动重载初值PCON&= 0x7f; //波特率不加倍TH1 = 0xFA; //波特率等于4800、数据位8、停止位1。
效验位无,晶振为11.0592MHZTL1 = 0xFA;TR1 = 1; //开启定时器1 ES = 1; //开串口中断EA = 1; // 开总中断NRF24L01_RX();//设置为接收模式while(!((READ_BYTE(READ_REG+STATUS))&0x40)); //判断是否接收好32字节数据READ_BYTES(RD_RX_PLOAD,data_RX,32); //将32字节数据存放在数组中CE=0;CSN=1;_nop_();CSN=0;SPI_WRITE(FLUSH_RX); //清空接收FIFO,否则接收数据不可预知SCK=0;CSN=1;jieshouv=0; //接收成功标志位WRITE_BYTE(WRITE_REG+STATUS,0xFF); //屏蔽中断位for(i=0;i<32;i++){ if(data_RX[i]>=10){SBUF=data_RX[i]/10+48; //将十位转化为ASCII码发送while(!TI);TI=0;SBUF = data_RX[i]%10+48; //将个位转化为ASCII码发送while(!TI); // 等特数据传送(TI发送中断标志)TI = 0; // 清除数据传送标志}else{SBUF = data_RX[i]%10+48; //将无符号数转为ASCII码发送while(!TI); // 等特数据传送(TI发送中断标志)TI = 0; // 清除数据传送标志}}while(1);}*************************************************************** *************************************************详情请咨询: http://shop108408772.taoba /*************************************************************** ***********************************************子函数:#include <reg52.h>#include 'NRF24L01.h'#include <intrins.h>unsigned char ADD_TX[]={0,1,2,3,4}; //通道地址unsigned char data_TX[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; //发送方32字节数据void SPI_WRITE(unsigned char canshu) //写入一个字节{unsigned char i;for(i=0;i<8;i++){SCK=0;MOSI=(canshu&0x80)>>7; //先发高位SCK=1;canshu=canshu<<1;}}unsigned char SPI_READ() //读一个字节{unsigned char canshu=0,i;for(i=0;i<8;i++){canshu=canshu<<1; //先接收的为高位SCK=0;_nop_();SCK=1;canshu=canshu|MISO;}return canshu;}void WRITE_BYTE(unsigned char address,unsigned char value)//写入完整指令,单字节{CSN=1;_nop_();CSN=0;SPI_WRITE(address); //写入寄存器绝对地址_nop_();SPI_WRITE(value); //写入参数SCK=0; //恢复初值CSN=1; //恢复初值}unsigned char READ_BYTE(unsigned char address) //读入完整指令,单字节{unsigned char canshu;CSN=1;_nop_();CSN=0;SPI_WRITE(address); //写入寄存器绝对地址_nop_();canshu=SPI_READ(); //读出数据SCK=0;CSN=1;return canshu;}*************************************************************** *************************************************详情请咨询: http://shop108408772.taoba /*************************************************************** ***********************************************void WRITE_BYTES(unsigned char address,unsigned char *value,unsigned char width)//写入指定字节数据,多字节{unsigned char i;CSN=1;_nop_();CSN=0;SPI_WRITE(address); //写入寄存器绝对地址_nop_();for(i=0;i<width;i++){SPI_WRITE(*value); //将数据依次写入value=value+1;}SCK=0;CSN=1;}void READ_BYTES(unsigned char address,unsigned char *value,unsigned char width)//读入指定字节数据,多字节{unsigned char i;CSN=1;_nop_();CSN=0;SPI_WRITE(address); //写入寄存器绝对地址_nop_();for(i=0;i<width;i++){*value=SPI_READ(); //将数据依次读入value=value+1;}SCK=0;CSN=1;}/************************************************void NRF24L01_TX()//NRF24L01设为发送模式{ //默认NRF24L01为掉电模式unsigned char i;CE=0;WRITE_BYTE(WRITE_REG+SETUP_AW,0x03);//设置地址宽度为5字节WRITE_BYTE(WRITE_REG+RX_PW_P0,0x20);//设置接收通道0数据宽度为32字节WRITE_BYTES(WR_TX_PLOAD,data_TX,32);//写入发送数据WRITE_BYTES(WRITE_REG+TX_ADDR,ADD_TX,5);//设置发送地址WRITE_BYTES(WRITE_REG+RX_ADDR_P0,ADD_TX,5);//设置通道0地址WRITE_BYTE(WRITE_REG+EN_RXADDR,0x01);//使能接收通道0WRITE_BYTE(WRITE_REG+EN_AA,0x01);//使能通道0自动应答WRITE_BYTE(WRITE_REG+SETUP_RETR,0x1a);// 自动重发次数10次WRITE_BYTE(WRITE_REG+RF_CH,0x40); //设置载波频率WRITE_BYTE(WRITE_REG+RF_SETUP,0x0f); //射频参数,如数据传输率,发射功率WRITE_BYTE(WRITE_REG+CONFIG,0x0A);//设置发射,上电,CRC校验8位CE=1;for(i=0;i<10;i++);//延时30us}********************************************************/void NRF24L01_RX()//NRF24L01设为接收模式{unsigned char i; //默认NRF24L01为掉电模式CE=0;WRITE_BYTE(WRITE_REG+SETUP_AW,0x03);//设置地址宽度为5字节WRITE_BYTE(WRITE_REG+RX_PW_P0,0x20);//设置接收通道0数据宽度为32字节WRITE_BYTES(WRITE_REG+RX_ADDR_P0,ADD_TX,5);//设置通道0地址WRITE_BYTE(WRITE_REG+EN_RXADDR,0x01);//使能接收通道0WRITE_BYTE(WRITE_REG+EN_AA,0x01);//使能通道0自动应答WRITE_BYTE(WRITE_REG+RF_CH,0x40); //设置载波频率WRITE_BYTE(WRITE_REG+RF_SETUP,0x0f); //射频参数,如数据传输率,发射功率WRITE_BYTE(WRITE_REG+CONFIG,0x0B);//设置接收,上电,CRC校验8位CE=1;for(i=0;i<20;i++);//延时60us}*************************************************************** *************************************************详情请咨询: http://shop108408772.taoba /*************************************************************** ***********************************************1>发送方程序:主程序://#include <reg52.h>#include 'stc12.h'#include'NRF24L01.h'#include <intrins.h>void main(){CLK_DIV=0x03;NRF24L01_TX(); //发送模式开启while(!((READ_BYTE(READ_REG+STATUS))&0x30));//等待发送完成CE=0;CSN=1;_nop_();CSN=0;SPI_WRITE(FLUSH_RX); //清空接收FIFO,否则数据不可预料SCK=0;CSN=1;if((READ_BYTE(READ_REG+STATUS))&0x20)fasong=0; // 发送成功标志位WRITE_BYTE(WRITE_REG+STATUS,0xFF); //屏蔽中断标志位while(1);}子程序:和接收子程序大部分一致,改动部分:void NRF24L01_TX()//NRF24L01设为发送模式{ //默认NRF24L01为掉电模式unsigned char i;CE=0;WRITE_BYTE(WRITE_REG+SETUP_AW,0x03);//设置地址宽度为5字节WRITE_BYTE(WRITE_REG+RX_PW_P0,0x20);//设置接收通道0数据宽度为32字节WRITE_BYTES(WR_TX_PLOAD,data_TX,32);//写入发送数据WRITE_BYTES(WRITE_REG+TX_ADDR,ADD_TX,5);//设置发送地址WRITE_BYTES(WRITE_REG+RX_ADDR_P0,ADD_TX,5);//设置通道0地址WRITE_BYTE(WRITE_REG+EN_RXADDR,0x01);//使能接收通道0WRITE_BYTE(WRITE_REG+EN_AA,0x01);//使能通道0自动应答WRITE_BYTE(WRITE_REG+SETUP_RETR,0x1a);// 自动重发次数10次WRITE_BYTE(WRITE_REG+RF_CH,0x40); //设置载波频率WRITE_BYTE(WRITE_REG+RF_SETUP,0x0f); //射频参数,如数据传输率,发射功率WRITE_BYTE(WRITE_REG+CONFIG,0x0A);//设置发射,上电,CRC校验8位CE=1;for(i=0;i<30;i++);//延时90us}将接收子程序中接收模式程序屏蔽即可。
nrf24l01模块与单片机通信方式
![nrf24l01模块与单片机通信方式](https://img.taocdn.com/s3/m/99e3cd06bf1e650e52ea551810a6f524cdbfcb79.png)
nrf24l01模块与单片机通信方式一、nRF24L01模块与单片机的通信方式1.基于SPI通信协议的数据交换nRF24L01模块与单片机基于SPI通信协议进行数据交换。
SPI是一种同步串行通信协议,它通过四个信号线进行通信:MOSI、MISO、SCK和CSN。
在这四个信号线中,MOSI用于发送数据,MISO用于接收数据,SCK用于同步时钟信号,而CSN用于片选信号。
这种通信方式具有传输速度快、数据稳定性高、抗干扰能力强等优点。
2.控制引脚与SPI通信引脚的配置nRF24L01模块的控制引脚包括CE、CSN、IRQ,这些引脚可用于控制模块的开启、关闭以及接收中断等功能。
SPI通信引脚包括MOSI、MISO、SCK,这些引脚可用于实现与单片机之间的数据传输。
值得注意的是,这些引脚可以直接接普通的IO口,而不必特意选择SPI外设对应的引脚。
二、nRF24L01模块的应用场景1. 一对多通信当有两个以上的nRF无线模块且代码中未设置SPI片选信号时,可以实现一对多通信(即一个发多个收到该信息)。
这种通信方式在需要多个接收方的情况下非常实用,可以有效提高通信效率,降低系统成本。
2.多种通信模式的选择nRF24L01模块支持多种通信模式,如广播模式、多路复用模式等。
用户可以根据实际需求选择合适的通信模式,以满足不同场景下的应用要求。
3.远程控制与监测nRF24L01模块可应用于远程控制与监测领域,如智能家居、工业自动化、智能交通等。
通过无线通信,可以实现远程控制设备的开关、调节参数以及实时监测设备状态等功能。
4.数据传输与存储nRF24L01模块还可应用于数据传输与存储领域,如物联网、传感器网络等。
在这些场景下,nRF24L01模块可以实现传感器数据的实时采集、传输和存储,为用户提供便捷的数据处理方案。
nRF24L01模块与单片机的通信方式在实际应用中具有广泛的应用价值,可以为各类工程项目提供可靠的无线通信解决方案。
基于nRF24L01的无线温度采集系统设计(1)概要
![基于nRF24L01的无线温度采集系统设计(1)概要](https://img.taocdn.com/s3/m/25aa88a61a37f111f1855be0.png)
1引言温度采集系统所采集的温度通常通过RS485、CAN 总线通信方式传输至上位机,但这种方式维护较困难,不利于工业现场生产;而无线通信GPRS 技术传输距离长,通信可靠稳定,但设计复杂、成本昂贵。
这里采用工业级内置硬件链路层协议的低成本单芯片nRF24L01型无线收发器件实现系统间的无线通信,完成无线信号的接收、显示及报警功能。
2nRF24L01简介nRF24L01是一款工业级内置硬件链路层协议的低成本无线收发器。
该器件工作于2.4GHz 全球开放ISM 频段,内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合增强型ShockBurst 技术,其输出功率和通信频道可通过程序配置。
拥有ShockBurst 和Enhanced ShockBurst 两种数据传输模式。
可直接与单片机I/O 连接,外接元件数目少。
nRF24L01功耗低,以-6dBm 的功率发射时,工作电流仅9mA ;接收时,工作电流仅12.3mA ,多种低功率工作模式[1](掉电和空闲模式更利于节能设计。
3系统硬件设计系统硬件设计主要由采集发送和接收显示两部分组成[2]。
图1为采集发送电路原理图,该电路主要由温度传感器DS18B20、单片机STC12LE5408和nRF24L01组成[3]。
STC12LE5408是增强型8051单片机,速度快,集成度高,电压范围宽(2.2~3.8V ,和MCS -51系列单片机指令系统完全兼容。
其内部还有8KB Flash 程序存储器,512字节RAM 、2KB EEPROM 、4路PWM 以及硬件看门狗(WDT 等资源,性价比高[4]。
DS18B20是DALLAS 公司生产的单总线数字1-Wire温度传感器[5],可把温度信号直接转换成串行数字信号供单片机处理,采用1-Wire 接口,DS18B20的数据端DQ 可通过4.7k Ω的上拉电阻接STC12LE5408。
nRF24L01的CE ,CSN ,SCK ,MOSI ,MISO ,IRQ 引脚则可接STC12LE5408的任意端口,但需在编程时注意,这里接至P1端口。
NRF24L01无线模块收发程序(实测成功多图)
![NRF24L01无线模块收发程序(实测成功多图)](https://img.taocdn.com/s3/m/312530c685254b35eefdc8d376eeaeaad1f31613.png)
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+温度无线传输51单片机
![基于NRF24L01+温度无线传输51单片机](https://img.taocdn.com/s3/m/e9a2a70f16fc700abb68fca3.png)
温度无线传输南阳理工周渴望本次所做是基于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。
基于51单片机与nRF24L01无线测温通信系统设计
![基于51单片机与nRF24L01无线测温通信系统设计](https://img.taocdn.com/s3/m/f8eeee19c850ad02de8041a6.png)
基于51单片机与nRF24L01无线测温通信系统设计作者:康乐为徐丹来源:《卷宗》2015年第10期摘要:文章将51单片机和nRF24L01技术有机结合起来,组成无线远程测温通信系统。
系统由51单片机,DS18D20温度采集模块,LCD温度数据显示模块,nRF24L01无线数据收发模块组成。
具有实现无线数据传输可靠稳定,低功耗,编程简单等特点。
实践证明该系统能适应于多种环境温度的检测。
关键词:nRF24L01;温度检测;无线通信;单片机目前,无线通信领域越来越广,如:wifi,蓝牙,安全防火系统,水产养殖系统,智能家居系统等等。
凡是布线复杂或者不能布线的场合都希望通过无线方案解决。
为此需要设计相应的接口系统,完成系统数据交互,实现系统控制功能等。
本系统采用了DS18D20温度采集模块及Nordic公司新推出的工作于2.4GHz频段的nRF24L01射频芯片,并由超低功耗单片机控制实现短距离无线数据通信,打破了传统操作中距离受限的问题,使测温操作更易实现。
系统框图如图1:nRF24L01是一款工作在2.4~2.5GHz世界通用ISM频段的单片无线收发器芯片,其工作速率为0~2Mb/s,最大发射功率为0dBm,其外围元件极少,内置硬件CRC(循环冗余校验)和点对多点通信地址控制,集成了频率合成器,晶体振荡器和调制解调器.它的主要特点如下:1)低工作电压:1.9~3.6V低电压工作;2)高速率:2Mbps,由于空中传输时间很短,极大地降低了无线传输中的碰撞现象;3)多频点:125频点,满足多点通信和跳频通信需要;4)超小型:体积小巧,5mm 5mm;5)低功耗:当工作在发射模式时,发射功率为-6dBm,电流消耗为9mA,接收模式为12.3mA,掉电模式和待机模式下电流消耗更低。
6)低应用成本:nRF24L01的SPI接口可以利用单片机的硬件SPI口连接或用单片机I/O 口进行模拟,内部有FIFO可以与各种高低速微处理器接口,便于使用低成本单片机.nRF24L01芯片最突出的特点是有2种通信模式:DirectMode(直接模式)和ShockBurstMode(突发模式).直接模式的使用与其他传统射频收发器的工作一样,需要通过软件在发送端添加校验码和地址码,在接收端判断是否为本机地址并检查数据是否传输正确.ShockBurstMode使用芯片内部的先入先出堆栈区,数据可从低速微控制器送入,高速(2Mb/s)发射出去,地址和校验码硬件自动添加和去除,这种模式的优点是:可使用低速微控制器控制芯片工作;‚减小功耗;ƒ射频信号高速发射,抗干扰性强;减小整个系统的平均电流.因此,使用nRF24L01芯片特有的ShockBurstMode使得系统整体的性能和效率提高。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
温度无线传输南阳理工周渴望本次所做是基于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。