基于STM32的温湿度传感器(DHT11)+OLED屏显示(超详细)

您所在的位置:网站首页 温度计上的湿度怎么读 基于STM32的温湿度传感器(DHT11)+OLED屏显示(超详细)

基于STM32的温湿度传感器(DHT11)+OLED屏显示(超详细)

2024-07-10 12:46| 来源: 网络整理| 查看: 265

目录

前言

一、前期准备

(一)软件环境准备

(二)硬件准备

二、接线图表

三、温湿度传感器(DHT11)驱动

(一)原理

(二)代码解析

1. void DHT_Init_InPut(void)函数

2. void DHT_Init_OutPut(void)函数

3. void DHT_Start(void)函数

4. uint16_t DHT_Scan(void)函数

5. uint16_t DHT_ReadBit(void)函数

6. uint16_t DHT_ReadByte(void)函数

7. uint16_t DHT_ReadData(uint8_t buffer[5])函数

四、OLED显示屏驱动(主要函数、I2C协议)

1. OLED_ShowChar函数

2. OLED_ShowString函数

3. OLED_Pow函数

4. OLED_ShowNum函数

5. OLED_ShowFNum函数

6. OLED_ShowCC_F16x16函数

五、效果展示

六、总结 

七、完整代码

前言

本文主要说明温湿度传感器(DHT11)在STM32下如何使用,并且结合OLED屏来达到显示的效果。喜欢的话可以点个赞和收藏噢!!以下内容均为查询相关资料撰写而成,如有侵权,请联系作者。

一、前期准备 (一)软件环境准备

编译工具为Keil5,对应芯片为:STM32F103C8

(二)硬件准备

1. STM32模块

2. OLED显示屏

3. 温湿度传感器(DHT11)

4. ST-Link V2(USB口)仿真器

5. 适量杜邦线

大约11根母对母杜邦线

二、接线图表

STM32 ST-LinkOLED屏DHT113V33.3VSWOSWDIOSWCLKSWCLKGNDGNDPB9SDAPB8SCL3.3VCCGGND3.3+PB11outG- 三、温湿度传感器(DHT11)驱动 (一)原理

        DHT11工作原理是基于内部的湿度传感器和温度传感器,通过检测这两个传感器的信号变化,将湿度和温度转换为数字信号输出。它采用简单的串行通信协议(后面补充)与外部设备通信,发送包含温湿度数据的数据帧,用户则获取数据帧进行相关的处理使用。

      经典应用电路图如图1所示

 图1

        DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:         一次完整的数据传输为40bit,高位先出。         数据格式:                 8bit湿度整数数据+8bit湿度小数数据                 +8bi温度整数数据+8bit温度小数数据                 +8bit校验和数据传送正确时校验和         数据等于“8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据” 所得结果的末8位。用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。       通讯过程如图2所示

图2  

        总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。

图3 

        总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1。格式见下面图示。如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常。当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。

      数字0信号表示方法如图4所示

图4 

      数字1信号表示方法.如图5所示

图5 

补充内容:

        串行通信协议是一种在数据传输中将信息逐位发送的通信方式。对于DHT11传感器而言,它使用的是一种简单的串行通信协议,通常是通过单个数据线与外部设备进行通信。具体来说,DHT11使用串行通信协议与外部设备通信的过程包括以下几个步骤:         启动信号: 外部设备发送一个启动信号给DHT11传感器,以指示开始通信的准备阶段。         数据传输: DHT11传感器根据约定的协议,将温湿度数据以串行的形式发送给外部设备。这些数据以特定的格式组织,例如先发送湿度值,然后发送温度值,或者相反。         校验: 在数据传输完成后,外部设备可能会对接收到的数据进行校验,以确保数据的完整性和准确性。通常使用校验和或循环冗余校验(CRC)等技术来实现校验。         应答: 在数据传输完成后,DHT11可能会发送一个应答信号给外部设备,以表示数据传输的成功或失败状态。

(二)代码解析 1. void DHT_Init_InPut(void)函数

函数介绍:

这个函数用于将连接到DHT11传感器的GPIO引脚配置为浮空输入模式。 使用了STM32的GPIO初始化结构体(GPIO_InitStructure)来配置GPIO的模式、引脚、速度等参数。

代码:

void DHT_Init_InPut(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } 2. void DHT_Init_OutPut(void)函数

函数介绍:

这个函数将连接到DHT11传感器的GPIO引脚配置为推挽输出模式。 同样使用了GPIO初始化结构体进行配置。

代码:

void DHT_Init_OutPut(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } 3. void DHT_Start(void)函数

函数介绍:

这个函数用于启动与DHT11传感器的通信。 首先调用了DHT_Init_OutPut()将引脚配置为输出模式,然后拉低总线一段时间(19ms),再拉高总线(20us),最后将引脚配置为输入模式。

代码:

void DHT_Start(void) { DHT_Init_OutPut(); GPIO_ResetBits(GPIOB, GPIO_Pin_11); // 拉低总线 Delay_us(19000); GPIO_SetBits(GPIOB, GPIO_Pin_11); // 拉高总线 Delay_us(20); DHT_Init_InPut(); } 4. uint16_t DHT_Scan(void)函数

函数介绍:

这个函数用于读取连接到DHT11传感器的GPIO引脚的当前状态,即读取传感器的响应状态。

代码:

uint16_t DHT_Scan(void) { return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); // 返回读取数据 } 5. uint16_t DHT_ReadBit(void)函数

函数介绍:

这个函数用于从DHT11传感器读取单个位。 它会等待传感器将数据线拉高,然后延时一段时间后再读取数据线的状态,以确定位值。

代码:

uint16_t DHT_ReadBit(void) { while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == RESET); Delay_us(40); if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET) { while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET); return 1; } else { return 0; } } 6. uint16_t DHT_ReadByte(void)函数

函数介绍:

这个函数用于从DHT11传感器读取一个字节(8位)的数据。 它通过调用DHT_ReadBit()函数8次,将每一位数据组装成一个完整的字节。

代码:

uint16_t DHT_ReadByte(void) { uint16_t i, data = 0; for(i = 0; i < 8; i++) { data 0; i--) { if(i == Length - FLength) { OLED_ShowChar(Line, Column + i + flag, '.'); flag = 0; } OLED_ShowChar(Line, Column + i + flag, Number2/OLED_Pow(10, Length-i)%10+'0'); } } 6. OLED_ShowCC_F16x16函数

函数介绍:

功能:在指定的行和列位置显示一个汉字(16x16像素)。 参数:

        Line:行位置,范围为1到4。         Column:列位置,范围为1到16。         num:要显示的汉字在字库中的索引。 这个函数类似于OLED_ShowChar(),但是专门用于显示汉字,字库中每个汉字占16个字节,前8个字节表示汉字的上半部分,后8个字节表示下半部分。

代码: 

void OLED_ShowCC_F16x16(uint8_t Line, uint8_t Column, uint8_t num) { uint8_t i; OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分 for (i = 0; i < 16; i++) { OLED_WriteData(CC_F16x16[num*2][i]); //显示上半部分内容 } OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分 for (i = 0; i < 16; i++) { OLED_WriteData(CC_F16x16[num*2][i + 16]); //显示下半部分内容 } } 五、效果展示

基于STM32的温湿度传感器+OLED屏显示的测试视频(有杂音,耳机党请注意)

六、总结 

本文章主要讲的是通过使用STM32实现了对DHT11温湿度传感器的数据采集和显示。通过对GPIO的配置和延时函数的使用,我们成功地与DHT11传感器进行了通信,并读取了温度和湿度数据。在软件开发方面,我们编写了针对DHT11传感器的初始化、数据读取和校验的函数,并成功地将获取到的数据显示在OLED屏幕上,使用户能够直观地了解当前环境的温度和湿度情况。

七、完整代码

压缩包连接:https://download.csdn.net/download/D102428/89078308

main.c

#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "DHT11.h" int main() { OLED_Init(); uint8_t buffer[5]; float h, t; OLED_ShowCC_F16x16(2, 1, 2); // 温 OLED_ShowCC_F16x16(2, 3, 4); // 度 OLED_ShowChar(2, 5, ':'); OLED_ShowCC_F16x16(3, 1, 3); // 湿 OLED_ShowCC_F16x16(3, 3, 4); // 度 OLED_ShowChar(3, 5, ':'); while(1) { if(DHT_ReadData(buffer) == 0) { h = buffer[0] + buffer[1] / 10.0; t = buffer[2] + buffer[3] / 10.0; OLED_ShowFNum(2, 6, t, 3, 1); OLED_ShowCC_F16x16(2, 11, 0); // ℃ OLED_ShowFNum(3, 6, h, 3, 1); OLED_ShowCC_F16x16(3, 11, 1); // % } else { OLED_Clear(); OLED_ShowString(2, 6, "ERROR"); } } }

 DHT11.h

#ifndef _DHT11_H #define _DHT11_H void DHT_Init_InPut(void); void DHT_Init_OutPut(void); void DHT_Start(void); uint16_t DHT_Scan(void); uint16_t DHT_ReadBit(void); uint16_t DHT_ReadByte(void); uint16_t DHT_ReadData(uint8_t buffer[5]); #endif

DHT11.c

#include "stm32f10x.h" // Device header #include "Delay.h" void DHT_Init_InPut(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void DHT_Init_OutPut(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void DHT_Start(void) { DHT_Init_OutPut(); GPIO_ResetBits(GPIOB, GPIO_Pin_11); // 拉低总线 Delay_us(19000); GPIO_SetBits(GPIOB, GPIO_Pin_11); // 拉高总线 Delay_us(20); DHT_Init_InPut(); } uint16_t DHT_Scan(void) { return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); // 返回读取数据 } uint16_t DHT_ReadBit(void) { while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == RESET); Delay_us(40); if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET) { while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET); return 1; } else { return 0; } } uint16_t DHT_ReadByte(void) { uint16_t i, data = 0; for(i = 0; i < 8; i++) { data


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3