文章目录
前言
本文主要介绍利用CubeMX配置STM32F4系列芯片读取DHT11温湿度采集模块,仅作于学习
一、CubeMX配置
1、新建工程,配置相关时钟和时钟树,该例程配置72Mhz的时钟主频,相关配置前面文章已有叙述,这里不再多讲
2、由于DHT11采用单总线时序电路来进行通信,因此我们只需要用到一个IO口就能实现对DHT11温湿度采集模块的数据读取。这里配置了PD6作为通信IO
3、该模块对时序有要求,需要用到us级别的延时函数,因此我们还需要配置一个定时器来做延时函数。相关配置如下:
二、代码
1、模块.c文件
#include "dht11.h"
/***************************
* 数据发送时序:
* 首先主机发送开始信号,即拉低数据线保持t1(至少18ms)时间,
* 接着拉高数据线t2(20~40us)时间,然后读取DHT11的响应,
* DHT11会拉低数据线并保持t3(40~50us)时间作为响应信号,接
* 着DHT11拉高数据线并保持t4(40~50us)时间后,开始传输数据
*
* 传输协议:
* 数据包由5个字节(40Bit)组成,数据分小数和整数部分
* 一次完整的数据传输为40bit,一位一位传输,高位先出,传输顺序为:
* 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位
*
* 湿度 = byte4.byte3 byte4整数,byte3小数
* 温度 = byte2.byte1 byte2整数,byte1小数
* 校验 = byte0 = byte4 + byte3 + byte2 + byte1
*
* 采集周期不小于1s
***************************/
//8bit温湿度数据
uint8_t tem_integer;
uint8_t tem_decimal;
uint8_t hum_integer;
uint8_t hum_decimal;
/*****************/
//采集数据处理
void DH11_ReadDate_Handle(void)
{
uint8_t i;
uint8_t buf[5]={0}; //数据转存数组
uint16_t tem=0;
uint16_t hum=0;
DHT11_SendOut(); //发送信号等待响应
if(DHT11_Check()==0){
for(i=0;i<5;i++){
buf[i]=DHT11_ReadByte();//获取1Byte数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){//校验
tem=(buf[2]<<8) + buf[3]; //8Bit转存16Bit
hum=(buf[0]<<8) + buf[1];
tem_integer = tem>>8; //右移8Bit,低8位清0
tem_decimal = tem&0xff; //按位与(0xff-->0000000011111111),高8位清0
hum_integer = hum>>8;
hum_decimal = hum&0xff;
// printf("当前环境温度: %d.%d 摄氏度\r\n",tem_integer,tem_decimal);
// printf("当前环境湿度: %d.%d%%\r\r\n",hum_integer,hum_decimal);
}
}
}
/*****************/
//发送数据给DHT11
void DHT11_SendOut(void)
{
DHT11_IO_OUT();
DHT11_Date_Low;
HAL_Delay(18); //拉低18ms
DHT11_Date_High;
delay_us(30); //拉高30us
}
/*****************/
//检测DHT11是否开始传输数据
uint8_t DHT11_Check(void)
{
uint8_t retry=0;
DHT11_IO_IN();
while (DHT11_Date && retry<100){ //拉低40~80us
retry++;
delay_us(1);
}
if(retry>=100)return 1;
else retry=0;
while (!DHT11_Date && retry<100){ //拉高40~80us
retry++;
delay_us(1);
}
if(retry>=100)return 1;
return 0;
}
/*****************/
//读取1Bit数据
uint8_t DH11_ReadBit(void)
{
uint8_t retry=0; //retry用于防止卡死
//等待DHT11响应拉低(默认拉高),最大等待时间为100us
while(DHT11_Date && retry<100){
delay_us(1);
retry++;
}
retry=0;
//等待DHT11响应拉高,最大等待时间为100us
while(!DHT11_Date && retry<100){
delay_us(1);
retry++;
}
delay_us(40); //高电平等待40us
if(DHT11_Date)return 1;//获取DHT11数据
else return 0;
}
/*****************/
//读取1Byte数据
uint8_t DHT11_ReadByte(void)
{
uint8_t i;
uint8_t Read_Byte=0; //用于存放1Byte(8bit)数据
for(i=0;i<8;i++){
Read_Byte<<=1; //Read_Byte左移一位
Read_Byte |= DH11_ReadBit(); //将读取到的二进制数据写入Read_Byte末位
}
return Read_Byte;
}
/*****************/
//IO口设置为输入
void DHT11_IO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_6;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOD,&GPIO_InitStructure);
}
/*****************/
//IO口设置为输出
void DHT11_IO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_6;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOD,&GPIO_InitStructure);
}
/*****************/
//us延时函数
void delay_us(uint16_t us)
{
uint16_t differ = 0xffff-us-5;
__HAL_TIM_SET_COUNTER(&htim3,differ); //设定TIM3计数器起始值
HAL_TIM_Base_Start(&htim3); //启动定时器
while(differ < 0xffff-5){ //判断
differ = __HAL_TIM_GET_COUNTER(&htim3); //查询计数器的计数值
}
HAL_TIM_Base_Stop(&htim3);
}
2、模块.h文件
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f4xx_hal.h"
#include <stdio.h>
#define DHT11_Date HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_6)
#define DHT11_Date_Low HAL_GPIO_WritePin(GPIOD,GPIO_PIN_6,GPIO_PIN_RESET)
#define DHT11_Date_High HAL_GPIO_WritePin(GPIOD,GPIO_PIN_6,GPIO_PIN_SET)
extern TIM_HandleTypeDef htim3; //用于写延时函数
void DHT11_IO_IN(void);
void DHT11_IO_OUT(void);
void delay_us(uint16_t us);
void DHT11_SendOut(void);
uint8_t DHT11_Check(void);
uint8_t DH11_ReadBit(void);
uint8_t DHT11_ReadByte(void);
void DH11_ReadDate_Handle(void);
#endif
总结
温湿度读取的主要代码就那些啦,如需和其它项目结合,只要将这两个源码拷贝到相应的工程文件就能实现对温湿度的读取啦。另外,欢迎大家在评论区指出笔者的不足之处
注:该文章仅用于学习,如有侵权,告知必删