基于51单片机和NRF24L01的无线温度监控.doc
基于51单片机和NRF24L01的无线温度监控一丶实现功能:以51单片机为核心实现智能化远程无线温度监控。利用18B20温度传感器获取温度信号,将需要测量的温度信号自动转化为数字信号,通过无线模块NRF24L01一对一传送将数据传送到接收机,最终单片机将信号转换成LCD可以识别的信息显示输出。二丶所需原件:51单片机*2DS18B20*1 (温度测量范围为-55+125C)12M晶振*222uf电容*25V降压至3.3V降压模块*2NRF24101无线模块*21602液晶显示屏*1按键*3蜂鸣器*1发光二极管*1排阻10K*9脚*2四丶NRF12401JI介绍:1、GFSK调制,硬件集成OSI链路层;2、具有自动应答和自动再发射功能;3、片内自动生成报头和CRC校验码;4、数据传输率为l Mb/s或2Mb/s;5、SPI速率为0 Mb/s10 Mb/s;6、125个频道与其他nRF24系列射频器件相兼容;7、 QFN20引脚4 mm×4 mm封装;8、 供电电压为1.9 V3.6 V;封装引脚介绍:CE:使能发射或接收;CSN,SCK,MOSI,MISO:SPI引脚端,微处理器可通过此引脚配置nRF24L01:IRQ:中断标志位;VDD:电源输入端;VSS:电源地;XC2,XC1:晶体振荡器引脚; VDD_PA:为功率放大器供电,输出为1.8 V;ANT1,ANT2:天线接口;IREF:参考电流输入;工作模式:工作原理:发射数据时,首先将nRF24L01配置为发射模式:接着把接收节点地址TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10s,延迟130s后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号(自动应答接收地址应该与接收节点地址TX_ADDR一致)。如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从TX FIFO中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC)达到上限,MAX_RT置高,TX FIFO中数据保留以便在次重发;MAX_RT或TX_DS置高时,使IRQ变低,产生中断,通知MCU。最后发射成功时,若CE为低则nRF24L01进入空闲模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入空闲模式2。接收数据时,首先将nRF24L01配置为接收模式,接着延迟130s进入接收状态等待数据的到来。当接收方检测到有效的地址和CRC时,就将数据包存储在RX FIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。若此时自动应答开启,接收方则同时进入发射状态回传应答信号。最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。在写寄存器之前一定要进入待机模式或掉电模式。SPI配置:SPI 指令设置用于SPI 接口的常用命令见下表。当CSN 为低时,SPI 接口开始等待一条指令,任何一条新指令均由CSN 的由高到低的转换开始寄存器:读操作写操作五丶温度监测:温度检测模块软件设计DS18B20的测温原理遵循严格的单总线协议,以确保通信数据的准确性,单片机通过时序来写入和读出DS18B20中的数据,包括初始化、读l、读0,写1、写0等操作。传感器复位后,接收应答信号,跳过读ROM中序列号后,启动温度转换,等待温度转换完毕后,保存数据。如此反复,完成所有操作。六丶无线流程:发射:首先进行初始化操作,初始化包括设置单片机IO和SPI相关寄存器两部分其可以和nRF24L01通信。通过SPI总线配置射频芯片使其进入正确的工作模式。发射数据时,首先将nRF24L01配置为发射模式。接着把发送端待发射数据的目标地址TX ADDR和数据TXPLD写入nRF24L01缓冲区,延时后发射数据,其流程图如图4.2所示接收:接 收 数 据 时 ,首先将nRF24L01配置为接收模式。接着延迟进入接收状态等待数据的到来。当接收方检测到有效地址和CRC时,就将数据包储存在接收堆栈中,同时状态寄存器中的中断标志位RXDR置高,产生中断使IRQ引脚变为低电平,以便通知MCU去取数据,其流程图如图4.3所示。七丶软件总体部分:发送部分:发送部分的一个循环的总体思路是这样的先初始化DS18B20,从DS18B20读出温度(DS18B20采用默认的12位精度),将得到的温度值的反码转化成十制,取温度数组的高两位(即整数部分)写入发送数据数组,然后初始化nRF24L01,将温度发送,其流程图如图4.5所示接收部分:接收部分的总体思路是这样的,首先还是初始化nRF24L01,然后进入大循环判断状态寄存器是否有接收中断。如果有就从FIFO_buffer读入二进制数据,然后将数据转换成十进制在数码管上显示出来,其流程图如图4.6所示。八:电路图:发射机: 接收机:九丶程序清单:接收机:#include <reg51.h> #include<intrins.h> #define uchar unsigned char#define uint unsigned int #define READ_REG 0x00 / Define read command to register #define WRITE_REG 0x20 / Define write command to register #define RD_RX_PLOAD 0x61 / Define RX payload register address #define WR_TX_PLOAD 0xA0 / Define TX payload register address #define FLUSH_TX 0xE1 / Define flush TX register command #define FLUSH_RX 0xE2 / Define flush RX register command #define REUSE_TX_PL 0xE3 / Define reuse TX payload register command #define NOP 0xFF / Define No Operation, might be used to read status register #define CONFIG 0x00 / 'Config' register address #define EN_AA 0x01 / 'Enable Auto Acknowledgment' register address #define EN_RXADDR 0x02 / 'Enabled RX addresses' register address #define SETUP_AW 0x03 / 'Setup address width' register address #define SETUP_RETR 0x04 / 'Setup Auto. Retrans' register address #define RF_CH 0x05 / 'RF channel' register address #define RF_SETUP 0x06 / 'RF setup' register address #define STATUS 0x07 / 'Status' register address #define OBSERVE_TX 0x08 / 'Observe TX' register address #define CD 0x09 / 'Carrier Detect' register address #define RX_ADDR_P0 0x0A / 'RX address pipe0' register address #define RX_ADDR_P1 0x0B / 'RX address pipe1' register address #define RX_ADDR_P2 0x0C / 'RX address pipe2' register address #define RX_ADDR_P3 0x0D / 'RX address pipe3' register address #define RX_ADDR_P4 0x0E / 'RX address pipe4' register address #define RX_ADDR_P5 0x0F / 'RX address pipe5' register address #define TX_ADDR 0x10 / 'TX address' register address #define RX_PW_P0 0x11 / 'RX payload width, pipe0' register address #define RX_PW_P1 0x12 / 'RX payload width, pipe1' register address #define RX_PW_P2 0x13 / 'RX payload width, pipe2' register address #define RX_PW_P3 0x14/ 'RX payload width, pipe3' register address #define RX_PW_P4 0x15 / 'RX payload width, pipe4' register address #define RX_PW_P5 0x16 / 'RX payload width, pipe5' register address #define FIFO_STATUS 0x17 / 'FIFO Status Register' register address#define TX_ADR_WIDTH 5 #define RX_ADR_WIDTH 5 #define TX_PLOAD_WIDTH 4#define TX_PLOAD_WIDTH 4 float f_temp; uint temp; uchar TX_ADDRESS5=0x34,0x43,0x19,0x91,0x09;uchar bdata sta; sbit CE=P27; sbit CSN=P22; sbit MOSI=P23; sbit MISO=P25; sbit SCK=P26; sbit IRQ=P24; sbit ds=P37; sbit led0=P10; sbit RX_DR= sta6; sbit TX_DS= sta5; sbit MAX_RT= sta4; void init_io(void) CE = 0; CSN = 1; SCK = 0; IRQ = 1; uchar SPI_RW(uchar byte) uchar i; for(i=0;i<8;i+) 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_pload(uchar reg,uchar *pBuf,uchar bytes) uchar status,i; CSN=0; status=SPI_RW(reg); for(i=0;i<bytes;i+) pBufi=SPI_RW(0); CSN=1; return(status); uchar SPI_write_pload(uchar reg,uchar *pBuf,uchar bytes) uchar status,i; CSN=0; status=SPI_RW(reg); for(i=0;i<bytes;i+) SPI_RW(pBufi); CSN=1; return(status); void TX_mode(uchar *tx_buf) CE=0; SPI_write_pload(WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); SPI_write_pload(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH); SPI_write_pload(WR_TX_PLOAD,tx_buf,TX_PLOAD_WIDTH); SPI_RW_reg(WRITE_REG+EN_AA,0X01); SPI_RW_reg(WRITE_REG+EN_RXADDR,0X01);SPI_RW_reg(WRITE_REG+SETUP_RETR,0X1F); SPI_RW_reg(WRITE_REG+RF_CH,40); SPI_RW_reg(WRITE_REG+RF_SETUP,0X0F); SPI_RW_reg(WRITE_REG+CONFIG,0X0e); CE=1; /CE置高,使能发送 uchar Check_ACK() /while(IRQ/ CE=0; sta=SPI_read(STATUS); if(TX_DS|MAX_RT) SPI_RW_reg(WRITE_REG + STATUS, 0xff); CSN=0; SPI_RW(FLUSH_TX); CSN=1; return (1); else return (0); / CE=1; IRQ = 1; /if(TX_DS) /return(0x00); / else /return(0xff); /* uchar CheckACK() sta=NRFReadReg(READ_REG+STATUS); if(TX_DS|MAX_RT) NRFWriteReg(WRITE_REG+STATUS,0xff); CSN=0; NRFSPI(FLUSH_TX);CSN=1;return(0); else return(1); */void delayus(uint z,uint x) uint i,j; for(i=z;i>0;i-) for(j=x;j>0;j-); void dreset(void) uint i; / ds=1; / _nop_();ds=0; delayus(7,15); ds=1; i=4; while(i>0) i-; delayus(1,100); bit tempreadbit(void) uint i; bit dat; /ds=1;i+; ds=0; _nop_(); ds=1; i+;i+; dat=ds; i=8; while(i>0)i-; return(dat); uchar tempread(void) uchar i,j,dat; dat=0; for(i=0;i<8;i+) j=tempreadbit(); dat=(j<<7)|(dat>>1); return(dat); void tempwritebyte(uchar dat) uint i; uchar j; bit testb; for(j=0;j<8;j+) testb=dat&0x01; dat=dat>>1; if(testb) ds=0; i+;i+; ds=1; i=8; while(i>0)i-; else ds=0; / i=8; / while(i>0)i-; delayus(1,5); ds=1; i+;i+; void tempchange(void) dreset(); delayus(1,113); tempwritebyte(0xcc); tempwritebyte(0x44); uint get_temp() uchar a,b;dreset(); delayus(1,113); tempwritebyte(0xcc); tempwritebyte(0xbe); a=tempread(); b=tempread(); temp=b; temp<<=8; temp=temp|a; f_temp=temp*0.0625; temp=f_temp*10+0.5; /f_temp=f_temp+0.05; return temp; void main() uchar tx_buf4=0; init_io(); while(1) tempchange(); delayus(1,113); get_temp(); tx_buf0=(uchar)(temp/100); tx_buf1=(uchar)(temp-500)%100)/10); tx_buf2='.' tx_buf3=(uchar)(temp%100)%10); TX_mode(tx_buf); 接收机:#include<reg52.h> /#include<intrins.h> #define uchar unsigned char #define uint unsigned int #define READ_REG 0x00 / Define read command to register #define WRITE_REG 0x20 / Define write command to register #define RD_RX_PLOAD 0x61 / Define RX payload register address #define WR_TX_PLOAD 0xA0 / Define TX payload register address #define FLUSH_TX 0xE1 / Define flush TX register command #define FLUSH_RX 0xE2 / Define flush RX register command #define REUSE_TX_PL 0xE3 / Define reuse TX payload register command #define NOP 0xFF / Define No Operation, might be used to read status register / SPI(nRF24L01) registers(addresses) #define CONFIG 0x00 / 'Config' register address #define EN_AA 0x01 / 'Enable Auto Acknowledgment' register address #define EN_RXADDR 0x02 / 'Enabled RX addresses' register address #define SETUP_AW 0x03 / 'Setup address width' register address #define SETUP_RETR 0x04 / 'Setup Auto. Retrans' register address #define RF_CH 0x05 / 'RF channel' register address #define RF_SETUP 0x06 / 'RF setup' register address #define STATUS 0x07 / 'Status' register address #define OBSERVE_TX 0x08 / 'Observe TX' register address #define CD 0x09 / 'Carrier Detect' register address #define RX_ADDR_P0 0x0A / 'RX address pipe0' register address #define RX_ADDR_P1 0x0B / 'RX address pipe1' register address #define RX_ADDR_P2 0x0C / 'RX address pipe2' register address #define RX_ADDR_P3 0x0D / 'RX address pipe3' register address #define RX_ADDR_P4 0x0E / 'RX address pipe4' register address #define RX_ADDR_P5 0x0F / 'RX address pipe5' register address #define TX_ADDR 0x10 / 'TX address' register address #define RX_PW_P0 0x11 / 'RX payload width, pipe0' register address #define RX_PW_P1 0x12 / 'RX payload width, pipe1' register address #define RX_PW_P2 0x13 / 'RX payload width, pipe2' register address #define RX_PW_P3 0x14 / 'RX payload width, pipe3' register address #define RX_PW_P4 0x15 / 'RX payload width, pipe4' register address #define RX_PW_P5 0x16 / 'RX payload width, pipe5' register address #define FIFO_STATUS 0x17 / 'FIFO Status Register' register address#define TX_ADR_WIDTH 5 #define RX_ADR_WIDTH 5 #define TX_PLOAD_WIDTH 4 #define RX_PLOAD_WIDTH 4 uchar idata rxbuf12=0; /uchar idata aa20=0; uchar RX_ADDRES5=0x34,0x43,0x19,0x91,0x09; uchar code table="0123456789" uchar bdata sta; sbit RX_DR= sta6; sbit TX_DS= sta5; sbit MAX_RT= sta4;sbit lcd_rs=P10; sbit lcd_rw=P11; sbit lcd_en=P12;sbit CE =P27; sbit CSN =P22; sbit MOSI=P23; sbit MISO=P25; sbit SCK =P26; sbit IRQ =P24;sbit K1=P34; sbit K2=P36; sbit K3=P35; sbit BJ=P13; sbit BEEF=P14;uchar MAX=30; uchar MIN=20;uchar a; bit flag=0; uchar slnum=0; void delayms(uint x) uint i,j; for(i=x;i>0;i-) for(j=113;j>0;j-); void init_io(void) CE = 0; CSN = 1; SCK = 0; IRQ = 1; uchar SPI_RW(uchar byte) uchar i; for(i=0;i<8;i+) 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_pload(uchar reg,uchar *pBuf,uchar bytes) uchar status,i; CSN=0; status=SPI_RW(reg); for(i=0;i<bytes;i+) pBufi=SPI_RW(0); CSN=1; return(status); uchar SPI_write_pload(uchar reg,uchar *pBuf,uchar bytes) uchar status,i; CSN=0; status=SPI_RW(reg); for(i=0;i<bytes;i+) SPI_RW(pBufi); CSN=1; return(status); void RX_mode() CE=0; SPI_write_pload(WRITE_REG+RX_ADDR_P0,RX_ADDRES,TX_ADR_WIDTH); SPI_RW_reg(WRITE_REG+RX_PW_P0,TX_PLOAD_WIDTH); SPI_RW_reg(WRITE_REG+EN_AA,0X01); SPI_RW_reg(WRITE_REG+EN_RXADDR,0X01); SPI_RW_reg(WRITE_REG+SETUP_RETR,0X1F); SPI_RW_reg(WRITE_REG+RF_CH,40); SPI_RW_reg(WRITE_REG+RF_SETUP,0X0F); SPI_RW_reg(WRITE_REG+CONFIG,0X0F); CE=1; uchar RxPacket(uchar *rx_buf) uchar flag=0; sta=SPI_read(STATUS); if(RX_DR) CE=0; SPI_read_pload(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH); flag=1; SPI_RW_reg(WRITE_REG+STATUS,0xff); CSN=0; SPI_RW(FLUSH_RX); CSN=1; CE=1; return(flag); void write_com(uchar com) lcd_rs=0; lcd_rw=0; P0=com; lcd_en=1; delayms(1); lcd_en=0; void write_data(uchar date) lcd_rs=1; lcd_rw=0; P0=date ; lcd_en=1; delayms(1); lcd_en=0; void lcd_init() lcd_en=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); void write_str(uchar x,uchar y,uchar *s) switch(y) case 0: write_com(0x08+x); break; case 1: write_com(0x08+0x40+x); break; while(*s) write_data(*s); s+; void write_maxmin(uchar add,uchar date) uchar shi,ge; shi=date/10; ge=date%10;write_com(0x80+add); write_data(0x30+shi); write_data(0x30+ge); void keyscan() uchar slnum; if(K1=0) delayms(5); if(K1=0) while(!K1); MAX+; if(MAX=99) MAX=0 ; write_maxmin(4,MAX); write_com(0x80+4);delayms(100); if(K3=0) while(!K3); MIN-; if(MIN=0) MIN=90; write_maxmin(14,MIN); write_com(0x80+14); delayms(100); void main() uchar rx_buf4=0,0,temp; lcd_init(); init_io(); write_com(0x80+0);write_data('M'); write_com(0x80+1);write_data('A'); write_com(0x80+2);write_data('X'); write_com(0x80+3);write_data(':');write_com(0x80+4);write_data('3');write_com(0x80+5);write_data('0');write_com(0x80+10);write_data('M'); write_com(0x80+11);write_data('I'); write_com(0x80+12);write_data('N'); write_com(0x80+13);write_data(':');write_com(0x80+14);write_data('2');write_com(0x80+15);write_data('0'); write_com(0xc0+0);write_data('N'); write_com(0xc0+1);write_data('O'); write_com(0xc0+2);write_data('W'); write_com(0xc0+3);write_data(':');write_com(0xc0+10);write_data('');write_com(0xc0+11);write_data('C'); while(1)