(一)主程序
while(1)
{DHT11_Read_Data();//读取温湿度数值
// RS485_Usart_SendArray(RS485_USARTx,temp,13);
RS485_Usart_SendString( RS485_USARTx,(char*)temp);
delay_ms(9000);
}
(二)模块调试函数
#include "bsp_dht11.h"
#include "delay.h"#include "bsp_485.h"
/*
* 函数名:DHT11_GPIO_Config
* 描述 :配置DHT11用到的I/O口
* 输入 :无
* 输出 :无
*/
static void DHT11_IN_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 温湿度传感器控制线浮空输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
/**
* @brief 设置端口为输出模式
*/
static void DHT11_OUT_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 温湿度传感器控制线模拟输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
/**
* @brief 初始化 DHT11,并检测,检测成功返回 0,否则返回 1
*/
static void DHT11_Rst(void)
{
DHT11_OUT_Init(); //设置引脚为输出模式
PAout(0) = 0;
delay_ms(19); //拉低至少 18ms
PAout(0) = 1; //总线拉高 20~40us,DHT11会返回一个低电平
delay_us(30);
DHT11_IN_Init();
//设置管脚为输入模式,用于读取 DHT11 的值,此时 PAin(1)为高电平
}
/**
* @brief 检测 DHT11,检测成功返回 0,否则返回 1
*/
static u8 DHT11_Check(void)
{
return PAin(0); //检测输入电平高低
}
static u8 DHT11_Read_Bit(void)
{
while(!PAin(0)); //等待变高电平,每次发送数据前都会有一个 50us 的电平信号
delay_us(40); //等待 40us
if(PAin(0) == 1)
{
while(PAin(0)); //当数据为 1 时,还得等到 1 信号结束,这里有不少人会出错
return 1;
}
else
return 0;
}
/**
* @brief 从 DHT11 读取一个字节
*/
static u8 DHT11_Read_Byte(void)
{
u8 i;
u8 Data = 0;
for(i=0;i<8;i++)
{
Data <<= 1;
Data |= DHT11_Read_Bit();
}
return Data;
}
/*** @brief 从 DHT11 读取 8 位数据包
*/
u8 temp[15]; //dht11数据发送
void DHT11_Read_Data(void)
{
u8 Data_Buff[5];
u8 i = 0;
// char check[] = "Device Not Available\n";
// char error_data[] = "Error Data\n";
DHT11_Rst();
if (DHT11_Check() == 0) //当检测到 DHT11 给 STM32 主控芯片的输入电压为低电压时,说明 DHT11 开始响应
{
while(!PAin(0)); //等待 80us 的低电平响应信号结束
while(PAin(0)); //等待 80us 的高电平结束,开始接收数据
for (i = 0; i < 5; i++)
{
Data_Buff[i] = DHT11_Read_Byte();
}
while(!PAin(0)); //等待 40 位数据输出完后的 50us 低电平输出结束
//此处不应该再加一个50us的延时吗?最后一bit数据传送完毕后, DHT11拉低总线
//50us,随后总线由上拉电阻拉高进入空闲状态
DHT11_OUT_Init();
PAout(0) = 1;
if ((Data_Buff[0]+Data_Buff[1]+Data_Buff[2]+Data_Buff[3]) == Data_Buff[4])
{
//加入湿度的整数和小数
temp[0]=Data_Buff[0]/10+48;
temp[1]=Data_Buff[0]%10+48;
temp[2]='.';
temp[3]=Data_Buff[1]/10+48;
temp[4]=Data_Buff[1]%10+48;
temp[5]='H';
temp[6]=' ';
//加入温度的整数和小数
temp[7]=Data_Buff[2]/10+48;
temp[8]=Data_Buff[2]%10+48;
temp[9]='.';
temp[10]=Data_Buff[3]/10+48;
temp[11]=Data_Buff[3]%10+48;
temp[12]='C';
}
delay_us(400);
}
}
(三).h文件
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "sys.h"
#include "delay.h"
#define HIGH 1
#define LOW 0
#define DHT11_CLK RCC_APB2Periph_GPIOA
#define DHT11_PIN GPIO_Pin_0
#define DHT11_PORT GPIOA
//带参宏,可以像内联函数一样使用,输出高电平或低电平
#define DHT11_DATA_OUT(a) if (a) \
GPIO_SetBits(GPIOA,GPIO_Pin_0);\
else \
GPIO_ResetBits(GPIOA,GPIO_Pin_0)
//读取引脚的电平
#define DHT11_DATA_IN() GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
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;
//void DHT11_GPIO_Config(void);
static void DHT11_Mode_IPU(void);
static void DHT11_Mode_Out_PP(void);
uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data);
static uint8_t Read_Byte(void);
static void DHT11_IN_Init(void);
static void DHT11_OUT_Init(void);
static void DHT11_Rst(void);
static u8 DHT11_Check(void);
static u8 DHT11_Read_Bit(void);
static u8 DHT11_Read_Byte(void);
void DHT11_Read_Data(void);
#endif /* __DHT11_H */