DHT11温湿度传感器数据采集教程(附STM32代码)
一、所需准备
硬件:DHT11模块(奥松电子)、DHT11资料手册、串口模块、STM32F103C8T6最小系统板、杜邦线
软件:Keil 5 、串口助手
DHT11资料手册-某盘链接
https://pan.baidu.com/s/1vC3wLzLvLqBAO0dkiWCYIw 提取码:pppp
二、引脚说明
模块工作流程可以简化为:①MCU唤醒DHT11 ,让DHT11开始工作。 ②DHT11传输温度和湿度数据MCU,MCU接收DHT11的数据。
注:DATA线决定数据何时发送何时接收,用另一种表达,DATA线控制数据的收发
三、代码
1.宏定义
本文DATA连接的是PB3
/*我这里DATA连接的是PB3*/
#define DHT11_DATA_H GPIO_SetBits(GPIOB, GPIO_Pin_3) //PB3输出高电平
#define DHT11_DATA_L GPIO_ResetBits(GPIOB,GPIO_Pin_3) //PB3输出低电平
#define DHT11_IN GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_3) //PB3输入
2.管脚配置/初始化
首先我们从资料手册可以得知设备通过漏极开路连至该数据线,且单总线通常要求外接了一个约5.1kΩ的上拉电阻,因此DATA线的空闲电平为高电平。
所以我们将与DATA线所连接的引脚配置为通用开漏输出。此时可能有人有疑问:配置成输出模式如何接收DHT11的数据?
这时我们就要用到GPIO口的一个特性:配置成输出模式的时候,输入功能正常使用。配置成输入模式的时候,输出功能无法使用。
产品手册中还写到上电后需要等待1秒以上同时保持高电平。
注:STM32F103C8T6想要使用PB3需要调整JTAG/SWD复用功能重映射,需要设置成关闭JTAG-DP,启用SW-DP。
void Dht11_Init(void)
{
//1、打开时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);//打开GPIOB的时钟
/*想要使用PB3需要调整JTAG/SWD复用功能重映射,关闭JTAG-DP,启用SW-DP*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//打开AFIO时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭JTAG-DP,开启SW-DP
//2、IO初始化,配置管脚
GPIO_InitTypeDef GPIO_InitStruct={0};
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//配置为通用推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;//配置管脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//IO速度为50Mhz
GPIO_Init(GPIOB,&GPIO_InitStruct);
delay_ms(1000);//DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令
DHT11_DATA_H;//拉高,释放总线
}
3.起始信号
从产品手册,可知要先DATA线先拉低18ms以上再拉高
void Dht11_Start(void)
{
DHT11_DATA_L;
delay_ms(25);
DHT11_DATA_H;
}
4.响应信号
由产品手册可知,DHT11接收到外部信号后会输出一个低电平,再输出一个高电平。
u8 Dht11_Ack(void)
{
while(DHT11_IN); // 等待DHT11发送响应号
while(!DHT11_IN);//等待80us低电平结束
while(DHT11_IN);//等待80us高电平结束
return 0;
}
5.接收数据
我们判断数据是 " 1 " 还是 " 0" 的方法就是区分高电平的时间,所以我们可以在延时35us后查看GPIO口电平状况,若还是高电平则是数据 " 1 ",反之则为数据" 0 "。
我们可以多种接收数据的方法,比如先接收32位数据再接收剩下8位数据,但为了取数据简便,我选择一次接收8位数据的方法,分5次接收。
u8 Dht11_Rec(void)
{
u8 data=0;
for(u8 i= 0;i < 8;i++)
{
while(!DHT11_IN);//等待50us低电平结束
delay_us(35); //延时35us查看是否是高电平
data <<=1;
if(DHT11_IN ==1) //判断数据是 1 还是 0
{
data |=1;
}
while(DHT11_IN);//等待高电平结束,准备接收下一位数据
}
return data;
}
6.整合
由产品手册可知,依次出的是湿度整数、湿度小数、温度整数、温度小数、校验位。
为了方便我们设置一个数组来接收数据。
u8 Dht11_Integrate(float *temp,float *humi)
{
u8 data[5]; //设置一个数组用来接收数据,也可以设置五个不同的变量用于接收
Dht11_Start(); //发送起始信号
Dht11_Ack(); //等待DHT11应答
data[0] = Dht11_Rec();//湿度整数
data[1] = Dht11_Rec();//湿度小数
data[2] = Dht11_Rec();//温度整数
data[3] = Dht11_Rec();//温度小数
data[4] = Dht11_Rec();//校验位
if( data[4] == data[0]+data[1]+data[2]+data[3] ) //校验数据是否正确
{
*temp=data[2] + data[3] /10.0; //温度数据
*hu=data[0] +data[1] /10.0 ; // 湿度数据
return 0;
}
return 1; //若不正确返回 1
}
最后我们可以使用串口助手或显示屏将得到的温湿度数据显示出来,串口部分代码和主函数部分代码就省略了。
注:上述代码只适用于测试零上温度。
效果图如下:
作者:芝士苦瓜汽水