//main函数
unsigned int count = 0;
int main(void)
{
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//用proteus仿真用到,一定要写在开头。
SysTick_Configuration();
Uart1_Configuration();
DHT11_GPIO_Configuration();
//注意,仿真专用,我修改了Systick 正常使用要把/9去掉,另外邴老师的代码有问题,仿真会出现错误,用老陈的连续读取,就没问题。
while(1)
{
DHT11_Read();
printf("Temperature = %d.%d℃\r\n", Tem_H, Tem_L);//
printf("Humidity = %d.%d%%RH\r\n", Hum_H, Hum_L); //显示在串口助手里不用\r
printf("---------------------\r\n");
Delay_us(1000000); // 仿真的时候修改一下delay_us 因为仿真里晶振频率为8Mhz.
}
}
//dht11.c
#include "bsp_dht11.h"
#include "bsp_uart.h"
unsigned char Hum_H=0, Hum_L=0, Tem_H=0, Tem_L=0;
unsigned char buff[5]={0};
//PA7:DHT11_DATA
void DHT11_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void DHT11_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void DHT11_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void DHT11_Start(void)
{
unsigned int timeout;
DHT11_Mode_Out_PP(); //将PA7配置为输出模式
DHT11_DATA_OUT(0); //将电平拉低
Delay_us(20000); //保持低电平至少18ms
DHT11_DATA_OUT(1); //将电平拉高
Delay_us(30); //保持高电平20~40us
DHT11_Mode_IPU();
//DHT11的80us低电平响应信号
timeout = 80;
while((!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)) && (timeout > 0))
{
timeout--;
Delay_us(1);
}
//DHT11的80us高电平响应信号
timeout = 80;
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) && (timeout > 0))
{
timeout--;
Delay_us(1);
}
}
void DHT11_Data_Read(void)
{
unsigned int i,j;
unsigned char dat = 0;
unsigned int timeout;
DHT11_Mode_IPU();
for (j = 0; j< 5; j++)
{
for(i = 0; i < 8; i++)
{
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) == 0); //等待50us过去
Delay_us(40); //跨过40us后再去读取信号线上的电平,如果为低电平标识数据为0,如果为高电平表示数据为1
dat <<= 1;
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7))
dat += 1;
buff[j] = dat;
timeout = 50;
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) && (timeout > 0))
{
timeout--;
Delay_us(1);
}
}
}
}
void DHT11_Read(void)
{
//启动DHT11
DHT11_Start();
//连续读取5个Byte,共计40bit,内含湿度8位整数位,湿度8位小数位,温度8位整数位,温度8位小数位,校验和
// Hum_H_temp = DHT11_Read_Byte();
// printf("Hum_H_temp=%d\r\n",Hum_H_temp);
//
// Hum_L_temp = DHT11_Read_Byte();
// printf("%d\r\n",Hum_L_temp);
//
// Tem_H_temp = DHT11_Read_Byte();
// printf("%d\r\n",Tem_H_temp);
//
// Tem_L_temp = DHT11_Read_Byte();
// printf("%d\r\n",Tem_L_temp);
//
// Check_Sum = DHT11_Read_Byte();
// printf("Check_Sum=%d\r\n",Check_Sum);
DHT11_Data_Read();
//发送结束标志
DHT11_Mode_Out_PP();
DHT11_DATA_OUT(1); //将电平拉高
//判断读取的40bit数据是否有效,及检查校验和是否正确
if((buff[0] + buff[1] + buff[2] + buff[3]) == buff[4])
{
Hum_H = buff[0];
Hum_L = buff[1];
Tem_H = buff[2];
Tem_L = buff[3];
}
}
//dht11.h
#ifndef __BSP_DHT11_H__
#define __BSP_DHT11_H__
#include <stm32f10x.h>
#include "bsp_SysTick.h"
#define DHT11_DATA_OUT(a) GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)(a))
extern unsigned char Hum_H, Hum_L, Tem_H, Tem_L;
void DHT11_GPIO_Configuration(void);
void DHT11_Read(void);
#endif
有个小伙伴问我说代码跑不了,我之前也遇到过这样的问题,总结如下:
1.没有进行对应的正确设置(见上篇)Proteus仿真STM32读取DHT11并串口打印输出_咕咕没有梦想的博客-CSDN博客
2.仿真对于数据读取要求比较苛刻,我特意创建了一个数组buff[5],然后按位填入数据dht11传出的40位数据(具体可以看dht11手册,有讲数据格式,我代码注释段也有提到),之前的问题就在这里,小伙伴可以仔细看一下。