目录

【demo · 串口打印温湿度:DHT11】

【驱动流程】

【数据格式】

【时序图】

【代码】


【demo · 串口打印温湿度:DHT11】

【驱动流程】

        ①   主机将DHT11数据引脚拉为低电平,持续至少18ms
        ②   主机将DHT11数据引脚拉为高电平,持续20~40us,等待DHT11响应
        ③   如果DHT11存在,则会有80us的响应信号,此时数据引脚会被拉为低电平,否则数据引脚始终为高电平
        ④   接下来控制权转移给DHT11,DHT11会继续把数据引脚拉高80us,然后开始返回数据
        ⑤   首先,DHT11会拉低数据引脚50us,表示开始传输数据位
        ⑥   接下来便是DHT11发送数据位,数据位的高低电平取决于数据位拉高的时间:如果数据位高电平的时间为26us~28us,则代表数据位是低电平 ‘0’;如果数据位高电平的时间为70us,则代表数据位是高电平 ‘1’

【数据格式】

40位数据=8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位

其中湿度小数部分为 0,且温度低位 Bit8 为 1 则表示负温度,否则为正温度

数据传送正确时,校验和数据=“ 8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据” 所得结果的末8位

【时序图】

【代码】
/* dht11.h */

#ifndef __DHT11_H__
#define __DHT11_H__

#include "main.h"

void DHT_GPIO_Init(uint32_t Mode);	// DHT11 GPIO初始化
void DHT11_Start(void);							// DHT11 触发信号
void Read_Data_From_DHT(void);			// DHT11 数据处理

#endif /*__ DHT11_H__ */

/* dht11.c */

/* 注意:此代码未进行DHT11是否存在的检测,DHT11不存在时依然有数据,只不过数据有误 */

#include "dht11.h"

#include "delay_us.h"
#include "stdio.h"

#define DHT_HIGHT 	HAL_GPIO_WritePin(DHT11_Port, DHT11_Pin, GPIO_PIN_SET)
#define DHT_LOW 		HAL_GPIO_WritePin(DHT11_Port, DHT11_Pin, GPIO_PIN_RESET)
#define DHT_Read 		HAL_GPIO_ReadPin(DHT11_Port, DHT11_Pin)

uint8_t datas[5];		// 数组内有 5 个元素,每个元素都是一个无符号 8 位整数

// DHT11 GPIO初始化
void DHT_GPIO_Init(uint32_t Mode)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	__HAL_RCC_GPIOB_CLK_ENABLE();
	
	GPIO_InitStruct.Pin = DHT11_Pin;
	GPIO_InitStruct.Mode = Mode;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(DHT11_Port, &GPIO_InitStruct);
}

// DHT11 触发信号
void DHT11_Start(void)
{
	DHT_GPIO_Init(GPIO_MODE_OUTPUT_PP);
	DHT_HIGHT;
	DHT_LOW;
	HAL_Delay(30);
	DHT_HIGHT;
	DHT_GPIO_Init(GPIO_MODE_INPUT);
	while(DHT_Read);
	while(!DHT_Read);
	while(DHT_Read);
}

// DHT11 数据处理
void Read_Data_From_DHT(void)
{
	int i;	//轮数:	4轮
	int j;	//每一轮读多少次:	8次
	char tmp;
	char flag;
	DHT11_Start();
	DHT_GPIO_Init(GPIO_MODE_INPUT);
	for(i= 0;i < 5;i++)
	{
		for(j=0;j<8;j++)
		{
			while(!DHT_Read);
			delay_us(40);
			if(DHT_Read == 1)
			{
				flag = 1;
				while(DHT_Read);
			}
			else
			{
				flag = 0;
			}
			tmp = tmp << 1;
			tmp |= flag;
		}
		datas[i] = tmp;
	}
}
/* delay_us.h */

#ifndef __DELAY_US_H__
#define __DELAY_US_H__

#include "main.h"

#define CPU_FREQUENCY_MHZ    72		// STM32时钟主频

void delay_us(__IO uint32_t delay);
/* delay_us.c */

#include "delay_us.h"


void delay_us(__IO uint32_t delay)
{
    int last, curr, val;
    int temp;

    while (delay != 0)
    {
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
            do
            {
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}
/* usart.h */

int fputc(int ch, FILE *f);
/* usart.c */


#include "stdio.h"

int fputc(int ch, FILE *f)
{
	unsigned char temp[1]={ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;
}

        Keil上勾选微库

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐