CC2530与DHT11温湿度传感器的连接和工作原理
DHT11是一款有已校准数字信号输出的温湿度传感器。
其精度湿度±5%RH,温度±2℃,量程湿度5~95%RH,温度-20~+60℃。
电路图
DHT11一次通信时序(开始发送数据流程)
1、用户主机(单片机)发送一次开始信号后,DHT11从低功耗模式转换到高速模式。
2、到主机开始信号结束后,DHT11发送响应信号。
3、DHT11并送出40bit(5个字节)的数据,并触发一次信号采集,用户读取部分数据。
起始信号波形
·总线空闲状态为高电平,主机把中线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,然后拉高20~40us后等待DH11的应答。
·DHT11接收到主机的开始信号后,等待主机开始信号结束,首先将总线拉低约80us,然后再拉高80us作为应答信号。
·主机发送开始信号结束后,延时等待20~40us后,读取DHT11的响应信号。
·主机发送开始信号后。可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。
数据信号波形
数据位‘0’和‘1’都是从低电平开始,根据高电平的长度来区分:26~28us的高电平为数据‘0’,70us的高电平为数据‘1’。
CC2530如何读取数据
1、DHT11之间的通讯和同步,采用单总线数据格式
2、一次通讯时间4ms左右
3、数据分小数部分和整数部分,当前小数部分用于以后扩展,现在读出为零。
4、一次完整的数据传输为40bit,高位先出。
数据格式
40bit数据=8位湿度整数+8位湿度小数+8位温度整数+8位温度小数+8位校验
校验和:8位湿度整数数据+8位湿度小数数据+8位温度整数数据+8位温度小数数据,所得结果的末八位
代码详解
/****************************************************************************
* 文 件 名: DHT11.c
* 作 者: Daniel Peng
* 修 订: 2022-5-10
* 版 本: 1.0
* 描 述: 温湿度传感器驱动
****************************************************************************/
#include <ioCC2530.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define DATA_PIN P0_4
//温湿度定义
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;
//延时函数
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++)
{
while(!DATA_PIN); //循环耗时完低电平时间,直到高电平
Delay_10us();
Delay_10us();
Delay_10us(); //由于数据0的高电平持续时间为26~28us,数据1高电平持续时间是70us,在30us后,可根据处于高低电平区分数据1或0
uchartemp=0; //设字符为0
if(DATA_PIN) //如果是高电平,则设字符为1
uchartemp=1;
while(DATA_PIN); //若是高电平耗时完高电平的时间,若是低电平直接略过
ucharcomdata<<=1; //用ucharcomdata来依次存取0或1,将其左移一位
ucharcomdata|=uchartemp; //然后通过与读取到的uchartemp值或等于来存入当前位,八次循环后,8位就存取了拼成一个字节
}
}
void DHT11(void) //温湿传感启动
{
P0DIR |= 0x10;
DATA_PIN=0; //起始信号,主机拉低
Delay_ms(19); //>18MS
DATA_PIN=1; //拉高
P0DIR &= ~0x10; //重新配置IO口方向输入
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us(); //主机拉高20~40ms
if(!DATA_PIN) //判断从机DHT11是否低电平应答
{
while(!DATA_PIN); //DHT11响应,拉低持续80us,等待80us耗尽
while(DATA_PIN); //耗尽后DHT拉高80us,等待耗尽
COM(); //5个字节,5次com接收一个字节8位,
ucharRH_data_H_temp=ucharcomdata; //存入临时变量,湿度高位ucharRH_data_H_temp
COM();
ucharRH_data_L_temp=ucharcomdata; //存入临时变量,湿度低位ucharRH_data_L_temp
COM();
ucharT_data_H_temp=ucharcomdata; //存入临时变量,温度高位ucharT_data_H_temp
COM();
ucharT_data_L_temp=ucharcomdata; //存入临时变量,温度低位 ucharT_data_L_temp
COM();
ucharcheckdata_temp=ucharcomdata; //存入临时变量,校验位 ucharT_data_L_temp
DATA_PIN=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;
}
P0DIR |= 0x10; //IO口需要重新配置
}