DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。
节点通过采集 DHT11 的温湿度信息,实时发送到协调器。协调器通
过串口打印方式展示当前温湿度。
像前面传感器例程一样,先实现裸机驱动 DHT11,然后把裸机上成功驱动的传感器添加到协议栈代码上,并实现数据传输。
三个步骤:
一:在裸机上完成对 DHT11 的驱动
二:将程序添加到协议栈代码中
三:将数据打包并按指定的方式发送给指定设备
一:在裸机上完成对 DHT11 的驱动。
---------------------------------------
DHT11.h
#ifndef __DHT11_H__
#define __DHT11_H__
#define uchar unsigned char
extern void Delay_ms(unsigned int xms); //延时函数
extern void COM(void); // 温湿写入
extern void DHT11(void); //温湿传感启动
extern uchar temp[2];
extern uchar temp1[5];
extern uchar humidity[2];
extern uchar humidity1[9];
extern uchar shidu_shi,shidu_ge,wendu_shi,wendu_ge;
#endif
---------------------------------------
DHT11.C
#include
#include
#define uint unsigned int
#define uchar unsigned char
#define wenshi P0_6
//温湿度定义
uchar ucharFLAG,uchartemp;
uchar shidu_shi,shidu_ge,
wendu_shi,wendu_ge=4;
uchar ucharT_data_H, ucharT_data_L,
ucharRH_data_H, ucharRH_data_L,
ucharcheckdata;
uchar ucharT_data_H_temp, ucharT_data_L_temp,
ucharRH_data_H_temp, ucharRH_data_L_temp,
ucharcheckdata_temp;
uchar ucharcomdata;
uchar temp[2]={0,0};
//uchar temp1[5]="temp=";
uchar humidity[2]={0,0};
//uchar humidity1[9]="humidity=";
/****************************
延时函数
*****************************/
void Delay_us() //1 us延时
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
void Delay_10us() //10 us延时
{
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
}
void Delay_ms(uint Time)//n ms延时
{
unsigned char i;
while(Time--)
{
for(i=0;i<100;i++)
Delay_10us();
}
}
/***********************
温湿度传感
***********************/
void COM(void) // 温湿写入
{
uchar i;
for(i=0;i<8;i++)
{
ucharFLAG=2;
//如果高电平 或者uchatFLAG到达0 退出循环
while((!wenshi)&&ucharFLAG++);
Delay_10us();
Delay_10us();
Delay_10us();
uchartemp=0;
if(wenshi)// 如果P0_6是高电平,
uchartemp=1;
ucharFLAG=2;
//如果是高电平并且ucharFLAG++ 一直为真 直到255 当做延时
//ucharFLAG变成0 停止执行 但是wenshi没有变成0 说明没有响应
while((wenshi)&&ucharFLAG++);
if(ucharFLAG==1)
break;
ucharcomdata<<=1;
ucharcomdata|=uchartemp;
}
}
void DHT11(void) //温湿传感启动
{
wenshi=0;
Delay_ms(19); //>18MS
wenshi=1;
P0DIR &= ~0x40; //重新配置IO口方向 0100 0000
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
if(!wenshi)
{
ucharFLAG=2;
while((!wenshi)&&ucharFLAG++);
ucharFLAG=2;
while((wenshi)&&ucharFLAG++);
COM();//读湿度的高八位
ucharRH_data_H_temp=ucharcomdata;
COM();//读湿度的低八位
ucharRH_data_L_temp=ucharcomdata;
COM();//读温度的高八位
ucharT_data_H_temp=ucharcomdata;
COM();//读温度的低八位
ucharT_data_L_temp=ucharcomdata;
COM();
ucharcheckdata_temp=ucharcomdata;//校验和
wenshi=1;
uchartemp
(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);
if(uchartemp==ucharcheckdata_temp)
{
ucharRH_data_H=ucharRH_data_H_temp;//收集湿度
ucharRH_data_L=ucharRH_data_L_temp;
ucharT_data_H=ucharT_data_H_temp;//收集温度
ucharT_data_L=ucharT_data_L_temp;
ucharcheckdata=ucharcheckdata_temp;
}
wendu_shi=ucharT_data_H/10;
wendu_ge=ucharT_data_H%10;
shidu_shi=ucharRH_data_H/10;
shidu_ge=ucharRH_data_H%10;
}
else //没用成功读取,返回0
{
wendu_shi=0;
wendu_ge=0;
shidu_shi=0;
shidu_ge=0;
}
}
---------------------------------------
二:将程序添加到协议栈代码中
接下来我们需要做的工作就是移植到协议栈z-stack 上面,这个过程要注意的是要了解协议栈上的 IO 口用途和晶振工作频率。
通过点播方式发送到协调器,协调器通过串口发送到上位机,在串口调试助手上面显示。
这就实现了无线温度采集。
(使用点播的原因是终端设备有针对性地发
送数据给指定设备,不像广播和组播可能会造成数据冗余)
(1)、将裸机程序里面的 DHT11.c和DHT11.h 文件复制到SampleApp/Source 文件夹下。
(2)、在协议栈的 App 目录树下点击右键--Add--添加 DS18B20.C 文件
(3)、整个实验以点播为依托,实验也就是在点播例程的基础上完成,故
函数编程也是像以前一样。
==========================================
初始化串口(参考协议栈串口实验)
1、
SampleApp.c
#include "MT_UART.h" //串口头文件引用
2、
SampApp.c
SampApp_Init()
SampApp_TransID() = 0;
MT_UartInit();
3、
void MT_UartInit()
uartConfig.baudRate =MT_UART_DEFAULT_BAUDRATE;
uartConfig.flowControl = MT_UART_DEFAULT_OVERFLOW;
#define MT_UART_DEFAULT_BAUDRATE HAL_UART_BR_115200 //38400
#define MT_UART_DEFAULT_OVERFLOW FALSE //TRUE
4、
用 ZTOOL,串口 0。我们可以在 option——C/C++ 的 CompilerPreprocessor 里面看到,已经默认添加 ZTOOL_P1 预编译。
5、
void SampleApp_Init( uint8 task_id )
MT_UartInit();
MT_UartRegisterTaskID(task_id);//登记任务号
至此,就可以使用
HalUARTWrite(0, "Hello,world\n", 12); //(串口, 字符, 字符个数) 发送数据了。
==========================================
点播配置部分(参考网络通讯--点播)
1、
afAddrType_t SampleApp_Point_DstAddr;
//点对点通信定义
2、
void SampleApp_Init( uint8 task_id ) 里面,
对 SampleApp_Point_DstAddr 一些参数进行配置
---------------
SampleApp_Point_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//点播
SampleApp_Point_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Point_DstAddr.addr.shortAddr = 0x0000;//发给协调器
---------------
3、
在SampleApp.c中
发送点播函数
添加头文件声明 void SampleApp_SendPointMessage( void );
定义该函数
void SampleApp_SendPointMessage( void )
{
if ( AF_DataRequest( &SampleApp_Point_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_POINT_CLUSTERID,//点播传输编号
1,
(uint8*)&SampleAppPeriodicCounter,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
4、
之前定义过Point_To_Point_DstAddr。
在SampleApp.h中声明SAMPLEAPP_POINT_CLUSTERID
#define SAMPLEAPP_MAX_CLUSTERS 3 //2
#define SAMPLEAPP_PERIODIC_CLUSTERID 1
#define SAMPLEAPP_FLASH_CLUSTERID 2
#define SAMPLEAPP_POINT_CLUSTERID 3
5、
周期性点播发送数据
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
// Send the periodic message
//SampleApp_SendPeriodicMessage();//周期性发送函数
SampleApp_SendPointMessage();//此处替换成点播函数
6、
接收方面
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
switch ( pkt->clusterId )
case SAMPLEAPP_POINT_CLUSTERID:
HalUARTWrite(0,"I get data\n",11);//用于提示有数据
break;
7、
由于协调器不允许给自己点播,故周期性点播初始化时协调器不能初始化。
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( //(SampleApp_NwkState == DEV_ZB_COORD)|| //协调器不给自己点播
(SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
// Start sending the periodic message in a regular interval.
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
==========================================
温湿度传感器配置
1、在SampleApp.c上进行,
先包含
DHT11
.h
文件。
SampleApp.c
#include "DHT11.h" //温湿度专用
2、初始化传感器引脚P0.6
SampleApp.c
void SampleApp_Init( uint8 task_id )
MT_UartInit();//串口初始化
MT_UartRegisterTaskID(task_id);//登记任务号
//温湿度传感器初始化 P0.6
P0SEL &= 0xbf;
3、DHT11.c 文件需要修改一个地方。打开该文件,将原来的延时函数改成协议栈自带的延时函数,保证时序的正确性。同时要包含 #include"OnBoard.h" 。
/****************************
延时函数
*****************************/
void Delay_us() //1 us延时
{
//asm("nop");
//asm("nop");
//asm("nop");
//asm("nop");
//asm("nop");
MicroWait(1);
}
void Delay_10us() //10 us延时
{
MicroWait(10);
}
给 DHT11.c 里面的函数都添加声明:
/*******函数声明*********/
void Delay_us(void); //1 us延时
void Delay_10us(void); //10 us延时
void Delay_ms(uint Time);//n ms延时
void COM(void); // 温湿写入
void DHT11(void) ; //温湿传感启动
编译,会出现如下错误:
IAR CC2530的2个程序整合后,报错,而全部错误都是一个性质。
Error[Pa045]: function "" has no prototype
解决方法:
打开Options,如图所示
去掉 Require prototype选项,重新编译即可。
4、借用周期性点播函数, 5s 读取温度传感器 1 次,通过串口打印并点对点发送给协调器 。
SampleApp.c
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
// Send a message out - This event is generated by a timer
// (setup in SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
uint8 T[8]; //温度+提示符
DHT11(); //温度检测
T[0]=wendu_shi+48;
T[1]=wendu_ge+48;
T[2]=' ';
T[3]=shidu_shi+48;
T[4]=shidu_ge+48;
T[5]=' ';
T[6]=' ';
T[7]=' ';
/*******串口打印*********/
//HalUARTWrite(0,"temp=",5);
HalUARTWrite(0,T,2);
HalUARTWrite(0,"\n",1);
//HalUARTWrite(0,"humidity=",9);
HalUARTWrite(0,T+3,2);
HalUARTWrite(0,"\n",1);
SampleApp_SendPointMessage();//点播函数
5、将数据打包并按指定的方式发送给指定设备
上一个步骤,完成了 DHT11基于协议栈的驱动,接下来,实现数据发送和接收就可以了。
在 EndDevice 的
点播发送函数中将温度信息发送出去。
SampleApp.C
void SampleApp_SendPointMessage( void )
{
uint8 T_H[4];//温湿度
T_H[0]=wendu_shi+48;
T_H[1]=wendu_ge%10+48;
T_H[2]=shidu_shi+48;
T_H[3]=shidu_ge%10+48;
if ( AF_DataRequest( &Point_To_Point_DstAddr,
&SampleApp_epDesc,
SAMPLEAPP_POINT_CLUSTERID,
4,
T_H,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
7、
协调器接收
SampleApp.c
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
case SAMPLEAPP_POINT_CLUSTERID:
/***********温度打印***************/
HalUARTWrite(0,"Temp is:",8); //提示接收到数据
HalUARTWrite(0,&pkt->cmd.Data[0],2); //温度
HalUARTWrite(0,"\n",1); // 回车换行
/***************湿度打印****************/
HalUARTWrite(0,"Humidity is:",12); //提示接收到数据
HalUARTWrite(0,&pkt->cmd.Data[2],2); //湿度
HalUARTWrite(0,"\n",1); // 回车换行
break;
实验结果:
观察终端设备以及将协调器连接到电脑,观察从终端发来的信息。
以终端方式下载到开发板,当连接上协调器时,可以看到串口打印出温湿度传感器信息。