最新传奇手游开服网站,遵义市播州区建设厅网站,龙岗网站建设深圳信科,wordpress边栏时间【屏幕显示DHT11数据】 面向对象的思想编写硬件驱动程序#xff0c;DHT11采集环境中的温湿度数据。使用FreeRTOS提供的任务间通信、同步、互斥#xff0c;将DHT11的数据传递给显示任务。显示任务中#xff0c;使用emWin中间件#xff0c;制作屏幕的各种界面#xff0c;并将…【屏幕显示DHT11数据】 面向对象的思想编写硬件驱动程序DHT11采集环境中的温湿度数据。使用FreeRTOS提供的任务间通信、同步、互斥将DHT11的数据传递给显示任务。显示任务中使用emWin中间件制作屏幕的各种界面并将DHT11的数据显示到屏幕上。
项目开发流程 第一个项目内容屏幕显示DHT11数据 面向对象的思想编写硬件驱动程序DHT11采集环境中的温湿度数据。使用FreeRTOS提供的任务间通信、同步、互斥将DHT11的数据传递给显示任务。显示任务中使用emWin中间件制作屏幕的各种界面并将DHT11的数据显示到屏幕上。
项目框架 TFT彩屏
TFT-LCD 即薄膜晶体管液晶显示器。其英文全称为Thin Film Transistor-Liquid Crystal Display。TFT-LCD与无源 TN-LCD、STN-LCD 的简单矩阵不同它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管TFT可有效地克服非选通时的串扰使显示液晶屏的静态特性与扫描线数无关。
TFT-LCD具有亮度好、对比度高、层次感强、颜色鲜艳等特点。应用于电视、手机、电脑、平板等各种电子产品。
分辨率240*320 驱动ICILI9341 自带触摸屏电阻触摸屏 16位80并口驱动 16位真彩显示65536色 TFT彩屏引脚定义 TFT写数据 TFT读数据 TFT控制框图 DHT11模块简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术确保产品具有极高的可靠性与卓越的长期稳定性。 传感器包括一个电阻式感湿元件和一个NTC测温元件并与一个高性能8位单片机相连接。 DHT11电路图 DHT11参数
测量分辨率分别为 8bit温度、8bit湿度。 DHT11传输数据:串行接口单线双向
DHT11采用单总线协议与stm32通信。DHT11只有在接收到开始信号后才会触发温湿度采集。数据采集完毕且无开始信号后DHT11自动切换到低速模式复位信号触发DHT11从低速到高速模式
1一次完整的数据传输为40bit高位先出。
2数据格式 8bit湿度整数数据 8bit湿度小数数据 8bi温度整数数据 8bit温度小数数据 8bit校验和
3数据传送正确时校验和数据等于 “8bit湿度整数数据8bit湿度小数数据 8bi温度整数数据8bit温度小数数据”所得结果的末8位
注DHT11传输时时序非常严格不允许各种意外情况打断。
DHT11时序 (通信过程)
如下图所示用户MCU发送一次开始信号后DHT11从低功耗模式转换到高速模式等待主机开始信号结束后DHT11发送响应信号送出40bit的数据并触发一次信号采集用户可选择读取部分数据。
从模式下DHT11接收到开始信号触发一次温湿度采集如果没有接收到主机发送开始信号DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。 如下图所示总线空闲状态为高电平主机把总线拉低等待DHT11响应主机把总线拉低必须大于18毫秒保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后等待主机开始信号结束然后发送80us低电平响应信号。主机发送开始信号结束后延时等待20-40us后读取DHT11的响应信号主机发送开始信号后可以切换到输入模式或者输出高电平均可总线由上拉电阻拉高。
如上图所示总线为低电平说明DHT11发送响应信号DHT11发送响应信号后再把总线拉高80us准备发送数据。 DHT11数据位格式
如下图所示每一bit数据都以50us低电平时隙开始高电平的长短定了数据位是0还是1。如果读取响应信号为高电平则DHT11没有响应请检查线路是否连接正常。当最后一bit数据传送完毕后DHT11拉低总线50us随后总线由上拉电阻拉高进入空闲状态。 数字0信号表示方法如下图所示 数字1信号表示方法如下图所示
数字0信号与数字1信号的不同之处在于高电平的时间不同利用这点我么们可以通过设置电平时间阈值来判断信号的种类。
DHT11驱动程序
DHT11.c 配置输入输出GPIO: 复位DHT11
复位DHT11就是发送DHT11起始信号告诉传感器通讯开始。 检查DHT11是否正常
检查DHT11是否正常正常的话会在单片机发送起始信号完成后传感器返回80us低电平然后发送80us高电平。即证明DHT11工作正常该函数工作正常返回0否则返回1该函数中利用了while循环检测在一定时间内的电平变化此类用法在后面也会经常用到。 读取一位数据返回值0/1
该函数采用两个while循环是等待每个周期的电平变化先等待低电平到来后等待高电平到来延时40us后判断引脚电平来判断该位数据为1或0。之所以是40微秒是因为传感器数字0的信号持续时间为26-28us数字1的信号持续时间为70us选择一个中值来区分两种信号当然也可以选择其他值但最好在40us附近在while循环中选择循环100次也就是100us是因为防止当单片机由于某些原因迟迟收不到传感器电平信号造成死机。 读取一个字节返回值读到的数据
循环读入一个字节的数据并将每一步新加入的数据放置在最低位。 读取DHT11数据读取成功返回0失败返回1
读取数据将数据存入数组这里仅保留了温度数据的整数位注意数据较验方法校验和数据等于“8bit湿度整数数据8bit湿度小数数据 8bi温度整数数据8bit温度小数数据”所得结果的末8位。 完整版.c文件
#include dht11.h
#include delay.h#define DHT11_DelayMs(t) Delay_Ms(t)
#define DHT11_DelayUs(t) Delay_Us(t)#define DHT11_PIN_HIGH 1
#define DHT11_PIN_LOW 0 #if defined (STM32F40_41xxx)#include stm32f4xx.h
//配置输入输出GPIO//温湿度模块输入函数
//浮空输入设置IO口速度选择端口
#define __DHT11_CONFIG_IO_INPUT(DHT11) { GPIO_InitTypeDef GPIO_InitStructure; \ GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN; \GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP; \GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; \GPIO_InitStructure.GPIO_Pin DHT11-pin; \GPIO_Init(DHT11-port, GPIO_InitStructure); \}
//温湿度模块输入函数
//推挽输出设置IO口速度选择端口
#define __DHT11_CONFIG_IO_OUTPUT(DHT11) { GPIO_InitTypeDef GPIO_InitStructure; \GPIO_InitStructure.GPIO_Mode GPIO_Mode_OUT; \GPIO_InitStructure.GPIO_OType GPIO_OType_PP; \ GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP; \GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; \GPIO_InitStructure.GPIO_Pin DHT11-pin; \GPIO_Init(DHT11-port, GPIO_InitStructure); \}#define __DHT11_IO_SET(DHT11, value) { if (value DHT11_PIN_HIGH) \GPIO_SetBits(DHT11-port, DHT11-pin); \else \GPIO_ResetBits(DHT11-port, DHT11-pin); \}#define DHT11_IO_H(DHT11) {__DHT11_IO_SET(DHT11, DHT11_PIN_HIGH)}
#define DHT11_IO_L(DHT11) {__DHT11_IO_SET(DHT11, DHT11_PIN_LOW)}
#define DHT11_IO_IN(DHT11) GPIO_ReadInputDataBit(DHT11-port, DHT11-pin)#endif/******************************************************************************* brief 复位DHT11** param[in] dht11 : dht11结构体指针** return 0, 表示正常, 其他值表示失败*******************************************************************************/
//根据DHT11时序图
//复位DHT11发送DHT11起始信号告诉传感器通讯开始
static int DHT11_Rst(DHT11_t *dht11) //DHT端口复位发出起始信号IO发送
{__DHT11_CONFIG_IO_OUTPUT(dht11); //设置引脚为输出模式DHT11_IO_L(dht11); //拉低DQDHT11_DelayMs(20); //拉低至少18ms 拉低20msDHT11_IO_H(dht11); //DQ1 DHT11_DelayUs(30); //主机拉高20~40us__DHT11_CONFIG_IO_INPUT(dht11); //设置引脚为输入模式//随后主机开始读取return 0;
}//复位DHT11可以理解为开始/******************************************************************************* brief 等待DHT11的回应** param[in] dht11 : dht11结构体指针** return 0, 存在, 返回1:未检测到DHT11的存在*******************************************************************************/
//检查DHT11是否正常检查DHT11是否正常正常的话会在单片机发送起始信号完成后传感器返回80us低电平然后发送80us高电平。
static int DHT11_Check(DHT11_t *dht11) //读取引脚的状态 retry临界值
{int retry 0; while (DHT11_IO_IN(dht11) (retry 100)) { //DHT11会拉低40-80usretry;DHT11_DelayUs(1);};if (retry 100) { //超过100ms说明统计没有相应return -2;} else {retry 0;}while (!DHT11_IO_IN(dht11) (retry 100)) { //DHT11拉低后会再次拉高40-80usretry;DHT11_DelayUs(1);};if (retry 100) {return -3;}return 0;
}/******************************************************************************
以上没有问题就可以传输数据了* brief 从DHT11读取一个位** param[in] dht11 : dht11结构体指针** return 0, 1 读取一位数据返回值0/1*该函数采用两个while循环是等待每个周期的电平变化先等待低电平到来
*等待高电平到来延时40us后判断引脚电平来判断该位数据为1或0。******************************************************************************/
static uint8_t DHT11_ReadBit(DHT11_t *dht11)
{int retry 0;while (DHT11_IO_IN(dht11) (retry 100)) { //等待变为低电平retry;DHT11_DelayUs(1);}retry 0;while (!DHT11_IO_IN(dht11) (retry 100)) { //等待变高电平retry;DHT11_DelayUs(1);}DHT11_DelayUs(40);//等待40usif (DHT11_IO_IN(dht11)) {return 1;} else {return 0;}
}/******************************************************************************* brief 从DHT11读取一个字节** param[in] dht11 : dht11结构体指针** return 读到的数据*读取一个字节返回值读到的数据
循环读入一个字节的数据并将每一步新加入的数据放置在最低位。******************************************************************************/
static uint8_t DHT11_ReadByte(DHT11_t *dht11)
{uint8_t i, dat;dat 0;for (i 0; i 8; i) {dat 1;dat | DHT11_ReadBit(dht11);}return dat;
}/******************************************************************************* brief 从DHT11读取一次数据 把协议全部放进去* temp:温度值(范围:0~50°)* humi:湿度值(范围:20%~90%)** param[in] dht11 : dht11结构体指针** return 0, 表示正常, 其他值表示失败*读取DHT11数据读取成功返回0失败返回1
读取数据将数据存入数组这里仅保留了温度数据的整数位注意数据较验方法校验和数据
等于“8bit湿度整数数据8bit湿度小数数据 8bi温度整数数据8bit温度小数数据”所得结果的末8位。******************************************************************************/
int DHT11_ReadData(DHT11_t *dht11)
{if (!dht11 || !dht11-init) return -1; //初始化引脚之后uint8_t buf[5];uint8_t i;DHT11_Rst(dht11); //复位传感器if (DHT11_Check(dht11) 0) {for (i 0; i 5; i) { //读取40位数据 40位 五个字节 连续读五次buf[i] DHT11_ReadByte(dht11);}if ((buf[0] buf[1] buf[2] buf[3]) buf[4]) { //校验 相等说明传输数据么有问题dht11-humidity buf[0];dht11-temperature buf[2]; //放入温湿度}} else {return -2;}return 0;
}/******************************************************************************* brief 初始化DHT11的IO口 DQ 同时检测DHT11的存在.*DHT11初始化
在上电后对IO端口初始化和检查DHT11状态。* param[in] dht11 : dht11结构体指针** return 0, 表示正常, 其他值表示失败*******************************************************************************/
int DHT11_Init(DHT11_t *dht11, DHT11_GPIO_Port_t port, uint32_t pin) //对外提供两个接口 触发温湿度传感器 读取数据
{if(!dht11) return -1;//配置引脚默认输出
#if defined (STM32F40_41xxx)assert_param(IS_GPIO_ALL_PERIPH(port));if (port GPIOA) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); }else if (port GPIOB) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); }else if (port GPIOC) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); }else if (port GPIOD) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); }else if (port GPIOE) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); }else if (port GPIOF) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); }else if (port GPIOG) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); }else return -1;__DHT11_CONFIG_IO_OUTPUT(dht11);#endifdht11-port port;dht11-pin pin;dht11-temperature 0.0;dht11-humidity 0.0;dht11-init true;DHT11_IO_H(dht11);DHT11_Rst(dht11);return DHT11_Check(dht11);
}
DHT11.h
#ifndef __DHT11_H
#define __DHT11_H #include stdint.h
#include stdio.h
#include stdbool.h
#include stdlib.h
#include string.h#if defined (STM32F40_41xxx)#include stm32f4xx.htypedef GPIO_TypeDef* DHT11_GPIO_Port_t;#else#error dht11.h: No processor defined!#endiftypedef struct dht11_t
{DHT11_GPIO_Port_t port; //所使用的端口uint32_t pin; //所使用的引脚double temperature; //温度值double humidity; //湿度bool init; //初始化标志
}DHT11_t;int DHT11_Init(DHT11_t* dht11, DHT11_GPIO_Port_t port, uint32_t pin); //初始化DHT11 使用哪个引脚
int DHT11_ReadData(DHT11_t* dht11); //获取DHT11的数据#endif
main.c
#include main.h
DHT11_t gDht11; //定义一个温湿度结构体
char show_buffer[100];
int main(void)
{Debug_Init(115200);Delay_Init();printf(DHT11 start\r\n);LCD_Init(); //初始化屏幕LCD_Clear(RED); //屏幕显示红色Delay_Ms(1000);LCD_Clear(~RED);Delay_Ms(1000);/* 初始化DHT11 */int ret DHT11_Init(gDht11, GPIOA, GPIO_Pin_6); //DHT11接到PA6引脚上去printf(ret: %d\r\n, ret);/* 每秒读取一次温湿度传感器并通过串口发送 */while (1) {DHT11_ReadData(gDht11); //读取温湿度传感器的数值memset(show_buffer, 0, sizeof(show_buffer));sprintf(show_buffer, T: %0.2f H: %0.2f\r\n, gDht11.temperature, gDht11.humidity);printf(%s, show_buffer); //显示LCD_ShowString(0, 0, 240, 30, 24, show_buffer); //通过LCD屏幕显示Delay_Ms(1000);}
}
总结
介绍DHT11温湿度传感器及STM32版本驱动函数的编写
后续将加入freertos和emwin