DTH11温湿度传感器使用(stm32)
作者:互联网
可以参考这个博客:
https://blog.csdn.net/qq_27508477/article/details/83661672
但是由于stm32f103很难得到1us的时钟,而且使用HAL库没有直接的寄存器操作,所以需要一定的修改,这里主要讲如何修改。
DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度20-90%RH, 温度0~50℃。
DHT11利用单总线协议,因此有严格的时序。
主机先要发送一个至少18ms的低电平,在这个过程中,DHT11内部完成AD转换等操作,当主机拉高后,有20-40us时间,这个时间用于主机做输入输出切换,当主机释放总线控制权(此时主机为输入状态,总线被上拉电阻拉高),DHT11尝试将总线拉低,成功拉低后就开始准备发送数据了,再拉高一次就开始传输数据了。
具体传输过程如下,其中数据0和数据1依靠高电平持续时长来判断。
一个bit数据发送完之后会把总线拉低,反过来说应该是拉低一段时间后开始采样。
数据0表示方法:
数据1表示方法:
使用stm32cubeMX新建工程
使用的是stm32f103c8,新建工程如下:
这是在一个系统中建立的过程,包括一个30us定时器中断,调试用的uart,以及几个io口。在DTH11的使用中,实际上不需要这些io口,所以这一步的关键在于读者自省摸索如何使用该工具。
stm32cubeMX可以可视化配置管脚,之后生成keil工程,用户只需要在该工程的指定位置添加自己的代码就行了。
生成代码可以参考此链接:
https://blog.csdn.net/qq_45467083/article/details/103525751
修改HAL_Delay单位为10us
修改源代码
这里主要是重写以下几个宏定义
//这个是源代码中的,修改后不需要
#define DHT11_IO_IN() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=0<<9*2;} //PE9输入模式
#define DHT11_IO_OUT() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=1<<9*2;} //PE9输出模式
//#define DHT11_DQ_OUT PEout(9) //数据端口 PE9
#define DHT11_DQ_IN() PEin(9) //数据端口 PE9
此外还要将原来的1us级延时改为10us级延时。
修改后的代码如下:
dth11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "sys.h"
int DHT11_DQ_IN(void);
void DHT11_DQ_OUT(int state);
void DHT11_IO_OUT(void);
void DHT11_IO_IN(void);
unsigned char DHT11_Init(void);//初始化DHT11
unsigned char DHT11_Read_Data(unsigned char *temp,unsigned char *humi);//读取温湿度
unsigned char DHT11_Read_Byte(void);//读出一个字节
unsigned char DHT11_Read_Bit(void);//读出一个位
unsigned char DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11
#endif
dth11.c
#include "dht11.h"
#define DTH11_GPIO GPIOB
#define DTH11_PIN GPIO_PIN_6
//IO方向设置
//#define DHT11_IO_IN() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=0<<9*2;} //PE9输入模式
//#define DHT11_IO_OUT() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=1<<9*2;} //PE9输出模式
void DHT11_IO_IN(void)//设置GPIOB_6为输入
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = DTH11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(DTH11_GPIO, &GPIO_InitStruct);
}
void DHT11_IO_OUT(void)//设置GPIOB_6为输出
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = DTH11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DTH11_GPIO, &GPIO_InitStruct);
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
unsigned char DHT11_Init(void)
{
// DHT11_IO_OUT();
// for(int i=0;i<100;i++){
// DHT11_DQ_OUT(i%2);HAL_Delay(10000);
// }
// DHT11_IO_IN();
// for(int i=0;i<500;i++){
// printf("%d ",DHT11_DQ_IN());HAL_Delay(10000);
// }
DHT11_IO_OUT();
DHT11_Rst();
return DHT11_Check();
}
IO操作函数
//#define DHT11_DQ_OUT PEout(9) //数据端口 PE9
void DHT11_DQ_OUT(int state)
{
if(state == 1){
HAL_GPIO_WritePin(DTH11_GPIO, DTH11_PIN, GPIO_PIN_SET);
}else{
HAL_GPIO_WritePin(DTH11_GPIO, DTH11_PIN, GPIO_PIN_RESET);
}
}
//#define DHT11_DQ_IN() PEin(9) //数据端口 PE9
int DHT11_DQ_IN(void)//设置GPIOB_7输出
{
return ((DTH11_GPIO->IDR & DTH11_PIN)!= (uint32_t)GPIO_PIN_RESET)?GPIO_PIN_SET:GPIO_PIN_RESET;
}
//复位DHT11
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT
DHT11_DQ_OUT(0); //拉低DQ
HAL_Delay(2000); //拉低至少18ms
DHT11_DQ_OUT(1); //DQ=1
HAL_Delay(3); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
unsigned char DHT11_Check(void)
{
unsigned char retry=0;
DHT11_IO_IN();//SET INPUT
while (DHT11_DQ_IN()&&retry<10)//DHT11会拉低40~80us
{
retry++;
HAL_Delay(1);
};
if(retry>=10){
printf("#1");
return 1;
}else retry=0;
while (!DHT11_DQ_IN()&&retry<10)//DHT11拉低后会再次拉高40~80us
{
retry++;
HAL_Delay(1);
};
if(retry>=10){
printf("#2");
return 1;
}
return 0;
}
//从DHT11读取一个位
//返回值:1/0
unsigned char DHT11_Read_Bit(void)
{
unsigned char retry=0;
while(DHT11_DQ_IN()&&retry<10)//等待变为低电平
{
retry++;
HAL_Delay(1);
}
retry=0;
while(!DHT11_DQ_IN()&&retry<10)//等待变高电平
{
retry++;
HAL_Delay(1);
}
HAL_Delay(4);//等待40us
if(DHT11_DQ_IN())return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
unsigned char DHT11_Read_Byte(void)
{
uint8_t i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
unsigned char DHT11_Read_Data(unsigned char *temp,unsigned char *humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}else{
printf("wrong read: buf:%2d buf:%2d\r\n",buf[0],buf[2]);
return 2;
}
}else return 1;
return 0;
}
测试代码:
//初始化
if(DHT11_Init()!=0){//初始化DHT11
printf("dht11 init wrong!\n\r\n");
}else{
printf("dht11 init ok!\n\r\n");
}
while (1)
{
unsigned char temperature=0, humidity=0;
if(DHT11_Read_Data(&temperature,&humidity)!=0){
//读取温湿度值出错
}
HAL_Delay(150000);
printf("temperature:%2d humidity:%2d\r\n",temperature,humidity);
}
标签:char,DTH11,温湿度,void,unsigned,stm32,IO,DQ,DHT11 来源: https://blog.51cto.com/u_15262460/2882982