0.参考资料
- Amomcu CC2540资料 基础例程 DHT11
- 数字温湿度传感器DHT11 雁凌电子http://ylelectronic.taobao.com/ 说明书最新版
引脚
通信
串口,单线双向
一次通讯时间4ms左右
总体概览
用户MCU发送一次开始信号后——》DHT11从低功耗模式转换到高速模式
等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,
采集数据后转换到低速模式
开始信号
总线空闲状态为高电平
主机把总线拉低(大于18毫秒,保证DHT11能检测到)等待DHT11响应,
DHT11接收到主机的开始信号后,等待主机开始信号结束(主机拉高并延时等待),然后发送80us低电平响应信号.
主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,(如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常.)
主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
数据格式
数据分小数部分和整数部分
当前小数部分用于以后扩展,现读出为零.
一次完整的数据传输为40bit,高位先出。
数据格式:
8bit湿度整数数据+
8bit湿度小数数据+
8bi温度整数数据+
8bit温度小数数据+
8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”
所得结果的末8位。
数据传输
- 每一bit数据都以50us低电平时隙开始,
- 高电平的长短决定了数据位是0还是1.
- 0:26us~28us
- 1:70us
- 当最后一bit数据传送完毕后,DHT11拉低总线50us,
- 随后总线由上拉电阻拉高进入空闲状态。
代码
main.c
/****************************************************************************
* 文 件 名: main.c
* 作 者: Amo [ www.amoMcu.com 阿莫单片机]
* 修 订: 2014-04-08
* 版 本: 1.0
* 描 述: 将采集到的温湿度通过串口发送到串口调试助手上显示 115200 8N1
****************************************************************************/
#include <ioCC2540.h>
#include <string.h>
#include "UART.H"
#include "DHT11.H"
/****************************************************************************
* 程序入口函数
****************************************************************************/
void main(void)
{
uchar temp[3];
uchar humidity[3];
uchar strTemp[13]="Temperature:";
uchar strHumidity[10]="Humidity:";
Delay_ms(1000); //让设备稳定
InitUart(); //串口初始化
while(1)
{
memset(temp, 0, 3);
memset(humidity, 0, 3);
DHT11(); //获取温湿度
//将温湿度的转换成字符串
temp[0]=wendu_shi+0x30; //0011 0000 0的ascii码是48 = 16+32 = 0011 0000
temp[1]=wendu_ge+0x30;
humidity[0]=shidu_shi+0x30;
humidity[1]=shidu_ge+0x30;
//获得的温湿度通过串口输出到电脑显示
UartSendString(strTemp, 12);
UartSendString(temp, 2);
UartSendString(" ", 3);
UartSendString(strHumidity, 9);
UartSendString(humidity, 2);
UartSendString("\n", 1);
Delay_ms(1500); //延时,1.5S读取1次
}
}
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 <ioCC2540.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define DATA_PIN P0_0
//温湿度定义
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; //温湿度,8bit整数和8bit小数部分, 8bit校验和
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()的作用是指函数内部的参数翻译为汇编指令
其作用是在C语言环境下直接使用汇编指令执行
nop是一个空等待汇编指令
这个指令执行时,单片机是什么也不做,仅仅起一个时间延时作用。
(“nop”)执行的是一条空指令(单周期指令),占用时间是一个机器周期,晶振为xMhz。
于是,机器周期=12*1/x=yus。即一句asm(“nop”)延时了yus。
---------------------
作者:Mr_White01
来源:CSDN
原文:https://blog.csdn.net/Mr_White01/article/details/68488802
版权声明:本文为博主原创文章,转载请附上博文链接!
*/
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
void Delay_10us() //10 us延时
{
#if 0
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
#else
int i = 6;
while(i--);
#endif
}
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;
while((!DATA_PIN)&&ucharFLAG++); //等待一开始约50us的低电平
Delay_10us();
Delay_10us();
Delay_10us(); //26~28us的高电平表示0,70us的表示1,
uchartemp=0;
if(DATA_PIN)uchartemp=1; //如果过了30us,还是高电平,这位数据就是1;否则是0
//
ucharFLAG=2;
while((DATA_PIN)&&ucharFLAG++); //如果是1的话等这个高电平结束
if(ucharFLAG==1)break;
//
ucharcomdata<<=1;
ucharcomdata|=uchartemp; //这一位数据复制为uchartemp
}
}
void DHT11(void) //温湿传感启动
{
DATA_PIN=0;
Delay_ms(19); //主机拉低>18MS,表示发出开始信号
DATA_PIN=1; //主机拉高并等待DHT输出低电平响应
P0DIR &= ~0x01; //重新配置IO口方向,允许DHT控制电平
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
if(!DATA_PIN) //DHT输出低电平,表示其响应了主机的开始信号
{
ucharFLAG=2;
while((!DATA_PIN)&&ucharFLAG++); //等待DHT的低电平响应(约80us)结束,
ucharFLAG=2;
while((DATA_PIN)&&ucharFLAG++); //等待DHT的拉高(约80us)结束,
COM();
ucharRH_data_H_temp=ucharcomdata; //8bit湿度整数数据
COM();
ucharRH_data_L_temp=ucharcomdata; //8bit湿度小数数据
COM();
ucharT_data_H_temp=ucharcomdata; //8bi温度整数数据
COM();
ucharT_data_L_temp=ucharcomdata; //8bit温度小数数据
COM();
ucharcheckdata_temp=ucharcomdata; //8bit校验和
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 |= 0x01; //IO口需要重新配置
}