STM32F103c8t6驱动DHT11温湿度在串口上打印温湿度(其它f103系列都可以用,直接移植这个库,修改下引脚就行)STM32驱动DHT11的库,可以直接移植

一、前言

在物联网和嵌入式系统开发中,温湿度监测是常见的基础功能需求。本文将详细介绍如何使用STM32F103c8t6单片机驱动DHT11数字温湿度传感器,并提供完整的代码解析,源码每条都进行了注释。资源链接包含了整个代码工程和DHT11的数据手册,需要自行下载


二、DHT11传感器简介

2.1 基本特性

  • 单总线数字信号输出

  • 湿度测量范围:20-90%RH(±5%RH)

  • 温度测量范围:0-50℃(±2℃)

  • 供电电压:3.3-5.5V

  • 典型功耗:0.5mA(测量时)

2.2 数据格式

DHT11每次发送40位数据(5字节),格式为:
湿度整数(8bit) 湿度小数(8bit) 温度整数(8bit) 温度小数(8bit) 校验和(8bit)
注:DHT11小数部分固定为0

2.3 驱动原理

2.3.1. 初始化准备

  • 硬件连接
    DHT11的DATA引脚通过4.7K上拉电阻接MCU的GPIO(如PA0),确保总线空闲时为高电平。

  • 上电等待
    DHT11上电后需等待至少2秒完成初始化,期间MCU需保持总线空闲(高电平)。


2.3.2. 发送起始信号

  • 拉低总线
    将GPIO配置为推挽输出模式,输出低电平持续 18~30ms(代码中为20ms),通知DHT11开始通信。

  • 释放总线
    切换GPIO为浮空输入模式(开漏模式更安全),释放总线。此时总线由外部上拉电阻拉高。

  • 等待应答
    DHT11会在总线释放后 80μs内拉低总线作为应答信号,随后再拉高 80μs 表示准备发送数据。
    代码关键点

    if (!GPIO_ReadInputDataBit(...)) {
        while (!GPIO_ReadInputDataBit(...)); // 等待低电平应答结束
        while (GPIO_ReadInputDataBit(...));  // 等待高电平结束
        return 1; // 应答成功
    }


2.3.3. 数据位读取

  • 数据格式
    DHT11发送40位数据(5字节),每位数据以 50~58μs低电平起始,后接不同时长的高电平:

    • 逻辑0:高电平持续 23~27μs

    • 逻辑1:高电平持续 68~74μs

  • 读取策略

    1. 检测到低电平后,等待 28μs(代码中delay_us(28)),此时若总线仍为高电平则为1,否则为0。

    2. 循环读取8次组成一个字节。
      代码关键点

    delay_us(28); // 关键采样点
    if (GPIO_ReadInputDataBit(...)) temp |= 0x01; // 判断逻辑1

    复制

    delay_us(28); // 关键采样点
    if (GPIO_ReadInputDataBit(...)) temp |= 0x01; // 判断逻辑1

2.3.4. 数据校验与解析

  • 数据组成
    40位数据分为:

    • 湿度整数(8bit)、湿度小数(8bit,DHT11固定为0)

    • 温度整数(8bit)、温度小数(8bit,DHT11固定为0)

    • 校验和(8bit,前四字节和的最低8位)

  • 校验逻辑
    校验和需满足:

    复制

    (buffer[0] + buffer[1] + buffer[2] + buffer[3]) == buffer[4]

三、硬件连接

3.1 接线方式

头文件直接宏定义了引脚,方便用户修改引脚

DHT11引脚STM32引脚
VCC3.3V/5V
DATAPA6
GNDGND

这个模块已经画了上拉电阻

库的DHT11.c源码

#include "DHT11.h"
#include "delay.h"

/**
  * @函数  DHT11_GPIO初始化函数
  * @参数  Mode:指定输入或输出模式
  * @返回值  None
  */
void DHT_GPIO_Init(GPIOMode_TypeDef Mode)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(DHT_RCC_PORT,ENABLE);  //打开对应引脚时钟
	
	GPIO_SetBits(DHT_GPIO_PORT,DHT_GPIO_PIN);
	
	GPIO_InitStructure.GPIO_Mode = Mode;  //通过参数形式来控制GPIO的模式
	GPIO_InitStructure.GPIO_Pin = DHT_GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(DHT_GPIO_PORT,&GPIO_InitStructure);
}

/**
  * @函数  DHT11模块起始信号函数
  * @参数  None
  * @返回值 1或0,标志起动信号成功与否
  */
uint8_t DHT_Start(void)
{
	DHT_GPIO_Init(GPIO_Mode_Out_PP);							//推挽输出模式
	
	GPIO_ResetBits(DHT_GPIO_PORT,DHT_GPIO_PIN);		//主机控制单总线输出20ms低电平
	delay_ms(20);
	GPIO_SetBits(DHT_GPIO_PORT,DHT_GPIO_PIN);       //主机输出高电平后主机释放总线
	
	DHT_GPIO_Init(GPIO_Mode_IN_FLOATING);					//输出高电平后主机释放总线,配置位浮空输入模式
	delay_us(20);                                           //从机控制总线
	
	if(!GPIO_ReadInputDataBit(DHT_GPIO_PORT,DHT_GPIO_PIN))   //判断从机是否进入应答模式
	{
		while(!GPIO_ReadInputDataBit(DHT_GPIO_PORT,DHT_GPIO_PIN));   //while循环等待从机低电平应答  大概低电平时间持续80us(具体看数据手册)
		while(GPIO_ReadInputDataBit(DHT_GPIO_PORT,DHT_GPIO_PIN));    //while循环等待从机高电平应答   大概高电平时间87us(具体看手册)
		return 1;    //返回1表示应答成功
	}
	return 0;   //返回0表示应答失败
}

/**
  * @函数   接收DHT11发送来8位的数据
  * @参数  None
  * @返回值 返回接收到的8位数据
  数据手册:数据位的传输:数据位为“0”时,DHT11先输出50~58μs的低电平随后输出23~27μs的高电平;数据位
  为“1”时,DHT11首先输出50~58μs的低电平随后输出68~74μs的高电平。
  判断数据位为1或0的方法:先whlie等待高电平时间结束,然后延时28us,即28us后再读取读取总线引脚,若还为高电平,则数据为位1,否则为0
  */
uint8_t DHT_Get_Byte_Data(void)
{
	int i = 0; 
	uint8_t temp;  //创建个变量用于结束从机发送的数据位
	for(i = 0; i < 8; i++)  //循环8次,每次接收一个数据为,8次为1个字节
	{
		temp <<= 1;   //变量先左移1位腾出最低位用于判断单总线的数据位的电平信号
		while(!GPIO_ReadInputDataBit(DHT_GPIO_PORT,DHT_GPIO_PIN));  //这里while等待数据位的等待高电平时间结束
		delay_us(28);  //延时28us  数据位为“0”时,DHT11先输出50~58μs的低电平随后输出23~27μs的高电平。等待数据为0的高电平时间结束
		GPIO_ReadInputDataBit(DHT_GPIO_PORT,DHT_GPIO_PIN) ? (temp |= 0x01) : (temp &= ~0x01);  //读取总线引脚的电平信号,若为高电平,则变量最低位为1,否则为0
		while(GPIO_ReadInputDataBit(DHT_GPIO_PORT,DHT_GPIO_PIN));  //while循环 表示一次数据位的读取结束
	} 
	return temp;  //返回1个字节,即8个数据位
}

/**
  * @函数  获取DHT11的温度湿度数据
  * @参数  buffer[]:需要传入一个存储数据的数组
  * @返回值 返回数据校验是否正确 1:正确 0:失败
  */
uint8_t DHT_Get_Temp_Humi_Data(uint8_t buffer[])
{
	if(DHT_Start())  //if判断DHT11从机是否应答完毕
	{
		buffer[0] = DHT_Get_Byte_Data();  //读取温度的整数放入数组第一个元素
		buffer[1] = DHT_Get_Byte_Data();  //读取温度的小数放入数组第二个元素
		buffer[2] = DHT_Get_Byte_Data();  //读取湿度的整数放入数组第三个元素
		buffer[3] = DHT_Get_Byte_Data();  //读取温度的小数放入数组第四个元素
		buffer[4] = DHT_Get_Byte_Data();  //读取的校验数据放入数组的第五个元素,用来检测数据是否读取正确
	}
	return (buffer[0]+buffer[1]+buffer[2]+buffer[3] == buffer[4]) ? 1 : 0;   //校验数据是否传输正确
}

头文件DHT11.h源码

#ifndef __DHT11_H
#define __DHT11_H

#include <stm32f10x.h>

//温湿度引脚在这里改
//这里通过宏定义,以方便用户修改引脚
#define DHT_GPIO_PORT		GPIOA
#define DHT_GPIO_PIN		GPIO_Pin_6
#define DHT_RCC_PORT		RCC_APB2Periph_GPIOA

uint8_t DHT_Get_Temp_Humi_Data(uint8_t buffer[]);

#endif

主函数main

 /*
   关注csdn单片机阿伟
*/
#include "stm32f10x.h"
#include "bsp_usart.h"
#include "delay.h"
#include "DHT11.h"
#include "bsp_usart.h"
/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
  
char str[20];
uint8_t DHT_Buffer[5];


int main(void)
{	
  /*初始化USART 配置模式为 115200 8-N-1,中断接收*/

  USART_Config();
 	printf("this is a tese based on stm32f103c8t6 drive DHT11\r\n");

	
	while (1)
	{
		if(DHT_Get_Temp_Humi_Data(DHT_Buffer))	//DHT_Get_Temp_Humi_Data获取温湿度
		{	
			printf("\r\nTemperature=%d.%d\r\n", DHT_Buffer[2],DHT_Buffer[3]);	//打印温度
			printf("humidity=%d.%d\r\n", DHT_Buffer[0],DHT_Buffer[1]);		//打印湿度
		}
  
    }
  

}
/*********************************************END OF FILE**********************/

运行看效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值