Pin |
名称 |
注释 |
1 |
VDD |
供电 3-5.5VDC |
2 |
DATA |
串行数据,单总线 |
3 |
NC |
空脚,请悬空 |
4 |
GND |
接地,电源负极 |
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
通讯过程如下:
1、用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。过程如图1所示:
图1
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。如图2所示:
数字0信号表示方法如图3所示:
数字1信号表示方法.如图4所示:
图4
接下去得讲述下STM32实现的DHT11驱动。
首先,得建立个基于库开发的STM32的使用工程,这里就不详细说明。
由于单总线的时序要求,需要写两个精确的延时函数:Delay_nus()和Delay_nms()。代码如下(使用如下代码的前提是你已将系统时钟配置为9MHz,72MHz的8分频):
/********************************************************
函数:Delay_us()
描述:延时n个us
参数:无
返回:无
********************************************************/
void Delay_us(u32 nus)
{
SysTick->LOAD=nus*9; //时间加载
SysTick->CTRL|=0x01; //开始倒数
while(!(SysTick->CTRL&(1<<16)));//等待时间到达
SysTick->CTRL=0X00000000; //关闭计数器
SysTick->VAL=0X00000000; //清空计数器
}
/********************************************************
函数:Delay_ms()
描述:延时n个毫秒
参数:无
返回:无
********************************************************/
void Delay_ms(u16 nms)
{
SysTick->LOAD=(u32)nms*9000; //给重装载寄存器赋值,9000时,将产生1ms的时基
SysTick->CTRL|=0x01; //开始倒数
while(!(SysTick->CTRL&(1<<16))); //等待时间到达
SysTick->CTRL=0X00000000; //关闭计数器
SysTick->VAL=0X00000000; //清空计数器
}
接着新建DHT11.c 和DHT11.h两个文件,并添加到工程中。
DHT11.h文件主要是定义DHT11数据线的引脚定义及其一些引脚控制宏命令。代码如下:
#include "stm32f10x.h"
#include "BSP.h"
#include
//定义DHT11单总线的数据引脚,在这里宏定义,给移植带来了方便性
#define DHT11_PIN GPIO_Pin_5
#define DHT11_PORT GPIOA
//读取引脚输入的数据
#define DHT11_DATA_IN() GPIO_ReadInputDataBit(GPIOA,DHT11_PIN)
//控制引脚的高低电平
#define DHT11_DATA_OUT(a) if (a) \
GPIO_SetBits(DHT11_PORT,DHT11_PIN);\
else \
GPIO_ResetBits(DHT11_PORT,DHT11_PIN)
void DHT11Read(u8 RH , u8 RL , u8 TH , u8 TL);
#endif
DHT11.c这个文件主要实现如下几个函数:
void DHT11_GPIO_IN(void) ——设置GPIO口为输入模式
void DHT11_GPIO_OUT(void) ——设置GPIO口为输出状态
void DHT11WriteStart(void) ——发起开始信号
u8 DHT11ReadByte(void) ——从DHT11中读取一位数据
void DHT11Read(u8 RH , u8 RL , u8 TH , u8 TL) ——采样当前温湿度值
#include "DHT11.h"
/********************************************************
函数:DHT11_GPIO_IN
描述:设置GPIO口为输入状态
参数:无
返回:无
********************************************************/
void DHT11_GPIO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置浮空输入
GPIO_Init(DHT11_PORT,&GPIO_InitStructure);
}
/********************************************************
函数:DHT11_GPIO_OUT
描述:设置GPIO口为输出状态
参数:无
返回:无
********************************************************/
void DHT11_GPIO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置开漏输出
GPIO_Init(DHT11_PORT,&GPIO_InitStructure);
}
/********************************************************
函数:DHT11WriteStart
描述:发起开始信号
参数:无
返回:无
********************************************************/
void DHT11WriteStart(void)
{
DHT11_GPIO_OUT(); //设置io为输出模式
DHT11_DATA_OUT(1); //拉高
DHT11_DATA_OUT(0); //拉低
Delay_ms(18); //主机拉低总线必须大于18ms
DHT11_DATA_OUT(1); //拉高
Delay_us(30); //主机发送开始信号结束后延时等待20-40us
DHT11_GPIO_IN(); //启动信号开始后,为如数据将io设置设置为输入模式
}
/********************************************************
函数:DHT11ReadByte
描述:从DHT11中读取一位数据
参数:无
返回:返回读出来的数据
********************************************************/
u8 DHT11ReadByte(void)
{
u8 temp=0,i;
for(i=0;i<8;i++) //读取8位数据
{
while(DHT11_DATA_IN()==0);//等待变高电平
/*DHT11 以26us~28us的高电平表示“0”,以70us的高电平表示“1”
每一bit数据都以50us低电平时隙开始,当检测到60us后的电平区别状态*/
Delay_us(60);
if(DHT11_DATA_IN()==1) //60us后还是高电平则是“1”
{
while(DHT11_DATA_IN()==1);
temp|=(u8)(0x01<<(7-i));
}
else //否则是“0”
{
temp&=(u8)~(0x01<<(7-i));
}
}
return temp;
}
/********************************************************
函数:DHT11Read
描述:采样当前温湿度值
参数:
RH:湿度值的整数部分
RL: 湿度值的小数部分
TH: 温度值的整数部分
TL: 温度值的小数部分
返回:
********************************************************/
void DHT11Read(u8 RH , u8 RL , u8 TH , u8 TL)
{
u8 sum = 0;
DHT11WriteStart(); //发起开始信号
if(DHT11_DATA_IN()==0)
{
while(DHT11_DATA_IN()==0);
while(DHT11_DATA_IN()==1);
RH = DHT11ReadByte(); //湿度高8位
RL = DHT11ReadByte(); //湿度低8位
TH = DHT11ReadByte(); //温度高8位
TL = DHT11ReadByte(); //温度低8位
sum = DHT11ReadByte(); //校验和
DHT11_GPIO_OUT(); //采样结束后设置io口为输出,等待下一次开始信号
DHT11_DATA_OUT(1); //设置总线空闲状态为高电平
if(sum == RH+RL+TH+TL) //校验和与计算出的数据相等
{
printf("当前环境湿度为%d.%d﹪,当前环境温度为%d.%d℃\r\n",RH,RL,TH,TL);
}
else
{
printf("采样失败!!!\r\n");
}
}
}
上一篇:移植到STM32fl13野火开发板上遇到的问题
下一篇:基于USB2.0接口的生物阻抗分析仪的研制
推荐阅读最新更新时间:2024-03-16 15:14