当前位置:首页 >> 能源/化工 >>

无线温度监测


摘要:通过使用 DS18B20 温度模块采集数据,将数据通过 51 单片机控制模块使用 NRF24L01 无线模块进行传输,在接收端通过液晶显示模块 LCD1602 显示温度模块传输的温 度数据,本设计具有发射距离远,精度高的优点,能满足我们课程设计的要求。 关键词:温度模块 DS18B20 无线模块 NRF24L01 LCD1602

1、设计目的、要求及方


1.1 设计目的
在工业生产中,温度是一个非常重要的指标。 为了保证安全生产,需要对温度 进行采集与测量,并根据采集到的数据控制输出。传统的数据传输方式是通过敷 设有线的通信线路来传递数据信息(常见的有 RS485 总线结构等),这种方式不仅 施工麻烦、 费用高,而且出现故障时不易排查,越来越不能满足现代工业快速发展 的需求。而无线数据传输方式具有不用布线、实时性高、容易重新部署等优点, 非常适用于现代工业监控系统[1]。 在本系统中把温度传感器 DS18B20 所采集到的温度值送给单片机进行处理, 通过 NRF2401 无线模块实现远程无线传输, 使用数码管或液晶屏显示所采集的温 度。故设计本系统,既能准确的测量温度,又能解决测量距离上的问题。

1.2 设计要求
(1)实时获取被测对象温度,温度测量范围:-10℃ ~+45℃; 测量精度:?0.1℃。 (2)无线传输实时获取的温度值,传输距离?10m。 (3)实时显示接收到的温度值。 (4)基于单片机实现。 (5)电路制作时,必须有学号或姓名。 (6)能够切换信道,用数码管显示信道(0—5) 。

1.3 设计方案
1.3.1 控制模块 采用宏晶科技有限公司的 STC89C52 作为主控芯片。此芯片内置 ADC 和 SPI 总线接口,且内部时钟不分频,达到 1MPS。而且价格适中,方便制作电路板及 焊接工作,能达到设计要求的性能[1]。 1.3.2 无线通信模块方案 由于 NRF24L01 是一款高速低功耗的无线通信模块,能传输上百米的距离, 而且价格较便宜,采用 SPI 总线通信模式电路简单,操作方便。符合设计要求, 故采用 NRF24L01 无线射频模块进行通信

1.3.3 温度传感方案 采用美国 DALLAS 公司生产的 DS18B20 可组网数字温度传感器芯片,具有耐磨 耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和 控制领域。经济,方便。线路简单,编程容易,考虑到电路的设计,成本,还有 多点通信,采用 DS18B20 作为本系统的温度传感器[2]。 1.3.4 显示模块方案 由于只需要显示温度, 还有学号,故选择采用字符液晶 LCD1602 当作显示器 较为合适, LCD1602 是一款比较通用的字符液晶模块, 能显示字符、 数字等信息, 且价格便宜,容易控制[2]。 1.3.5 信道选择方案 直接使用按键接单片机的 I/O 口,进行信道的选择, 通过数码管模块显示信 道的序号。 1.3.6 设计方案框图 综合以上几点设计方案,设计出方案框图如图 1 发送模块方案框图,图 2 接收模块方案框图
按键控制模块

温度传感器 DS18B20

控制模块STC89C52

无线发射模块 NRF24L01

数码管显示信道模块

图 1 发送模块方案框图

按键控制模块

无线接收模块 NRF24L01

控制模块STC89C52

显示模块LCD1602

数码管显示信道模块

图 2 接收模块方案框图

2.基本原理
无线温度监控系统由发送模块和接收两大模块组成,其原理如下: 发送模块:温度传感器 DS18B20 将采集到的信号送到单片机控制模块存储, 通过按键使控制模块将信号处理然后送到无线模块 NRF24L01 经行数据传输,数 码管显示出所选择的通信信道。 接收模块:通过按键使无线模块 NRF24L01 接收到发送模块的数据,把数据 送到 51 控制模块,控制模块将数据处理后通过 LCD1602 把温度显示出来,数码 管显示出所选择的通信信道。 系统组成方框图如图 3 无线温度监测器系统组成方框图所示:
按键控制模块 无线发射模块NRF24L01

控制模块STC89C52 温度传感器DS18B20 数码管显示信道模块

数码管显示信道模块
控制模块STC89C52 显示模块LCD1602

按键控制模块

无线接收模块NRF24L01

图 3 无线温度监测器系统组成方框图

3.硬件电路设计
3.1 温度模块
温度模块设计分析: 根据 DS18B20 的设计原理, 第 1 个引脚接 GND;第 2 个引脚接单片机的 P2.2 口;第 2 个引脚再串联一个 4.7k 到 VCC;第 3 个引脚直接接 VCC。[3] 电路连接原理图如图 4 温度模块原理图所示

图 4 温度模块原理图

3.2 无线收发模块
无线收发模块 NRF24L01 的各引脚与单片机的 P1 口相连, 电路连接原理图如 图 5 无线模块收发原理图所示

图 5 无线模块收发原理图

无线收发模块 NRF24L01 引脚功能: CSN(P1.0):芯片的片选线,CSN 为低电平芯片工作。 SCK(P1.4):芯片控制的时钟线(SPI 时钟) 。 MISO(P1.3):芯片控制数据线(Master input slave output) 。 MOSI(P1.1):芯片控制数据线(Master output slave input) 。 IRQ(P1.2):中断信号。无线通信过程中 MCU 主要是通过 IRQ 与 NRF24L01 进行通信。 CE(P1.5):芯片的模式控制线。在 CSN 为低的情况下,CE 协同 NRF24L01 的 CONFIG 寄存器共同决定 NRF24L01 的状态。

3.3 液晶显示模块
液晶显示模块设计,数据口 DB0-DB7 连接单片机的 P0 口;RS、R/W、E 这 3 条控制线分别接单片机的 P2.3、P2.4 和 P2.5 口。电阻 R3 用来调节背光的亮度。 电路连接原理图如图 6 显示模块原理图所示

图 6 显示模块原理图

3.4 系统原理图及 PCB 图
发送端原理图如图 7 无线发送系统原理图所示:

图 7 无线发送系统原理图

接收端原理图如图 8 线接收系统原理图所示:

图 8 无线接收系统原理图

4、软件程序设计
4.1 无线收发模块 NRF24L01 的编程
4.1.1NRF24L01 编程的基本思路 (1) 置 CSN 为低,使能芯片,配置芯片各个参数。配置参数在 Power Down 状态中完成。 (2)如果是 Tx 模式,填充 Tx FIFO。 (3)配置完成以后,通过 CE 与 CONFIG 中的 PWR_UP 与 PRIM_RX 参数确定 NRF24L01 要切换到的状态。 Tx Mode:PWR_UP=1;PRIM_RX=0; CE=1(保持超过 10us 就可以); Rx Mode:PWR_UP=1;PRIM_RX=1; CE=1; (4) IRQ 引脚会在以下三种情况变低: ① Tx FIFO 发完并且收到 ACK(使能 ACK 情况下) ② Rx FIFO 收到数据 ③ 达到最大重发次数 4.1.2 Tx 与 Rx 的配置过程 Tx 模式初始化过程 (1)写 Tx 节点的地址 TX_ADDR (2)写 Rx 节点的地址(主要是为了使能 Auto Ack) RX_ADDR_P0 (3)使能 AUTO ACK EN_AA (4)使能 PIPE 0 EN_RXADDR (5)配置自动重发次数 SETUP_RETR (6)选择通信频率 RF_CH (7)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP (8)选择通道 0 有效数据宽度 Rx_Pw_P0 (9)配置 24L01 的基本参数以及切换工作模式 CONFIG。 4.1.3NRF24L01 数据信道的切换 NRF24L01 配置为接收模式时,可以接收 6 路不同地址相同频率的数据,每 个数据通道拥有自己的地址, 并且可以通过寄存器来进行分别配置。数据通道是 通过寄存器 EN_RXADDR 来设置的默认状态下只有数据通道 0 和数据通道 1 是开启 状态的每一个数据通道的地址是通过寄存 RX_ADDR_Px 来配置的,通常情况下不 允许不同的数据通道设置完全相同的地址。数据通道 0 有 40 位可配置地址,数 据通道 1-5 的地址:为 32 位共用地址+各自的地址(最低字节) ,1-5 数据通道 的最低位必须不同。

发送端通过按键把数据通道从 0-5 经行切换,选择不同的地址经行通信,接 收端同样经行对应的处理以便通信。 发送端切换通道的程序:

接收端的选择程序

uchar code dizhi[]={0x01,0x02,0x04,0x08,0x10,0x20}; //接收通道和使能通 道的切换 通过按键的选择,通道能从 0 到 5 进行切换,然后只有通道相同才可以传输 数据,显示屏上才有数据更新。

4.2 DS18B20 温度模块
温度模块读取温度程序流程图如图 9 读取温度程序流程图所示
开始 定义变量并初始化 DS18B20初始化 跳过读序列号 启动温度转换

结束

赋值变量

读取温度寄存器

跳过读序列号

DS18B20初始化

延时 10ms

图 9 读取温度程序流程图

程序见附录 A

5、PCB 板的设计与制作:
5.1 PCB 图设计
PCB 图如图 10 所示:

PCB 图的设计如图 10 PCB 图所示
图 10 PCB 图所示

6、电路的调试及调试结果
把 PCB 板制作完毕之后,拿到元器件之后,开始进行焊接,对安装焊接工艺 要求是:电阻,电容尽可能卧式安装,减少虚焊,脱焊现象,贴片元器件等需要 快速焊接,避免元器件由于温度过高而损坏。 进行测试的时候发现 LCD 没有显示数据,然后对 LCD1602 进行测试,没有问 题;对照资料才发现数据口反过来接了,然后用杜邦线进行重新连接,测试通过 了[3]。 接着排查无线模块, 温度模块, 进行资料的查询, 发现 DS18B20 引脚接反了, 然后把 DS18B20 调转插在底座上面 。 无线模块也没有正常工作, 是因为没有正常的供电, 缺少 AMS1117 降压模块, 然后手工焊接了一个降压模块,无线模块也正常工作了,然后进行整体测试,硬 件测试通过。 接着就是程序测试,一开始是数据不能正确显示,有一些字符乱码,通过调 试程序,优化 LCD 显示,完成测试。[3] 由于设计要求需要进行信道的切换,一开始写了数组进行信道的选择,但是 达不到所需要的效果, 只能有通道 0 和 1 可以单独通信, 其他通道无法进行通信。 后来才知道信道的使能端也需要进行选择处理,才可以对数据进行单独处理。 因为一开始对无线模块的使能通道处理不妥当,发送端和接收端全打开 (0x3f)处理,所以进行通信的时候,只有 0 和 1 可以切换,其他通道时会出现 错误, 当接收端为 0 时, 发送端每一个通道都可以传输数据, 所以一直在找原因。 最后才知道要在接收端进行使能端的选择,才能使通道单独选择,而不收其他通 道的影响。 发送端原处理程序如下: SPI_W_Reg(W_REGISTER+EN_AA,0x30);/*接收通道自动应答*/ SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x30);/*使能接收通道*/ 修改后把 0x30 改为 0x3f,把通道使能全打开,程序如下: SPI_W_Reg(W_REGISTER+EN_AA,0x3f);/*接收全通道自动应答*/ SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x3f);/*使能接收权通道*/ 接收端的使能端进行按键选择,原程序如下: SPI_W_Reg(W_REGISTER+EN_AA,0x3f); SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x3f); 调试之后程序为: uchar code dizhi[]={0x01,0x02,0x04,0x08,0x10,0x20};
[3]

SPI_W_Reg(W_REGISTER+EN_AA,dizhi[xuan]); SPI_W_Reg(W_REGISTER+EN_RX_ADDR,dizhi[xuan]);

7、实验总结及心得体会
这次课程设计一共做了几个 PCB 才成功,由于第一个缺陷太多,所以重新修 改原理图及 PCB, 制作第二个 PCB 板, 把元器件拆卸下来重新焊接到第二板子上, 出现了不少错误,后来在切换信道的功能上,又进行了第三个板子制作,终于调 通了。所以在刚动手之前就要想清楚原理图,最好进行仿真,以免出现过多的错 误,导致损坏元器件。 在实验过程中,通过选取元件、确定电路形式、以及计算等等,同时通过调 试来发现自己的错误并分析及排除这些故障。 焊接电路板更要注意, 要先检查所有的元件是否可用,焊接二极管电接电容 时应分清正负极焊接时要注意防止虚焊,电容电感尽量卧式安装,焊接完成后尽 量缩短元件引线,但不用剪太短,否则不容易更改。
参考文献 [1] 付聪,付慧生,李益青. 基于 NRF24L01 无线温度采集控制系统的设计[J].工业自 动化.2010 年 1 月,第一期:73-74 [2] 王振, 胡清, 黄杰. 基于 NRF24L01 无线温度采集系统设计[J].电子设计工程.2009 年 12 月,第十二期第 17 卷:24-25 [3] 郭天祥著. 51 单片机 C 语言教程[M].北京:电子工业出版社.2012 年: 148-156, 342-354

附录 A
无线温度发送模块程序代码: #include <reg52.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char #define TX_ADDR_WITDH 5//发送地址宽度设置为 5 个字节 #define RX_ADDR_WITDH 5 #define TX_DATA_WITDH 5 #define RX_DATA_WITDH 5 /****************************************************************** // nRF24L01 指令格式: *******************************************************************/ #define R_REGISTER 0x00 // 读寄存器 #define W_REGISTER 0x20 // 写寄存器 #define R_RX_PLOAD 0x61 // 读 RX FIFO 有效数据,1-32 字节,当读数据完成后,数 据被清除,应用于接收模式 #define W_TX_PLOAD 0xA0 // 写 TX FIFO 有效数据,1-32 字节,写操作从字节 0 开始, 应用于发射模式 #define FLUSH_TX 0xE1 // 清除 TX FIFO 寄存器,应用于发射模式 #define FLUSH_RX 0xE2 // 清除 RX FIFO 寄存器,应用于接收模式 #define REUSE_TX_PL 0xE3 // 重新使用上一包有效数据,当 CE 为高过程中,数据包被不 断的重新发射 #define NOP 0xFF // 空操作,可以用来读状态寄存器 /****************************************************************** // nRF24L01 寄存器地址 *******************************************************************/ #define CONFIG 0x00 // 配置寄存器 #define EN_AA 0x01 // “自动应答”功能寄存 #define EN_RX_ADDR 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 // 数据通道 1 有效数据宽度设置寄存器 #define RX_PW_P2 0x13 // 数据通道 2 有效数据宽度设置寄存器 #define RX_PW_P3 0x14 // 数据通道 3 有效数据宽度设置寄存器 #define RX_PW_P4 0x15 // 数据通道 4 有效数据宽度设置寄存器 #define RX_PW_P5 0x16 // 数据通道 5 有效数据宽度设置寄存器 #define FIFO_STATUS 0x17 // FIFO 状态寄存器 //***************************************************************************** **** uchar sta; // 状态变量 #define RX_DR (sta & 0x40) // 接收成功中断标志 #define TX_DS (sta & 0x20) // 发射成功中断标志 #define MAX_RT (sta & 0x10) // 重发溢出中断标志 sbit CE=P1^5; sbit IRQ=P1^2; sbit CSN=P1^0; sbit MOSI=P1^1; sbit MISO=P1^3; sbit SCK=P1^4; sbit DQ=P2^2; sbit key=P2^6; uchar uchar uchar uchar uchar uchar code code code code code code TX_Addr[]={0x34,0x43,0x10,0x10,0x01}; TX_Addr1[]={0x33,0x42,0x11,0x11,0x21}; //++++++++ TX_Addr2[]={0xb1,0x42,0x11,0x11,0x21}; TX_Addr3[]={0xb2,0x42,0x11,0x11,0x21}; TX_Addr4[]={0xb3,0x42,0x11,0x11,0x21}; TX_Addr5[]={0xb4,0x42,0x11,0x11,0x21};

uchar code shuma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92}; uchar counter=0; uchar RX_Buffer[RX_DATA_WITDH]; uchar Temp_Value[]={0x00,0x00}; uchar Temp=0; uchar Display_Digit[]={0,0,0,0}; bit DS18B20_IS_OK=1; uchar code df_tab[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};//decimal fraction void _delay_tus(uint x) { while(--x); }

void _delay_us(uint x) { uint i,j; for (j=0;j<x;j++) for (i=0;i<12;i++); } void _delay_ms(uint x) { uint i,j; for (j=0;j<x;j++) for (i=0;i<120;i++); } /**************************************************/ /*函数功能:DS18B20 初始化 */ /*入口参数:无 */ /*出口函数:status */ /**************************************************/ uchar DS18B20_Init(void) { uchar status; DQ=1; _delay_tus(10); DQ=0; _delay_tus(90); DQ=1; _delay_tus(8); status=DQ; _delay_tus(100); DQ=1; return status; } /**************************************************/ /*函数功能:从 DS18B20 读取一字节 */ /*入口参数:无 */ /*出口函数:dat(返回读取到数据) */ /**************************************************/ uchar Read_One_Byte(void) { uchar i,dat=0; DQ=1; _nop_(); for(i=8;i>0;i--) { DQ=0;

dat>>=1; DQ=1; _nop_();_nop_(); if(DQ) dat|=0x80; _delay_tus(30); DQ=1; } return dat; } /**************************************************/ /*函数功能:向 DS18B20 写一字节 */ /*入口参数:dat(把 dat 写入 DS18B20) */ /*出口函数:无 */ /**************************************************/ void Write_One_Byte(uchar dat) { uchar i; for(i=8;i>0;i--) { DQ=0; DQ=dat&0x01; _delay_tus(5); DQ=1; dat>>=1; } } /**************************************************/ /*函数功能:从 DS18B20 读取数据(数据) */ /*入口参数:无 */ /*出口函数:无 */ /**************************************************/ void Read_Temp(void) { uchar ng=0; if(DS18B20_Init()==1) DS18B20_IS_OK=0; else { Write_One_Byte(0xcc); Write_One_Byte(0x44); DS18B20_Init(); Write_One_Byte(0xcc); Write_One_Byte(0xbe);

Temp_Value[0]=Read_One_Byte(); Temp_Value[1]=Read_One_Byte(); DS18B20_IS_OK=1; } if((Temp_Value[1]&0xf8)==0xf8) { Temp_Value[1]=~Temp_Value[1]; Temp_Value[0]=~Temp_Value[0]+1; if(Temp_Value[0]==0x00) Temp_Value[1]++; ng=1; } Display_Digit[0]=df_tab[Temp_Value[0]&0x0f]; Temp=((Temp_Value[0]&0xf0)>>4)|((Temp_Value[1]&0x07)<<4); Display_Digit[3]=Temp/100; Display_Digit[2]=Temp%100/10; Display_Digit[1]=Temp%10; } /*nRF24L01 初始化*/ void nRF24L01_Init(void) { _delay_us(2000); CE=0;//待机模式Ⅰ CSN=1; SCK=0; IRQ=1; } /*SPI 时序函数*/ uchar SPI_RW(uchar byte) { uchar i; for(i=0;i<8;i++)//一字节 8 位循环 8 次写入 { if(byte&0x80)//如果数据最高位是 1//当访问多字节寄存器时首先要读/写的是 最低字节的高位? MOSI=1;//向 NRF24L01 写 1 else //否则写 0 MOSI=0; byte<<=1;//低一位移到最高位 SCK=1;//SCK 拉高,写入一位数据,同时读取一位数据 if(MISO) byte|=0x01; SCK=0;//SCK 拉低

} return byte;//返回读取一字节 } /*SPI 写寄存器一字节函数*/ /*reg:寄存器地址*/ /*value:一字节(值)*/ uchar SPI_W_Reg(uchar reg,uchar value) { uchar status;//返回状态 CSN=0;//SPI 片选 status=SPI_RW(reg);//写入寄存器地址,同时读取状态 SPI_RW(value);//写入一字节 CSN=1;// return status;//返回状态 } /*SPI*/ uchar SPI_R_byte(uchar reg) { uchar reg_value; CSN=0;//SPI 片选 SPI_RW(reg);//写入地址 reg_value=SPI_RW(0);//读取寄存器的值 CSN=1; return reg_value;//返回读取的值 } /*SPI 读取 RXFIFO 寄存器数据*/ /*reg:寄存器地址*/ /**Dat_Buffer:用来存读取的数据*/ /*DLen:数据长度*/ uchar SPI_R_DBuffer(uchar reg,uchar *Dat_Buffer,uchar Dlen) { uchar status,i; CSN=0;//SPI 片选 status=SPI_RW(reg);//写入寄存器地址,同时状态 for(i=0;i<Dlen;i++) { Dat_Buffer[i]=SPI_RW(0);//存储数据 } CSN=1; return status; } /*SPI 向 TXFIFO 寄存器写入数据*/ /*reg:写入寄存器地址*/ /*TX_Dat_Buffer:存放需要发送的数据*/

/*Dlen:数据长度*/ uchar SPI_W_DBuffer(uchar reg,uchar *TX_Dat_Buffer,uchar Dlen) { uchar status,i; CSN=0;//SPI 片选,启动时序 status=SPI_RW(reg); for(i=0;i<Dlen;i++) { SPI_RW(TX_Dat_Buffer[i]);//发送数据 } CSN=1; return status; } /*设置发送模式*/ void nRF24L01_Set_TX_Mode(uchar *TX_Data) { CE=0;//待机(写寄存器之前一定要进入待机模式或掉电模式) CSN=0; SPI_RW(FLUSH_TX); CSN=1; /*信道的选择,按键切换*/ if(key==0) { _delay_ms(20); if(key==0) { P0=shuma[counter]; _delay_ms(50); switch(counter) { case 0 : SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH); break; case 1 : SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr1,TX_ADDR_WITDH); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P1,TX_Addr1,TX_ADDR_WITDH); break; case 2 : SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr2,TX_ADDR_WITDH); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P2,TX_Addr2,TX_ADDR_WITDH); break; case 3 : SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr3,TX_ADDR_WITDH);

SPI_W_DBuffer(W_REGISTER+RX_ADDR_P3,TX_Addr3,TX_ADDR_WITDH); break; case 4 : SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr4,TX_ADDR_WITDH); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P4,TX_Addr4,TX_ADDR_WITDH); break; case 5 : SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr5,TX_ADDR_WITDH); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P5,TX_Addr5,TX_ADDR_WITDH); break; } counter++; if(counter==6) counter=0; } } SPI_W_DBuffer(W_TX_PLOAD,TX_Data,TX_DATA_WITDH);/* 写有效数据地址 + 有效数据 + 有效数据宽度*/ SPI_W_Reg(W_REGISTER+EN_AA,0x3f);/*接收全通道自动应答*/ SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x3f);/*使能接收全通道*/ SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);/*自动重发延时 250US+86US,重发 10 次*/ SPI_W_Reg(W_REGISTER+RF_CH,0x27);/*(2400+39)MHZ 选择射频通道 0X27*/ SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);/*1Mbps 速率,发射功率:0DBM,低噪声放大器 增益*/ SPI_W_Reg(W_REGISTER+CONFIG,0x0e);/*发送模式,上电,16 位 CRC 校验,CRC 使能*/ CE=1;//启动发射 _delay_ms(5);/*CE 高电平持续时间最少 10US 以上*/ } uchar Check_Rec(void) { uchar status; sta=SPI_R_byte(R_REGISTER+STATUS); if(RX_DR) { CE=0; SPI_R_DBuffer(R_RX_PLOAD,RX_Buffer,RX_DATA_WITDH); status=1; } SPI_W_Reg(W_REGISTER+STATUS,0xff); return status; } /*检测应答信号*/

uchar Check_Ack(void) { sta=SPI_R_byte(R_REGISTER+STATUS);/*读取寄存状态*/ if(TX_DS||MAX_RT)/*如果 TX_DS 或 MAX_RT 为 1,则清除中断和清除 TX_FIFO 寄存器的 值*/ { SPI_W_Reg(W_REGISTER+STATUS,0xff); CSN=0; SPI_RW(FLUSH_TX); CSN=1; return 0; } else return 1; } void main(void) { uchar i; P0=0xff; P1=0xff; P2=0xff; P3=0xff; nRF24L01_Init(); Read_Temp(); _delay_ms(1000); while(1) { Read_Temp(); if(DS18B20_IS_OK) { for(i=0;i<TX_DATA_WITDH-4;i++)//减 1 是因为最后一位为结束标志 { nRF24L01_Set_TX_Mode(&Display_Digit[i]); _delay_ms(100); while(Check_Ack()); } } } }

无线温度接收模块程序代码:

#include <reg52.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char #define TX_ADDR_WITDH 5//发送地址宽度设置为 5 个字节 #define RX_ADDR_WITDH 5 #define TX_DATA_WITDH 5 #define RX_DATA_WITDH 5 /****************************************************************** // nRF24L01 指令格式: *******************************************************************/ #define R_REGISTER 0x00 // 读寄存器 #define W_REGISTER 0x20 // 写寄存器 #define R_RX_PLOAD 0x61 // 读 RX FIFO 有效数据,1-32 字节,当读数据完成后,数 据被清除,应用于接收模式 #define W_TX_PLOAD 0xA0 // 写 TX FIFO 有效数据,1-32 字节,写操作从字节 0 开始, 应用于发射模式 #define FLUSH_TX 0xE1 // 清除 TX FIFO 寄存器,应用于发射模式 #define FLUSH_RX 0xE2 // 清除 RX FIFO 寄存器,应用于接收模式 #define REUSE_TX_PL 0xE3 // 重新使用上一包有效数据,当 CE 为高过程中,数据包被不 断的重新发射 #define NOP 0xFF // 空操作,可以用来读状态寄存器 /****************************************************************** // nRF24L01 寄存器地址 *******************************************************************/ #define CONFIG 0x00 // 配置寄存器 #define EN_AA 0x01 // “自动应答”功能寄存器 #define EN_RX_ADDR 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 // 数据通道 1 有效数据宽度设置寄存器

#define RX_PW_P2 0x13 // 数据通道 2 有效数据宽度设置寄存器 #define RX_PW_P3 0x14 // 数据通道 3 有效数据宽度设置寄存器 #define RX_PW_P4 0x15 // 数据通道 4 有效数据宽度设置寄存器 #define RX_PW_P5 0x16 // 数据通道 5 有效数据宽度设置寄存器 #define FIFO_STATUS 0x17 // FIFO 状态寄存器 //***************************************************************************** **** uchar sta; // 状态变量 #define RX_DR (sta & 0x40) // 接收成功中断标志 #define TX_DS (sta & 0x20) // 发射成功中断标志 #define MAX_RT (sta & 0x10) // 重发溢出中断标志 sbit sbit sbit sbit sbit sbit CE=P1^5; IRQ=P1^2; CSN=P1^0; MOSI=P1^1; MISO=P1^3; SCK=P1^4;

sbit key1=P1^6; sbit key2=P1^7; sbit deng=P2^0; sbit LCD_RS=P2^3; sbit LCD_RW=P2^4; sbit LCD_EN=P2^5; uchar uchar uchar uchar uchar uchar uchar uchar uchar uchar uchar uchar code TX_Addr[]={0x34,0x43,0x10,0x10,0x01}; code TX_Addr1[]={0x33,0x42,0x11,0x11,0x21}; //++++++++ code TX_Addr2[]={0xb1}; code TX_Addr3[]={0xb2}; code TX_Addr4[]={0xb3}; code TX_Addr5[]={0xb4}; code dizhi[]={0x01,0x02,0x04,0x08,0x10,0x20}; //+++++++ code shuma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92};//++++++ code TX_Buffer[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; RX_Buffer[RX_DATA_WITDH]; code Display_LINE0[]={"ID:110709 06/14 "}; Display_LINE1[]={" TEMP: "};

uchar counter=0; uchar xuan=0; void _delay_us(uint x)

{ uint i,j; for (j=0;j<x;j++) for (i=0;i<12;i++); } void _delay_ms(uint x) { uint i,j; for (j=0;j<x;j++) for (i=0;i<120;i++); } bit LCD_Busy(void)//测忙 { bit LCD_Status;//返回值变量 LCD_RS=0;//读取状态 LCD_RW=1; LCD_EN=1; _nop_();_nop_();_nop_();_nop_(); LCD_Status=(bit)(P0&0x80); LCD_EN=0; return LCD_Status; } void LCD_Write_Command(uchar cmd)//写指令 { LCD_RS=0; LCD_RW=0; LCD_EN=0; _nop_();_nop_(); P0=cmd; _nop_();_nop_();_nop_();_nop_(); LCD_EN=1; _nop_();_nop_();_nop_();_nop_(); LCD_EN=0; } void LCD_Write_Data(uchar dat)//写数据 { //每次写数据操作之前均需要检测忙信号 LCD_RS=1; LCD_RW=0; LCD_EN=0; P0=dat; _nop_();_nop_();_nop_();_nop_(); LCD_EN=1; _nop_();_nop_();_nop_();_nop_();

LCD_EN=0; } void Init_LCD(void)//液晶初始化 { _delay_ms(15);//延时 15MS LCD_Write_Command(0x38); _delay_ms(5); LCD_Write_Command(0x38); _delay_ms(5); LCD_Write_Command(0x38);//以后每次写指令操作之前均需要检测忙信号 _delay_ms(5); LCD_Write_Command(0x01);//清屏 _delay_ms(5); LCD_Write_Command(0x38);//设置 16*2 显示,5*7 点阵,8 位数据接口 _delay_ms(5); LCD_Write_Command(0x0c);//开显示,不显示光标 _delay_ms(5); LCD_Write_Command(0x06);//当读或写一个字符后地址指针加一,且光标加一 } void LCD_POS(uchar pos)//字符显示位置 { LCD_Write_Command(0x80|pos); } void Show_String(uchar *str)//显示字符串 { while(*str!='\0') LCD_Write_Data(*str++); } void nRF24L01_Init(void) { _delay_us(2000); CE=0; CSN=1; SCK=0; IRQ=1; } uchar SPI_RW(uchar byte) { uchar i; for(i=0;i<8;i++) { if(byte&0x80) MOSI=1; else

MOSI=0; byte<<=1; SCK=1; if(MISO) byte|=0x01; SCK=0; } return byte; } uchar SPI_W_Reg(uchar reg,uchar value) { uchar status; CSN=0; status=SPI_RW(reg); SPI_RW(value); CSN=1; return status; } uchar SPI_R_byte(uchar reg) { uchar status; CSN=0; SPI_RW(reg); status=SPI_RW(0); CSN=1; return status; } uchar SPI_R_DBuffer(uchar reg,uchar *Dat_Buffer,uchar Dlen) { uchar reg_value,i; CSN=0; reg_value=SPI_RW(reg); for(i=0;i<Dlen;i++) { Dat_Buffer[i]=SPI_RW(0); } CSN=1; return reg_value; } uchar SPI_W_DBuffer(uchar reg,uchar *TX_Dat_Buffer,uchar Dlen) { uchar reg_value,i;

CSN=0; reg_value=SPI_RW(reg); for(i=0;i<Dlen;i++) { SPI_RW(TX_Dat_Buffer[i]); } CSN=1; return reg_value; } void nRF24L01_Set_RX_Mode(void) { CE=0;//待机 /*信道的选择,按键切换*/ if(key1==0) { _delay_ms(20); if(key1==0) { switch(counter) { case 0 : P3=shuma[counter]; _delay_ms(1000); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH); SPI_W_Reg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH); break; case 1 : P3=shuma[counter]; _delay_ms(1000); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P1,TX_Addr1,TX_ADDR_WITDH); SPI_W_Reg(W_REGISTER+RX_PW_P1,RX_DATA_WITDH); break; case 2 : P3=shuma[counter]; _delay_ms(1000); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P2,TX_Addr2,1); SPI_W_Reg(W_REGISTER+RX_PW_P2,RX_DATA_WITDH); break; case 3 : P3=shuma[counter]; _delay_ms(1000); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P3,TX_Addr3,1); SPI_W_Reg(W_REGISTER+RX_PW_P3,RX_DATA_WITDH); break; case 4 : P3=shuma[counter];

_delay_ms(1000); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P4,TX_Addr4,1); SPI_W_Reg(W_REGISTER+RX_PW_P4,RX_DATA_WITDH); break; case 5 : P3=shuma[counter]; _delay_ms(1000); SPI_W_DBuffer(W_REGISTER+RX_ADDR_P5,TX_Addr5,1); SPI_W_Reg(W_REGISTER+RX_PW_P5,RX_DATA_WITDH); break; } counter++; if(counter==6) counter=0; } } if(key2==0) { _delay_ms(20); if(key2==0) { deng=~deng; _delay_ms(1000); xuan++; } } SPI_W_Reg(W_REGISTER+EN_AA,dizhi[xuan]); SPI_W_Reg(W_REGISTER+EN_RX_ADDR,dizhi[xuan]); SPI_W_Reg(W_REGISTER+RF_CH,0x27); SPI_W_Reg(W_REGISTER+RF_SETUP,0x07); SPI_W_Reg(W_REGISTER+CONFIG,0x0f); CE=1; _delay_ms(5); if(xuan==6) xuan=0; } uchar nRF24L01_RX_Data(void) { sta=SPI_R_byte(R_REGISTER+STATUS); if(RX_DR) { CE=0; SPI_R_DBuffer(R_RX_PLOAD,RX_Buffer,RX_DATA_WITDH); SPI_W_Reg(W_REGISTER+STATUS,0xff);

CSN=0; SPI_RW(FLUSH_RX); CSN=1; return 1; } else return 0; } void main(void) { uchar i,RX_Temp_Value[RX_DATA_WITDH]; P0=0xff; P1=0xff; P2=0xff; P3=0xff; Init_LCD(); nRF24L01_Init(); _delay_us(1000); LCD_POS(0); Show_String(Display_LINE0); while(1) { nRF24L01_Set_RX_Mode(); if(nRF24L01_RX_Data()) { for(i=0;i<RX_DATA_WITDH;i++) { RX_Temp_Value[i]=RX_Buffer[i]; } } Display_LINE1[7]=RX_Temp_Value[3]+'0'; Display_LINE1[8]=RX_Temp_Value[2]+'0'; Display_LINE1[9]=RX_Temp_Value[1]+'0'; Display_LINE1[10]='.'; Display_LINE1[11]=RX_Temp_Value[0]+'0'; Display_LINE1[12]=0xdf; Display_LINE1[13]=0x43; if(RX_Temp_Value[3]==0) Display_LINE1[7]=' '; LCD_POS(0x40); Show_String(Display_LINE1); } }


相关文章:
无线温度监测
无线温度监测_能源/化工_工程科技_专业资料。摘要:通过使用 DS18B20 温度模块采集数据,将数据通过 51 单片机控制模块使用 NRF24L01 无线模块进行传输,在接收端通过...
基于单片机的无线温度检测器的设计
ANYANG INSTITUTE OF TECHNOLOGY 本 科 毕 业 论 文 基于单片机的无线温度检测器的设计 The Design of Wireless Temperature Detector Based on MCU 院(部)名称:...
无线温度监测系统
无线温度监测系统_解决方案_计划/解决方案_实用文档。无线温度监测系统 上海仁微电子科技股份有限公司是以技术立本的物联网技术研发和服务型公司。 针对大型工业企业...
无线温度检测系统
大连民族学院课程设计论文 大连民族学院 单片机系统课程设计 题目: 班级: 姓名: 同组人: 无线温度监测系统 通信 101 王先冬 姚常福 丁季峰 指导教师: 设计日期: ...
无线温度在线监测
无线温度在线监测 一、概述 DYW2000 系列无线温度在线监测是我公司借鉴国内外同类无线温度在线监测为 保证电力电 器良好的运行环境,针对电气设备接点部位由于材料老化...
多点温度无线检测系统
多点温度无线检测系统_IT/计算机_专业资料。电路综合系统课程设计 题学 目院 多点温度无线检测系统 电子信息与电气工程学院 I 摘要 本文论述的远程温度控制是将...
温度检测系统无线传输的设计
1.2 课题内容温度检测无线传输系统是无线通信技术在温度数据无线传输方面的一个 具体应用。 该系统属于无线通信系统,设计的最主要内容是对其完成功能得各部 分...
HYCW无线测温在线监测系统技术方案
7 三、产品常用现场安装示意图片 第四章 无线测温系统后台软件 一、直观显示接头的温度 软件充分发挥了温度监测与地理信息相结合的优势, 在软件界面上直观显示开关 ...
基于ZigBee的无线温度检测系统设计
40 V 江苏师范大学科文学院本科生毕业设计 基于 Zigbee 的无线温度检测系统设计 1 绪论 1.1 引言温控系统、冷库温控系统、智能化建筑控制系统、中央空调系统等众多...
基于无线传感网络的环境温度监测系统设计
基于无线传感网络的 环境温度检测系统如图 1 所示。 1 簇头 GPRS 骨干网 汇聚节点 任务管 理节点 监测区域 图 1 环境温度监测系统架构 本系统主要实现采集节点...
更多相关标签:
无线温湿度监测系统 | 无线温度监测系统 | 无线温湿度监测仪 | 无线温度监控系统 | 电力无线测温系统 | 多点温度测量仪 | 无线温湿度监测 | 无线温度监测器 |