嵌入式设计与开发项目-DHT11温湿度传感器程序设计
一、实现的功能二、根据功能实现代码1、主文件main.c2、DHT11温湿度的头文件“dht11.h”3、DHT11温湿度的源文件“dht11.c”三、实现功能过程的注意与学习点1、注意点2、学习的知识点知识普及:
DHT11是单线接口数字温湿度传感器,温度测量范围是0 ~ 50℃,湿度测量范围是20% ~ 90%RH,温度测量精度是±2℃,湿度测量精度是±5%RH。
DHT11包含一个电阻式感湿元件和一个NTC(负温度系数)测温元件,通过双向单线输出温度、湿度数据,一次数据输出40位(高位在前,大约需要4ms),数据格式为:8位湿度整数 + 8位湿度小数(0) + 8位温度整数 + 8位温度小数(0) + 8位校验和(其中检验和是前4个8位数据之和的后8位)。
时序学习流程:
①单线空闲时为高电平,MCU读取数据时首先发送开始信号(输出低电平,持续时间必须大于18ms),然后切换到输入模式(单线由上拉电阻拉为高电平)等待DHT11;
②DHT11检测到开始信号后触发一次数据采集,并等待单线变为高电平后输出响应信号(低电平,持续时间80us)
一、实现的功能
①完成DHT11温湿度传感器数据的实时采集显示;②8个LED的流水灯控制,每隔1s点亮一个灯,按以上步骤重复进行;③编写DHT11温湿度的底层驱动;二、根据功能实现代码
1、主文件main.c
#include"key.h"#include"led.h"#include"lcd.h"#include"stdio.h"#include"dht11.h"unsigned int uiDht_Val;unsigned char ucSec,ucSec1;unsigned char pucStr[21];unsigned long ulTick_ms;void DHT_Proc(void);int main(void){SysTick_Config(72000);//定时1ms(HCLK = 72MHz)KEY_Init();LED_Init();STM3210B_LCD_Init();LCD_Clear(Blue);LCD_SetBackColor(Blue);LCD_SetTextColor(White);while(1){LED_Disp(ucSec);DHT_Proc();}}void DHT_Proc(void){if(ucSec != ucSec1){ucSec1 = ucSec;uiDht_Val = dht11_read();sprintf((char *)pucStr," Humidity: %2d%%",uiDht_Val >> 24);LCD_DisplayStringLine(Line3,pucStr);sprintf((char *)pucStr," Temperature: %dC",(uiDht_Val >> 8)&0xff);LCD_DisplayStringLine(Line5,pucStr);}}//SysTick 中断处理程序void SysTick_Handler(void){ulTick_ms++;if(ulTick_ms % 1000 ==0)ucSec++;}
主函数分析:❤️ ❤️ ❤️
dht11_read()返回的是36位数据,已经把DHT11的低八位校验和阉割掉,所以湿度的整数位是采集到的数据右移24位;温室的整数数据是采集到的数据uiDht_Val右移8位取低八位数据;
2、DHT11温湿度的头文件“dht11.h”
#ifndef __DHT11_H#define __DHT11_Hvoid dht11_init (void );void delay(unsigned int n);unsigned int dht11_read(void);void DisplayDht11(void);#endif
简要分析:❤️ ❤️
DHT11对于的引脚进行初始化;设定延时函数根据时序进行接收函数;获取温湿度数据,返回一个无符号整型的数据;
3、DHT11温湿度的源文件“dht11.c”
#include "stm32f10x.h"#define delay_us(X) delayd(X*72/5)void delayd(unsigned int n){while (n--);}void dht11_init (void ){GPIO_InitTypeDef GPIO_InitStructure;/* Enable clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);/* Configure Ports */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_7);}void mode_input(void ){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);}void mode_output(void ){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);}unsigned int dht11_read(void){int i;long long val;int timeout;GPIO_ResetBits(GPIOA, GPIO_Pin_7);delay_us(18000); //pulldown for 18msGPIO_SetBits(GPIOA, GPIO_Pin_7);delay_us( 20 );//pullup for 30usmode_input();//等待DHT11拉低,80ustimeout = 5000;while( (! GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_7)) && (timeout > 0) ) timeout--; //wait LOW//等待DHT11拉高,80ustimeout = 5000;while( GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_7) && (timeout > 0) ) timeout-- ; //wait HIGH#define CHECK_TIME 28for(i=0;i<40;i++){timeout = 5000;while( (! GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_7)) && (timeout > 0) ) timeout--; //wait HIGHdelay_us(CHECK_TIME);if ( GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_7) ){val=(val<<1)+1;} else {val<<=1;}timeout = 5000;while( GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_7) && (timeout > 0) ) timeout-- ; //wait LOW}mode_output();GPIO_SetBits(GPIOA, GPIO_Pin_7);if (((val>>32)+(val>>24)+(val>>16)+(val>>8) -val ) & 0xff ) return 0;else return val>>8; }
简要分析:❤️ ❤️
DHT11温湿度传感器连接到芯片的PA7引脚,dht11_init()初始化即时初始化PA7引脚为推挽输出模式,并设置PA7为高电平;同时配置PA7引脚推挽输出模式和上拉输入模式,根据时序图进行相对应的发送和接收;**#define delay_us(X) delayd(X*72/5)**可能通过调试计算出来相对准确的延时函数;MCU首先发送开始数据(输出低电平,持续时间必须大于18ms,保证DHT11能检测到开始信号),然后切换到输入模式(单线由上拉电阻拉为高电平),等待DHT11响应;DHT11检测到开始信号后,触发一次数据采集,并等待单线变为高电平后输出响应信号(低电平,持续时间80us),然后输出高电平(持续时间80us)准备输出40位数据;每位数据都以低电平(持续时间为50us)开始,输出0时高电平持续时间为26~28us,输出1时高电平持续时间为70us。最后一位数据输出后输出低电平(持续时间50us),单线由上拉电阻拉为高电平进入空闲状态。MCU检测到响应信号从单线读取40位数据,并判断校验是否正确,如果正确则有效,否则丢弃数据。
三、实现功能过程的注意与学习点
1、注意点
dht11_read()返回的是32位数据,已经把8位校验和数据除掉了;分别获取温湿度时,注意向右移的位数;2、学习的知识点
①根据DHT11传输数据的时序,编写获取DHT11温湿度的驱动;②掌握通过移位获取相对应的温湿度数据;③学会使用while循环等待特定的响应信号;④判断传感器数据输出0或者1时,可以通过判断输出0最大持续时间28us;❤️ ❤️ ❤️ ❤️ ❤️ ❤️