STM32简单读取DHT11温湿度数据
本文是关于对DHT11传感器进行数据的获取和处理
一,模块图片如下:
一般是4根线
从左到右分别为:
VDD:供电引脚3.3~5.5V DC
Data:穿行数据,单总线
NC:空脚
GND:接地,电源负极
二,总体说明:
简化版的单总线通信,有一根数据线,完成系统中的数据交换,控制,所以设计引脚模式的切换,这个后文会有提到,一次输出的数据有40位分别为湿度高低8位 温度高低8位 ,还有校验位
三,具体流程
步骤1
先进行一系列的准备,因为DHT11是单总线,所以要封装两个函数,反别设置引脚位是输出还是输入
static void DHT11_Mode_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStruct);
}
static void DHT11_Mode_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStruct);
}
可以理解为主机和从机,松手和放手 的关系
在初始化引脚后,就要奖DHT11的Data引脚拉高至于高电平,并且对于DHT11来说Data是输入
void DHT11_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStruct);
DHT11_High;
}
步骤2:
unsigned char Read_DHT11(DHT11_Data_TypeDef *DHT11_Data)//这个地方和后面的步骤4拼接到一起
{
DHT11_Mode_OUT();
DHT11_Low;
SysTick_delay_ms(20);//拉低不得低于18ms
DHT11_High; //按照时序再拉高
SysTick_delay_us(30);//延时等待20~40us
DHT11_Mode_IN();
步骤3:
这是对于读取到的数据进行一个判断
static uint8_t Read_Byte(void)
{
uint8_t i,temp=0;
for(i=0;i<8;i++)
{
while(Read_Data==0);//’0‘的格式是54us的低电平和23-27us的高电平
//1的格式是54us的低电平和68~74us的高电平,因为两者前面都是54us的低电平,所以等待低电平结束,再延时40us(这是一个中间值)再来判断是高电平还是低电平
SysTick_delay_us(40);
if(Read_Data==1){
while(Read_Data==1);
temp|=(uint8_t)(0x01<<(7-i));
}
else{
temp&=(uint8_t)~(0x01<<(7-i));
}
}
return temp;
}
步骤4:
主机将控制权给从机,也就是此时的引脚为输入模式,开始判断接收到的数据是不是低电平
if(Read_Data==0)
{
while(Read_Data==0);//大概54us
while(Read_Data==1);//大概23-27us
DHT11_Data->humi_int=Read_Byte();//这地方的读取函数在步骤三
DHT11_Data->humi_deci=Read_Byte();
DHT11_Data->temp_int=Read_Byte();
DHT11_Data->temp_deci=Read_Byte();
DHT11_Data->check_sum=Read_Byte();
if(DHT11_Data->check_sum==(DHT11_Data->temp_deci+DHT11_Data->temp_int+DHT11_Data->humi_deci+DHT11_Data->humi_int))//这里用的是结构体存储,也可以用指针,我觉得结构体好看
{
return 1;
}
else{
return 0;
}
}
else{
return 0;
}
}
后面是头文件和宏定义记得:
#include "stm32f10x.h" // Device header
#define DHT11_High GPIO_SetBits(GPIOD, GPIO_Pin_6)
#define DHT11_Low GPIO_ResetBits(GPIOD, GPIO_Pin_6)
#define Read_Data GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_6)
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;
最后是主函数部分:用的江协 的OLED屏幕代码
#include "stm32f10x.h" // Device header
#include <USART.H>
#include <stdio.h>
#include <DHT11.H>
#include <OLED.H>
//uint8_t RXDate=0;
//uint8_t RX_Flag=0;
DHT11_Data_TypeDef DHT11_Data;
int main(void){
OLED_Init();
DHT11_GPIO_Config();
OLED_ShowString(1, 1, "temp:");
OLED_ShowString(2, 1, "humidity:");
while(1)
{
if(Read_DHT11(&DHT11_Data) == 1)
{
OLED_ShowNum(2, 10, DHT11_Data.humi_int, 2);
OLED_ShowString(2, 12, ".");
OLED_ShowNum(2, 13, DHT11_Data.humi_deci, 2);
OLED_ShowNum(1, 6, DHT11_Data.temp_int, 2);
OLED_ShowString(1, 8, ".");
OLED_ShowNum(1, 9, DHT11_Data.temp_deci, 1);
}
}
}
作者:怪盗坤洋