STM32 DHT11
1. 开发平台
- 野火STM32F429开发板
- 使用标准库开发
2. DHT11介绍
- DHT11温湿度传感器,是一个单总线传感器。
所以DHT11最先输出的是湿度然后在输出温度(最开始我没认真看,以为先输出温度再输出湿度,然后打印出来的数据是反的)
3. DHT11的时序
- 先是主机发送开始信号
- 然后就DHT11响应
- DHT11发送数据
- 最后要把数据线拉高,释放总线
代码如下:
dht11 .h
#ifndef __DHT11__H
#define __DHT11__H
#include "stm32f4xx.h"
#include "systick.h"
#include "USART.h"
#include "stdio.h"
//DATA线引脚为PD6
#define DHT11_OUT_H GPIO_SetBits(GPIOD,GPIO_Pin_6)
#define DHT11_OUT_L GPIO_ResetBits(GPIOD,GPIO_Pin_6)
#define DHT11_READ GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_6)
#define DHT11_CLK RCC_AHB1Periph_GPIOD
#define DHT11_PIN GPIO_Pin_6
#define DHT11_PORT GPIOD
void DHT11_Init (void);
void DHT11_MODE_IN(void);
void DHT11_MODE_OUT(void);
uint8_t DHT11_Read_Byte(void);
uint8_t DHT11_ReadData(uint8_t *temp,uint8_t *humi);
void DHT11_Data(void);
#endif
dht11.c
#include "DHT11.h"
uint8_t temp=0;
uint8_t humi=0;
//DHT11驱动
void DHT11_Init (void)
{
RCC_AHB1PeriphClockCmd(DHT11_CLK,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin=DHT11_PIN;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;
GPIO_Init(DHT11_PORT,&GPIO_InitStruct);
}
//输入模式
void DHT11_MODE_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin=DHT11_PIN;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;
GPIO_Init(DHT11_PORT,&GPIO_InitStruct);
}
//输出模式
void DHT11_MODE_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin=DHT11_PIN;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;
GPIO_Init(DHT11_PORT,&GPIO_InitStruct);
}
//读取一个字节
uint8_t DHT11_Read_Byte(void)
{
uint8_t i,data;
for(i=0;i<8;i++)
{
if(DHT11_READ==0)
{
while(DHT11_READ==0);
}
DELAY_us (40); //40us
if(DHT11_READ==1)
{
while(DHT11_READ==1);//这里要等待高电平结束,否者读取下一位的时候会因为高电平没有结束而跳过上一个if
data|=(uint8_t)0x01<<(7-i);
}
else
data&=(uint8_t)~0x01<<(7-i);
}
return data;
}
//读五个字节
uint8_t DHT11_ReadData(uint8_t *temp,uint8_t *humi)
{
uint8_t buf[5];
uint8_t i;
for(i=0;i<5;i++)
{
buf[i]=DHT11_Read_Byte();
}
if(buf[0]+buf[1]+buf[2]+buf[3]==buf[4])
{
*temp=buf[2];
*humi=buf[0];
return 1;
}
else
return 0;
}
//DHT11 读数据
void DHT11_Data(void)
{
DHT11_Init ();
DHT11_OUT_L;
DELAY_us(20000);
DHT11_OUT_H;
DELAY_us(20);
DHT11_MODE_IN();
if(DHT11_READ==0)
{
while(DHT11_READ==0);
while(DHT11_READ==1);
DHT11_ReadData(&temp,&humi);
printf("温度:%d 湿度:%d\n",temp,humi);
}
DHT11_MODE_OUT();
DHT11_OUT_H;
}