前言
本文记录的温湿度传感器的学习过程。 实验平台:野火指南者stm32f103vet6 模块:DHT11温湿度传感器
一、编程前期工作
1.原理图引脚
有原理图可以知道DHT11的数据线接在板子的PE6引脚 编程的时候,要配置并初始化PE6。
2.工作方式
DHT11只有一条数据线与MCU连接,是单总线串行通信,系统中的数据交换、控制均由单总线完成。
设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器 件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
3.数据格式
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位。
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。 注意:高位先出。一次传送40位数据。其中湿度小数部分为0。
4.通信过程和时序
通信过程:用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集, 如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
时序图:
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后, 等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
———————————————————————————————————————————— 总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。 数字信号为0的表示方法,如图所示:
数据信号为1的表示方法,如图所示:
。
二、代码
考虑到文章篇幅问题,所以只放有关DHT11的代码。
main.c
代码如下(示例):
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "bsp_dht11.h"
#include "./systick/bsp_SysTick.h"
void Delay(unsigned int n) {
unsigned int i,j;
for(j = 0; j<5000; j++)
{
for(i = 0;i<n;i++);
}
return ;
}
int main(void) {
DHT11_Data_TypeDef DHT11_Data;
SysTick_Init();
USART_Config();
DHT11_Init();
printf("DHT11温湿度传感器实验\n\r");
while(1) {
if( DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS) {
printf("读取成功!\n\r温度:%d.%d ℃, 湿度:%d.%d \n", \
DHT11_Data.temp_int, DHT11_Data.temp_deci, DHT11_Data.humi_int, DHT11_Data.humi_deci);
} else {
printf("读取温湿度失败!\n");
}
Delay(5000);
}
}
bsp_dht11.c
代码如下(示例):
#include "bsp_dht11.h"
#include "bsp_usart.h"
static void DHT11_GPIO_Config(void);
static void DHT11_Mode_Out_PP(void);
static void DHT11_Mode_IPU(void);
static uint8_t DHT11_ReadByte(void);
void DHT11_Init(void) {
DHT11_GPIO_Config();
DHT11_Dout_1;
return ;
}
static void DHT11_GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
DHT11_Dout_SCK_APBxClkCmd(DHT11_Dout_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
return ;
}
static void DHT11_Mode_Out_PP(void) {
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
static void DHT11_Mode_IPU(void) {
GPIO_InitTypeDef GPIO_InitStructure;
DHT11_Dout_SCK_APBxClkCmd(DHT11_Dout_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
return ;
}
static uint8_t DHT11_ReadByte(void) {
uint8_t i, dht11_onebyte_data = 0;
for(i = 0; i < 8; i++) {
while( 0 == DHT11_Dout_IN() );
DHT11_DELAY_US(50);
if( 1 == DHT11_Dout_IN() ) {
dht11_onebyte_data |= (uint8_t)(1 << 0);
while( 1 == DHT11_Dout_IN() );
} else {
dht11_onebyte_data &= (uint8_t)~(1 << 0);
}
if(i == 7) {
break;
}
dht11_onebyte_data = dht11_onebyte_data << 1;
}
return dht11_onebyte_data;
}
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef* DHT11_Data) {
DHT11_Mode_Out_PP();
DHT11_Dout_0;
DHT11_DELAY_MS(18);
DHT11_Dout_1;
DHT11_DELAY_US(30);
DHT11_Mode_IPU();
if( 0 == DHT11_Dout_IN() ) {
while(DHT11_Dout_IN() == 0);
while(DHT11_Dout_IN() == 1);
DHT11_Data->humi_int = DHT11_ReadByte();
DHT11_Data->humi_deci = DHT11_ReadByte();
DHT11_Data->temp_int = DHT11_ReadByte();
DHT11_Data->temp_deci = DHT11_ReadByte();
DHT11_Data->check_sum = DHT11_ReadByte();
}
DHT11_DELAY_US(50);
DHT11_GPIO_Config();
DHT11_Dout_1;
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci) {
return SUCCESS;
} else {
printf("读取温湿度数据不正确!!!\n");
return ERROR;
}
}
bsp_dht11.h
代码如下(示例):
#ifndef __BSP_DHT11_H__
#define __BSP_DHT11_H__
#include "stm32f10x.h"
#include "./dwt_delay/core_delay.h"
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;
#define DHT11_DELAY_US(us) CPU_TS_Tmr_Delay_US(us)
#define DHT11_DELAY_MS(ms) CPU_TS_Tmr_Delay_MS(ms)
#define DHT11_Dout_GPIO_PORT GPIOE
#define DHT11_Dout_GPIO_PIN GPIO_Pin_6
#define DHT11_Dout_SCK_APBxClkCmd RCC_APB2PeriphClockCmd
#define DHT11_Dout_GPIO_CLK RCC_APB2Periph_GPIOE
#define DHT11_Dout_0 GPIO_ResetBits(DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN)
#define DHT11_Dout_1 GPIO_SetBits(DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN)
#define DHT11_Dout_IN() GPIO_ReadInputDataBit(DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN)
void DHT11_Init(void);
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef* DHT11_Data);
#endif
结果
结果如图所示:
总结
重点还是要学会看时序图,而且总的时序图尤为重要,先有大局观,再抓其中细节的部分。 如写完程序,对照总时序图看看,有没有哪些地方是错漏的。
|