目录
温湿度传感器
温湿度传感器的基本概述
测量精度
硬件接线
时序分析
接收数据分析
代码
全局变量
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO外设的结构体变量
配置DHT11为输出模式
void DHT11_OutputConfig(void)
{
//1.打开GPIOG端口的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
//2.配置PG9引脚为输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
//3.对GPIOG端口进行初始化
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
配置DHT11为输入模式
//配置DHT11为输入模式
void DHT11_InputConfig(void)
{
//1.打开GPIOG端口的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
//2.配置PG9引脚为输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
//3.对GPIOG端口进行初始化
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
配置初始化DHT11
void DHT11_Config(void)
{
DHT11_OutputConfig();
}
发送开始信号
void Sent_StartSignal(void)
{
//将主机设置为输出模式并输出高电平并延时5ms ——>空闲模式
DHT11_OutputConfig();
GPIO_SetBits(GPIOG, GPIO_Pin_9);
delay_ms(5);
//输出低电平并延时20ms
GPIO_ResetBits(GPIOG, GPIO_Pin_9);
delay_ms(20);
//输出高电平并延时30us
GPIO_SetBits(GPIOG, GPIO_Pin_9);
delay_us(30);
}
判断DHT11温湿度传感器是否应答
bool Is_DHT11ACK(void)
{
//定义一个计数器用来记数
u32 cont = 0;
//配置PG9为输入模式
DHT11_InputConfig();
//此时总线为高电平,需要等待总线拉低为低电平,并做超时处理
while( (GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_9)) && cont < 50)
{
delay_us(1);
cont++;
}
//判断延时了多少us
if(cont >= 50)
{
return false; //说明超时了
}
//计数器清零
cont = 0;
//这里为DHT11的应答
//此时总线为低电平,需要等待总线拉高为高电平,并计数
while((! GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_9)) && cont < 100)
{
delay_us(1);
cont++;
}
//判断延时了多少us
if(cont >= 100)
{
return false; //说明超时了
}
return true;
}
接收一位数据
u8 Recv_DHT11Bit(void)
{
//定义计时器
u32 cont = 0;
//此时为高电平,需要等待低电平出现
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_9) );
//此时为低电平,需要等待总线电平变为高电平
while( ! GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_9) );
//此时为高电平,需要等待总线电平变为低电平,并通过判断高电平的持续时间,从而判断数据是0还是1
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_9) )
{
delay_us(1);
cont++;
}
if( cont <= 50)
return 0;
else
return 1;
}
接收一个字节的数据
u8 Recv_DHT11Byte(void)
{
//定义用来接收数据的变量
u8 data = 0;
//循环接收数据
for(u32 i = 0; i<8; i++)
{
data <<= 1 ;
data |=Recv_DHT11Bit();
}
return data;
}
接收DHT11传输的数据
义计时器
//u32 cont = 0;
//1.配置PG9为输出模式
DHT11_OutputConfig();
//2.发送开始信号
Sent_StartSignal();
//3.等待DHT11应答
if(Is_DHT11ACK())
{
//6.开始接收数据
for( u32 i = 0; i<5; i++)
{
DHT11Data[i] = Recv_DHT11Byte();
}
//7.检验校验和
if(DHT11Data[4] == DHT11Data[0] + DHT11Data[1] + DHT11Data[2] + DHT11Data[3])
return true;
else
return false;
}
else
return false;
}
串口USART1的初始化
void USART1_Config(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//打开了GPIO端口时钟 PA9和PA10
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//打开USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//选择GPIO引脚的复用功能
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9 , GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
//配置GPIO引脚 注意:复用模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置串口参数+对串口初始化
USART_InitStructure.USART_BaudRate = baud; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure);
//配置NVIC参数 + 对NVIC初始化
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//选择USART1的中断源,接收到数据则触发中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//打开串口
USART_Cmd(USART1, ENABLE);
}
利用串口发送一个字符串
//利用串口发送一个字符串
void USART1_SendString(const char *str)
{
while(*str)
{
USART_SendData(USART1,*str++);
while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET );
}
}
主函数
/**
******************************************************************************
* @file main.c
* @author Dazz
* @version v1.0
* @date 2024/07/12
* @brief 利用温湿度传感器DHT11获取温度和湿度,并重定向到串口输出
* @None DQ -> PG9
******************************************************************************
**/
#include "stm32f4xx.h" //必须包含
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "DHT11.h"
#include "delay.h"
#define BUFSIZE 128
uint8_t recvbuf[BUFSIZE] ={0}; //用于存储串口收到的数
uint32_t recvcnt = 0; //用于作为数组的计数器
u8 DHT11Data[5] = "0"; //用于接收DHT11的数据
//前台程序就是中断服务程序,该程序是不需要手动调用的,当中断触发之后CPU会自动跳转过来执行该函数
void USART1_IRQHandler(void)
{
uint8_t data;
//判断中断是否发生
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
//从USART1中接收一个字节
data = USART_ReceiveData(USART1); //一次只能接收一个字节
//把接收到的数据转发出去
USART_SendData(USART1,data);
}
}
int main()
{
//1.硬件的初始化
USART1_Config(9600); //串口
DHT11_Config(); //DHT11温湿度传感器
u8 data[128] = "0";
while(1)
{
Recv_DHT11Data(DHT11Data);
sprintf((char*)data, "湿度 = %d%%RH, 温度 = %d℃\r\n", DHT11Data[0], DHT11Data[2]);
USART1_SendString((char*)data);
delay_ms(500);
}
}