温度无线传输南阳理工周渴望本次所做是基于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。