摘要:通过使用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接收模块方案框图
图1发送模块方案框图
图2接收模块方案框图
2. 基本原理
无线温度监控系统由发送模块和接收两大模块组成,其原理如下:
发送模块:温度传感器DS18B20将采集到的信号送到单片机控制模块存储,通过按键使控制模块将信号处理然后送到无线模块NRF24L01经行数据传输,数码管显示出所选择的通信信道。
接收模块:通过按键使无线模块NRF24L01接收到发送模块的数据,把数据送到51控制模块,控制模块将数据处理后通过LCD1602把温度显示出来,数码管显示出所选择的通信信道。
系统组成方框图如图3无线温度监测器系统组成方框图所示:
图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
进行通信。 的CONFIG 寄存器共同决定NRF24L01的状态。 CE(P1.5):芯片的模式控制线。在CSN 为低的情况下,CE 协同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读取温度程序流程图所示
图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
#include
#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 code TX_Addr[]={0x34,0x43,0x10,0x10,0x01};
uchar code TX_Addr1[]={0x33,0x42,0x11,0x11,0x21}; //++++++++
uchar code TX_Addr2[]={0xb1,0x42,0x11,0x11,0x21};
uchar code TX_Addr3[]={0xb2,0x42,0x11,0x11,0x21};
uchar code TX_Addr4[]={0xb3,0x42,0x11,0x11,0x21};
uchar code 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
for (i=0;i
}
void _delay_ms(uint x)
{
uint i,j;
for (j=0;j
for (i=0;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)
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
{
if(byte&0x80)//如果数据最高位是1//当访问多字节寄存器时首先要读/写的是最低字节的高位?
MOSI=1;//向NRF24L01写1
else //否则写0
MOSI=0;
byte
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
{
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
{
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
nRF24L01_Set_TX_Mode(&Display_Digit[i]);
_delay_ms(100);
while(Check_Ack());
}
}
}
}
无线温度接收模块程序代码:
#include
#include
#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 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 code TX_Addr[]={0x34,0x43,0x10,0x10,0x01};
uchar code TX_Addr1[]={0x33,0x42,0x11,0x11,0x21}; //++++++++
uchar code TX_Addr2[]={0xb1};
uchar code TX_Addr3[]={0xb2};
uchar code TX_Addr4[]={0xb3};
uchar code TX_Addr5[]={0xb4};
uchar code dizhi[]={0x01,0x02,0x04,0x08,0x10,0x20}; //+++++++
uchar code shuma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92};//++++++
uchar code TX_Buffer[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar RX_Buffer[RX_DATA_WITDH];
uchar code Display_LINE0[]={"ID:110709 06/14 "};
uchar Display_LINE1[]={" TEMP: "};
uchar counter=0;
uchar xuan=0;
void _delay_us(uint x)
{
uint i,j;
for (j=0;j
for (i=0;i
}
void _delay_ms(uint x)
{
uint i,j;
for (j=0;j
for (i=0;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
{
if(byte&0x80)
MOSI=1;
else
byte
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
{
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;
reg_value=SPI_RW(reg);
for(i=0;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_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无线模块进行传输,在接收端通过液晶显示模块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接收模块方案框图
图1发送模块方案框图
图2接收模块方案框图
2. 基本原理
无线温度监控系统由发送模块和接收两大模块组成,其原理如下:
发送模块:温度传感器DS18B20将采集到的信号送到单片机控制模块存储,通过按键使控制模块将信号处理然后送到无线模块NRF24L01经行数据传输,数码管显示出所选择的通信信道。
接收模块:通过按键使无线模块NRF24L01接收到发送模块的数据,把数据送到51控制模块,控制模块将数据处理后通过LCD1602把温度显示出来,数码管显示出所选择的通信信道。
系统组成方框图如图3无线温度监测器系统组成方框图所示:
图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
进行通信。 的CONFIG 寄存器共同决定NRF24L01的状态。 CE(P1.5):芯片的模式控制线。在CSN 为低的情况下,CE 协同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读取温度程序流程图所示
图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
#include
#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 code TX_Addr[]={0x34,0x43,0x10,0x10,0x01};
uchar code TX_Addr1[]={0x33,0x42,0x11,0x11,0x21}; //++++++++
uchar code TX_Addr2[]={0xb1,0x42,0x11,0x11,0x21};
uchar code TX_Addr3[]={0xb2,0x42,0x11,0x11,0x21};
uchar code TX_Addr4[]={0xb3,0x42,0x11,0x11,0x21};
uchar code 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
for (i=0;i
}
void _delay_ms(uint x)
{
uint i,j;
for (j=0;j
for (i=0;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)
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
{
if(byte&0x80)//如果数据最高位是1//当访问多字节寄存器时首先要读/写的是最低字节的高位?
MOSI=1;//向NRF24L01写1
else //否则写0
MOSI=0;
byte
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
{
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
{
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
nRF24L01_Set_TX_Mode(&Display_Digit[i]);
_delay_ms(100);
while(Check_Ack());
}
}
}
}
无线温度接收模块程序代码:
#include
#include
#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 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 code TX_Addr[]={0x34,0x43,0x10,0x10,0x01};
uchar code TX_Addr1[]={0x33,0x42,0x11,0x11,0x21}; //++++++++
uchar code TX_Addr2[]={0xb1};
uchar code TX_Addr3[]={0xb2};
uchar code TX_Addr4[]={0xb3};
uchar code TX_Addr5[]={0xb4};
uchar code dizhi[]={0x01,0x02,0x04,0x08,0x10,0x20}; //+++++++
uchar code shuma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92};//++++++
uchar code TX_Buffer[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar RX_Buffer[RX_DATA_WITDH];
uchar code Display_LINE0[]={"ID:110709 06/14 "};
uchar Display_LINE1[]={" TEMP: "};
uchar counter=0;
uchar xuan=0;
void _delay_us(uint x)
{
uint i,j;
for (j=0;j
for (i=0;i
}
void _delay_ms(uint x)
{
uint i,j;
for (j=0;j
for (i=0;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
{
if(byte&0x80)
MOSI=1;
else
byte
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
{
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;
reg_value=SPI_RW(reg);
for(i=0;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_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);
}
}