基于51单片机和NRF24L01的无线温度监控.docx
《基于51单片机和NRF24L01的无线温度监控.docx》由会员分享,可在线阅读,更多相关《基于51单片机和NRF24L01的无线温度监控.docx(32页珍藏版)》请在冰豆网上搜索。
基于51单片机和NRF24L01的无线温度监控
基于51单片机和NRF24L01的无线温度监控
一丶实现功能:
以51单片机为核心实现智能化远程无线温度监控。
利用18B20温度传感器获取温度信号,将需要测量的温度信号自动转化为数字信号,通过无线模块NRF24L01一对一传送将数据传送到接收机,最终单片机将信号转换成LCD可以识别的信息显示输出。
二丶所需原件:
51单片机*2
DS18B20*1(温度测量范围为-55~+125^C)
12M晶振*2
22uf电容*2
5V降压至3.3V降压模块*2
NRF24101无线模块*2
1602液晶显示屏*1
按键*3
蜂鸣器*1
发光二极管*1
排阻10K*9脚*2
四丶NRF12401JI介绍:
1、GFSK调制,硬件集成OSI链路层;
2、具有自动应答和自动再发射功能;
3、片内自动生成报头和CRC校验码;
4、数据传输率为l Mb/s或2Mb/s;
5、SPI速率为0 Mb/s~10 Mb/s;
6、125个频道与其他nRF24系列射频器件相兼容;
7、QFN20引脚4 mm×4 mm封装;
8、供电电压为1.9 V~3.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置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么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配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。
当接收方检测到有效的地址和CRC时,就将数据包存储在
RX FIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。
若此时自动应答开启,接收方则同时进入发射状态回传应答信号。
最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。
在写寄存器之前一定要进入待机模式或掉电模式。
SPI配置:
SPI指令设置
用于SPI接口的常用命令见下表。
当CSN为低时,SPI接口开始等待一条指令,任何一条新指令均由CSN的由高到低的转换开始
寄存器:
读操作
写操作
五丶温度监测:
温度检测模块软件设计DS18B20的测温原理遵循严格的单总线协议,以确保通信数据的准确性,单片机通过时序来写入和读出DS18B20中的数据,包括初始化、读l、读0,写1、写0等操作。
传感器复位后,接收应答信号,跳过读ROM中序列号后,启动温度转换,等待温度转换完毕后,保存数据。
如此反复,完成所有操作。
六丶无线流程:
发射:
首先进行初始化操作,初始化包括设置单片机I/O和SPI相关寄存器两部分其可以和nRF24L01通信。
通过SPI总线配置射频芯片使其进入正确的工作模式。
发射数据时,首先将nRF24L01配置为发射模式。
接着把发送端待发射数据的目标地址TX—ADDR和数据TX
—PLD写入nRF24L01缓冲区,延时后发射数据,其流程图如图4.2所示
接收:
接收数据时,首先将nRF24L01配置为接收模式。
接着延迟进入接收状态等待数据的到来。
当接收方检测到有效地址和CRC时,就将数据包储存在接收堆栈中,同时状态寄存器中的中断标志位RX—DR置高,产生中断使IRQ引脚变为低电平,以便通知MCU去取数据,其流程图如图4.3所示。
七丶软件总体部分:
发送部分:
发送部分的一个循环的总体思路是这样的先初始化DS18B20,从DS18B20读出温度(DS18B20采用默认的12位精度),将得到的温度值的反码转化成十制,取温度数组的高两位(即整数部分)写入发送数据数组,然后初始化nRF24L01,将温度发送,其流程图如图4.5所示
接收部分:
接收部分的总体思路是这样的,首先还是初始化nRF24L01,然后进入大循环判断状态寄存器是否有接收中断。
如果有就从FIFO_buffer读入二进制数据,然后将数据转换成十进制在数码管上显示出来,其流程图如图4.6所示。
八:
电路图:
发射机:
接收机:
九丶程序清单:
接收机:
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineREAD_REG0x00//Definereadcommandtoregister
#defineWRITE_REG0x20//Definewritecommandtoregister
#defineRD_RX_PLOAD0x61//DefineRXpayloadregisteraddress
#defineWR_TX_PLOAD0xA0//DefineTXpayloadregisteraddress
#defineFLUSH_TX0xE1//DefineflushTXregistercommand
#defineFLUSH_RX0xE2//DefineflushRXregistercommand
#defineREUSE_TX_PL0xE3//DefinereuseTXpayloadregistercommand
#defineNOP0xFF//DefineNoOperation,mightbeusedtoreadstatusregister
#defineCONFIG0x00//'Config'registeraddress
#defineEN_AA0x01//'EnableAutoAcknowledgment'registeraddress
#defineEN_RXADDR0x02//'EnabledRXaddresses'registeraddress
#defineSETUP_AW0x03//'Setupaddresswidth'registeraddress
#defineSETUP_RETR0x04//'SetupAuto.Retrans'registeraddress
#defineRF_CH0x05//'RFchannel'registeraddress
#defineRF_SETUP0x06//'RFsetup'registeraddress
#defineSTATUS0x07//'Status'registeraddress
#defineOBSERVE_TX0x08//'ObserveTX'registeraddress
#defineCD0x09//'CarrierDetect'registeraddress
#defineRX_ADDR_P00x0A//'RXaddresspipe0'registeraddress
#defineRX_ADDR_P10x0B//'RXaddresspipe1'registeraddress
#defineRX_ADDR_P20x0C//'RXaddresspipe2'registeraddress
#defineRX_ADDR_P30x0D//'RXaddresspipe3'registeraddress
#defineRX_ADDR_P40x0E//'RXaddresspipe4'registeraddress
#defineRX_ADDR_P50x0F//'RXaddresspipe5'registeraddress
#defineTX_ADDR0x10//'TXaddress'registeraddress
#defineRX_PW_P00x11//'RXpayloadwidth,pipe0'registeraddress
#defineRX_PW_P10x12//'RXpayloadwidth,pipe1'registeraddress
#defineRX_PW_P20x13//'RXpayloadwidth,pipe2'registeraddress
#defineRX_PW_P30x14//'RXpayloadwidth,pipe3'registeraddress
#defineRX_PW_P40x15//'RXpayloadwidth,pipe4'registeraddress
#defineRX_PW_P50x16//'RXpayloadwidth,pipe5'registeraddress
#defineFIFO_STATUS0x17//'FIFOStatusRegister'registeraddress
#defineTX_ADR_WIDTH5
#defineRX_ADR_WIDTH5
#defineTX_PLOAD_WIDTH4
#defineTX_PLOAD_WIDTH4
floatf_temp;
uinttemp;
ucharTX_ADDRESS[5]={0x34,0x43,0x19,0x91,0x09};
ucharbdatasta;
sbitCE=P2^7;
sbitCSN=P2^2;
sbitMOSI=P2^3;
sbitMISO=P2^5;
sbitSCK=P2^6;
sbitIRQ=P2^4;
sbitds=P3^7;
sbitled0=P1^0;
sbitRX_DR=sta^6;
sbitTX_DS=sta^5;
sbitMAX_RT=sta^4;
voidinit_io(void)
{
CE=0;
CSN=1;
SCK=0;
IRQ=1;
}
ucharSPI_RW(ucharbyte)
{
uchari;
for(i=0;i<8;i++)
{
MOSI=(byte&0x80);
byte=(byte<<1);
SCK=1;
byte|=MISO;
SCK=0;
}
return(byte);
}
ucharSPI_RW_reg(ucharreg,ucharvalue)
{
ucharstatus;
CSN=0;
status=SPI_RW(reg);
SPI_RW(value);
CSN=1;
return(status);
}
ucharSPI_read(ucharreg)
{
ucharreg_val;
CSN=0;
SPI_RW(reg);
reg_val=SPI_RW(0);
CSN=1;
return(reg_val);
}
ucharSPI_read_pload(ucharreg,uchar*pBuf,ucharbytes)
{
ucharstatus,i;
CSN=0;
status=SPI_RW(reg);
for(i=0;ipBuf[i]=SPI_RW(0);
CSN=1;
return(status);
}
ucharSPI_write_pload(ucharreg,uchar*pBuf,ucharbytes)
{
ucharstatus,i;
CSN=0;
status=SPI_RW(reg);
for(i=0;iSPI_RW(pBuf[i]);
CSN=1;
return(status);
}
voidTX_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置高,使能发送
}
ucharCheck_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);
}
/*
ucharCheckACK()
{
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);
}
*/
voiddelayus(uintz,uintx)
{
uinti,j;
for(i=z;i>0;i--)
for(j=x;j>0;j--);
}
voiddreset(void)
{
uinti;
//ds=1;
//_nop_();
ds=0;
delayus(7,15);
ds=1;
i=4;
while(i>0)
i--;
delayus(1,100);
}
bittempreadbit(void)
{
uinti;
bitdat;
//ds=1;i++;
ds=0;
_nop_();
ds=1;
i++;i++;
dat=ds;
i=8;
while(i>0)
i--;
return(dat);
}
uchartempread(void)
{
uchari,j,dat;
dat=0;
for(i=0;i<8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1);
}
return(dat);
}
voidtempwritebyte(uchardat)
{
uinti;
ucharj;
bittestb;
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++;
}
}
}
voidtempchange(void)
{
dreset();
delayus(1,113);
tempwritebyte(0xcc);
tempwritebyte(0x44);
}
uintget_temp()
{
uchara,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;
returntemp;
}
voidmain()
{
uchartx_buf[4]={0};
init_io();
while
(1)
{
tempchange();
delayus(1,113);
get_temp();
tx_buf[0]=(uchar)(temp/100);
tx_buf[1]=(uchar)(((temp-500)%100)/10);
tx_buf[2]='.';
tx_buf[3]=(uchar)((temp%100)%10);
TX_mode(tx_buf);
}
}
接收机:
#include
//#include
#defineucharunsignedchar
#defineuintunsignedint
#defineREAD_REG0x00//Definereadcommandtoregister
#defineWRITE_REG0x20//Definewritecommandtoregister
#defineRD_RX_PLOAD0x61//DefineRXpayloadregisteraddress
#defineWR_TX_PLOAD0xA0//DefineTXpayloadregisteraddress
#defineFLUSH_TX0xE1//DefineflushTXregistercommand
#defineFLUSH_RX0xE2//DefineflushRXregistercommand
#defineREUSE_TX_PL0xE3//DefinereuseTXpayloadregistercommand
#defineNOP0xFF//DefineNoOperation,mightbeusedtoreadstatusregister
//SPI(nRF24L01)registers(addresses)
#defineCONFIG0x00//'Config'registeraddress
#defineEN_AA0x01//'EnableAutoAcknowledgment'registeraddress
#defineEN_RXADDR0x02//'EnabledRXaddresses'registeraddress
#defineSETUP_AW0x03//'Setupaddresswidth'registeraddress
#defineSETUP_RETR0x04//'SetupAuto.Retrans'registeraddress
#defineRF_CH0x05//'RFchannel'registeraddress
#defineRF_SETUP0x06//'RFsetup'registeraddress
#defineSTATUS0x07//'Status'registeraddress
#defineOBSERVE_TX0x08//'ObserveTX'registeraddress
#defineCD0x09//'CarrierDetect'registeraddress
#defineRX_ADDR_P00x0A//'RXaddresspipe0'registeraddress
#defineRX_ADDR_P10x0B//'RXaddresspipe1'registeraddress
#defineRX_ADDR_P20x0C//'RXaddresspipe2'registeraddress
#defineRX_ADDR_P30x0D//'RXaddresspipe3'registeraddress
#defineRX_ADDR_P40x0E//'RXaddresspipe4'registeraddress
#defineRX_ADDR_P50x0F//'RXaddresspipe5'registeraddress
#defineTX_ADDR0x10//'TXaddress'registeraddress
#defineRX_PW_P00x11//'RXpayloadwidth,pipe0'registeraddress
#d