stm32实用篇5:HAL库 DHT11 驱动

DHT11是很常用的温湿度传感器,时序也比较简单,如下所示:

直接给出HAL库的驱动:

1 微秒级延时函数

HAL库并没有直接的微秒级延时函数,下面是自己实现的微秒堵塞延时函数(使用定时器TIM3);

/**
	* @brief 微秒级延时
	*/
void bsp_delay_us(uint16_t us)
{
	__HAL_TIM_SET_COUNTER(&htim3, 0);
	
	HAL_TIM_Base_Start(&htim3);
	
	while (__HAL_TIM_GET_COUNTER(&htim3) != us);
	
	HAL_TIM_Base_Stop(&htim3);
}

2 配置DHT11数据引脚的输出模式和输入模式;

/**
	* @brief DHT11 输出模式
	*/
static void DHT11_Mode_OUT_PP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	
  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

/**
	* @brief DHT11 输入模式
	*/
static void DHT11_Mode_IN_NP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

3 读取一个字节的数据(经过测试,延时时间最好设置为 40 ~ 60,这里我设置为50us);

/**
	* @brief DHT11 读取字节
	*/
uint8_t DHT11_ReadByte(void)
{
	uint8_t i, temp = 0;

	for (i = 0; i < 8; i++)
	{
		while (DHT11_IN == 0);    // 等待低电平结束
		
		// 经过测试,这个值最好是 40 ~ 60,这里我选择 50 us
        bsp_delay_us(50);     // 至少延时 40 微秒  低电平为 0 ,高电平为 1
		
		if (DHT11_IN == 1)
		{
			while (DHT11_IN == 1);	// 等待高电平结束
			
			temp |= (uint8_t)(0X01 << (7 - i));	    // 先发送高位 MSB
		}
		else
		{
			temp &= (uint8_t)~(0X01 << (7 - i));
		}
	}
	return temp;
}

4 完整的读取一次数据(读取数据间隔最好为2s及以上,不然容易出错);

/**
	* @brief DHT11 读取一次数据
	*/
uint8_t DHT11_ReadData(DHT11_Data_TypeDef *DHT11_Data)
{
	DHT11_Mode_OUT_PP();		// 主机输出,主机拉低
	DHT11_OUT_0;	
	HAL_Delay(18);					// 延时 18 ms
	
	DHT11_OUT_1;						// 主机拉高,延时 30 us
	bsp_delay_us(30);	

	DHT11_Mode_IN_NP();			// 主机输入,获取 DHT11 数据
	
	if (DHT11_IN == 0)			// 收到从机应答
	{
		while (DHT11_IN == 0);		// 等待从机应答的低电平结束
		
		while (DHT11_IN == 1);		// 等待从机应答的高电平结束
		
		/*开始接收数据*/   
		DHT11_Data->humi_int  = DHT11_ReadByte();
		DHT11_Data->humi_deci = DHT11_ReadByte();
		DHT11_Data->temp_int  = DHT11_ReadByte();
		DHT11_Data->temp_deci = DHT11_ReadByte();
		DHT11_Data->check_sum = DHT11_ReadByte();
		
		DHT11_Mode_OUT_PP();		// 读取结束,主机拉高
		DHT11_OUT_1;	
		
		// 数据校验
		if (DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci)	
		{
			return 1;
		}		
		else
		{
			return 0;
		}
	}
	else		// 未收到从机应答
	{
		return 0;
	}
}

测试程序:

while (1)
{
	if (DHT11_ReadData(&DHT11_Data))
	{
		DEBUG_INFO("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",		
		DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
	}
	else
	{
		DEBUG_INFO("Read DHT11 ERROR!\r\n");
	}

	HAL_Delay(3000);
}

完整的驱动程序,仅供参考。

bsp_dht11.c

/**
	******************************************************************************
	* @file			bsp_dht11.c
	* @author		
	* @date			
	* @version	v1.0
	* @note			DHT11 driver
	******************************************************************************
	*/

#include "tim.h"
#include "bsp_dht11.h"

/**
	* @brief DHT11 输出模式
	*/
static void DHT11_Mode_OUT_PP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	
  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

/**
	* @brief DHT11 输入模式
	*/
static void DHT11_Mode_IN_NP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

/**
	* @brief DHT11 读取字节
	*/
uint8_t DHT11_ReadByte(void)
{
	uint8_t i, temp = 0;

	for (i = 0; i < 8; i++)
	{
		while (DHT11_IN == 0);		// 等待低电平结束
		
		bsp_delay_us(40);					//	延时 40 微秒		低电平为 0 ,高电平为 1
		
		if (DHT11_IN == 1)
		{
			while (DHT11_IN == 1);	// 等待高电平结束
			
			temp |= (uint8_t)(0X01 << (7 - i));			// 先发送高位 MSB
		}
		else
		{
			temp &= (uint8_t)~(0X01 << (7 - i));
		}
	}
	return temp;
}

/**
	* @brief DHT11 读取一次数据
	*/
uint8_t DHT11_ReadData(DHT11_Data_TypeDef *DHT11_Data)
{
	DHT11_Mode_OUT_PP();		// 主机输出,主机拉低
	DHT11_OUT_0;	
	HAL_Delay(18);					// 延时 18 ms
	
	DHT11_OUT_1;						// 主机拉高,延时 30 us
	bsp_delay_us(30);	

	DHT11_Mode_IN_NP();			// 主机输入,获取 DHT11 数据
	
	if (DHT11_IN == 0)			// 收到从机应答
	{
		while (DHT11_IN == 0);		// 等待从机应答的低电平结束
		
		while (DHT11_IN == 1);		// 等待从机应答的高电平结束
		
		/*开始接收数据*/   
		DHT11_Data->humi_int  = DHT11_ReadByte();
		DHT11_Data->humi_deci = DHT11_ReadByte();
		DHT11_Data->temp_int  = DHT11_ReadByte();
		DHT11_Data->temp_deci = DHT11_ReadByte();
		DHT11_Data->check_sum = DHT11_ReadByte();
		
		DHT11_Mode_OUT_PP();		// 读取结束,主机拉高
		DHT11_OUT_1;	
		
		// 数据校验
		if (DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci)	
		{
			return 1;
		}		
		else
		{
			return 0;
		}
	}
	else		// 未收到从机应答
	{
		return 0;
	}
}

// 测试程序
/*
while (1)
{
	if (DHT11_ReadData(&DHT11_Data))
	{
		DEBUG_INFO("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",					\
		DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
	}
	else
	{
		DEBUG_INFO("Read DHT11 ERROR!\r\n");
	}

	HAL_Delay(3000);
}
*/

bsp_dht11.h

#ifndef __BSP_DHT11_H
#define __BSP_DHT11_H

#include "tim.h"
#include "stm32f1xx_hal.h"

#define BSP_DHT11_PORT		DHT11_GPIO_Port
#define BSP_DHT11_PIN			DHT11_Pin

#define DHT11_OUT_1				HAL_GPIO_WritePin(BSP_DHT11_PORT, BSP_DHT11_PIN, GPIO_PIN_SET)
#define DHT11_OUT_0				HAL_GPIO_WritePin(BSP_DHT11_PORT, BSP_DHT11_PIN, GPIO_PIN_RESET)

#define DHT11_IN					HAL_GPIO_ReadPin(BSP_DHT11_PORT, BSP_DHT11_PIN)

typedef struct
{
	uint8_t humi_int;				// 湿度的整数部分
	uint8_t humi_deci;	 		// 湿度的小数部分
	uint8_t temp_int;	 			// 温度的整数部分
	uint8_t temp_deci;	 		// 温度的小数部分
	uint8_t check_sum;	 		// 校验和
		                 
} DHT11_Data_TypeDef;

uint8_t DHT11_ReadData(DHT11_Data_TypeDef* DHT11_Data);

#endif	/* __BSP_DHT11_H */

 

  • 12
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值