STM32HAL库 DHT11驱动+0.96寸4针OLED显示

STM32HAL库 DHT11驱动+0.96寸4针OLED显示

单片机:STM32F103C8T6
软件版本:STM32CubeMX 4.20.1
单片机固件包:STM32Cube_FW_F1_V1.4.0

本代码为DHT11的驱动代码,OLED驱动相关代码请阅读以下这篇博客:STM32HAL库 0.96寸4针OLED驱动代码
本代码是参考网络上的部分程序代码编写,仅用于学习和交流。希望能给各位读者些许帮助。

根据DHT11手册,可得以下信息:
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
1.通讯过程如图所示
在这里插入图片描述
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
在这里插入图片描述
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
数字0信号表示方法如图所示:
在这里插入图片描述
数字1信号表示方法.如图所示:
在这里插入图片描述

dht11.c代码:

/*************************************************
// 文件说明:      DHT11驱动代码
// 创 建 人:     mnWu522
// 日期:         2020-2-20
// 修 改 人:                     
// 修改日期:     20xx-xx-xx
*************************************************/
#include "dht11.h"
#include "tim.h"
#include <string.h>
#include "common.h"
#include "oled.h"

uint8_t DHT_data[5];

//DHT11引脚初始化
void DHT_GPIO_Init(void)
{ 
 GPIO_InitTypeDef  GPIO_InitStruct;
  
 DHT_GPIO_CLK_ENABLE();
 GPIO_InitStruct.Pin  = DHT_DAT_PIN;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 HAL_GPIO_Init(GPIOx_DHT_PORT, &GPIO_InitStruct);
 
 DHT_DAT_ON();
}

void DHT_DAT_GPIO_Output_Init(void)
{
 GPIO_InitTypeDef  GPIO_InitStruct;
 
 DHT_GPIO_CLK_ENABLE();
 GPIO_InitStruct.Pin  = DHT_DAT_PIN;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 HAL_GPIO_Init(GPIOx_DHT_PORT, &GPIO_InitStruct);
}

void DHT_DAT_GPIO_Input_Init(void)
{
 GPIO_InitTypeDef  GPIO_InitStruct;
 
 DHT_GPIO_CLK_ENABLE();
 GPIO_InitStruct.Pin  = DHT_DAT_PIN;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 HAL_GPIO_Init(GPIOx_DHT_PORT, &GPIO_InitStruct);
}

//DHT11复位
void DHT_Reset(void)
{
 DHT_DAT_GPIO_Output_Init();
 DHT_DAT_ON();
}

//DHT11读1Byte数据
uint8_t DHT_Read_Byte(void)
{
 uint8_t i;
 uint8_t data = 0;
// DHT_DAT_GPIO_Input_Init();//DAT设置为输入
 for(i=0; i<8; i++)
 {
  data <<= 1;
  while(!READ_DHT_DAT());//每一位数据前会有一个50us的低电平时间,等待该低电平结束
  //26-28us的高电平表示该位是0,70us高电平表示该位是1
  Delay_us(30);//延时30us后检测电平状态
  if(READ_DHT_DAT())
  {
   data |= 0x01;
   while(READ_DHT_DAT());
  }
 }
 return data;
}

//DHT11读数据
void DHT_ReadData(void)
{
 uint8_t i;
 DHT_DAT_GPIO_Output_Init();//DAT设置为输出
 DHT_DAT_OFF();//低电平大于18ms发送开始信号
 Delay_ms(20);
 DHT_DAT_ON();
 Delay_us(40);//延时20-40us
 DHT_DAT_GPIO_Input_Init();//DAT设置为输入
 if(!READ_DHT_DAT())
 {
  while(!READ_DHT_DAT());
 }
 while(READ_DHT_DAT());
 for(i=0; i<5; i++)
 {
  DHT_data[i] = DHT_Read_Byte();
 }
 Delay_us(50);
}

void DHT_ShowData(void)
{
 int i,j,k,p;
 DHT_ReadData();
 DHT_Reset();
 OLED_ALL_Clear();
 for(i=0; i<5; i++)
 {
  j = 0;p = (int)DHT_data[i];
  if(p/100 != 0)
  {
   k = p/100;
   OLED_Draw_8_6_ASCII(i,j,16+k);
   j += 6;p = p - k * 100;
   k = p/10;
   OLED_Draw_8_6_ASCII(i,j,16+k);
   j += 6;p = p - k * 10;
   OLED_Draw_8_6_ASCII(i,j,16+p);
  }
  else if(p/10 != 0)
  {
   k = p/10;
   OLED_Draw_8_6_ASCII(i,j,16+k);
   j += 6;p = p - k * 10;
   OLED_Draw_8_6_ASCII(i,j,16+p);
  }
  else
  {
   OLED_Draw_8_6_ASCII(i,j,16+p);
  }
 }
}

dht11.h代码:

#ifndef  __DHT11_H__
#define  __DHT11_H__

#include "stm32f1xx_hal.h"

///
#define    DHT_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOB_CLK_ENABLE()

#define    GPIOx_DHT_PORT                GPIOB
#define    DHT_DAT_PIN                   GPIO_PIN_4
#define    DHT_DAT_ON()                  HAL_GPIO_WritePin(GPIOx_DHT_PORT, DHT_DAT_PIN, GPIO_PIN_SET)
#define    DHT_DAT_OFF()                 HAL_GPIO_WritePin(GPIOx_DHT_PORT, DHT_DAT_PIN, GPIO_PIN_RESET)
#define    DHT_DAT_TOGGLE()              HAL_GPIO_TogglePin(GPIOx_DHT_PORT, DHT_DAT_PIN)

#define    READ_DHT_DAT()                HAL_GPIO_ReadPin(GPIOx_DHT_PORT, DHT_DAT_PIN)
///
extern uint8_t DHT_data[5];

void DHT_GPIO_Init(void);
void DHT_DAT_GPIO_Output_Init(void);
void DHT_DAT_GPIO_Input_Init(void);
void DHT_Reset(void);
uint8_t DHT_Read_Byte(void);
void DHT_ReadData(void);
void DHT_ShowData(void);

#endif

注意事项:
读取DHT11模块数据周期不易小于2s。(即运行一次DHT_ShowData();后应加上Delay_ms(2000);形成有至少两秒的延时)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,你需要先准备以下硬件设备: - STM32开发板 - DHT11温湿度传感器 - OLED显示屏 然后按照以下步骤进行操作: 1. 连接DHT11传感器和STM32开发板 将DHT11传感器的VCC引脚连接至STM32的3.3V电源,GND引脚连接至STM32的GND,DATA引脚连接至STM32的任意GPIO口(例如PA0)。 2. 连接OLED显示屏和STM32开发板 将OLED的VCC引脚连接至STM32的3.3V电源,GND引脚连接至STM32的GND,SCL引脚连接至STM32的SCL(例如PB10),SDA引脚连接至STM32的SDA(例如PB11)。 3. 编写程序 使用STM32HAL库DHT11的库函数读取温湿度数据,并使用OLED屏幕显示。以下是一个简单的代码示例: ```c #include "stm32f1xx_hal.h" #include "dht11.h" #include "ssd1306.h" #define OLED_WIDTH 128 #define OLED_HEIGHT 64 I2C_HandleTypeDef hi2c1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); ssd1306_Init(&hi2c1); DHT11_Init(GPIOA, GPIO_PIN_0); char buffer[16]; while (1) { DHT11_Read(); int temp = DHT11_GetTemperature(); int humi = DHT11_GetHumidity(); sprintf(buffer, "Temp: %d C", temp); ssd1306_SetCursor(0, 0); ssd1306_WriteString(buffer, Font_7x10, White); sprintf(buffer, "Humi: %d%%", humi); ssd1306_SetCursor(0, 16); ssd1306_WriteString(buffer, Font_7x10, White); ssd1306_UpdateScreen(); HAL_Delay(1000); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInit; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1; PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } static void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } ``` 4. 编译并下载程序 使用STM32的开发环境(如Keil、CubeMX等)编译程序并下载到STM32开发板中。 5. 测试 将DHT11传感器放置在室内,观察OLED屏幕上的温湿度数据是否正确显示。 以上就是使用STM32DHT11OLED屏幕实现温湿度监测的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值