STM32L431(CubeMX)使用DHT11读取环境温度与湿度并通过串口打印

12 篇文章 3 订阅
1 篇文章 0 订阅

一、开发平台

·小熊派(STM32L431)
·DHT11数字温湿度传感器
·keil5
·cubemx
·使用HAL库

软件下载

1、keil5

在官网下载(注意下载正确版本,STM32属于MDK-Arm):https://www.keil.com/download/product/在这里插入图片描述

2、CubeMx

在官网下载:https://www.st.com/zh/development-tools/stm32cubemx.html
在这里插入图片描述

二、DHT11介绍

用户单片机发送一次开始信号后,DHT11从低功耗模式转换到高速模式,待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信采集。
请添加图片描述
DHT11接线:

DHT11STM32
VCC5V
GNDGND
DATAPC9

三、新建工程步骤

1、CubeMx

1、打开CubeMx,选择芯片类型
请添加图片描述
我这里用的是小熊派(STM32L431RCT)
请添加图片描述
配置RCC为外部高速时钟。
请添加图片描述
在这里插入图片描述
请添加图片描述
配置串口1,串口配置按默认来就可以了。
请添加图片描述
因为我的DHT11接在PC9引脚上,所以配置引脚PC9为GPIO_OUTPUT,并把标签改为DHT11,方便后续的编程。
请添加图片描述
对PC9引脚进行配置
在这里插入图片描述

配置时钟树,STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可
请添加图片描述
请添加图片描述
最后点击Genrate code
请添加图片描述
至此工程建立完毕,点击open project,自动打开keil5
请添加图片描述

2、Keil5

1、点击Build,等待工程编译完成,0 error后点击工程文件管理,添加hareware文件夹,将驱动文件添加进去。
请添加图片描述
2、点击魔术棒,添加include路径,添加dht11.h所在文件夹路径,再次编译。

请添加图片描述
添加重定向printf代码
在这里插入图片描述

四、代码部分

1、dht11.h

#ifndef __DHT11_H__
#define __DHT11_H__
 
#include "main.h"
#include "tim.h"
#include "gpio.h"
#include "stm32l4xx_hal.h"

#define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW 	HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,GPIO_PIN_RESET)
#define DHT11_DQ_IN	 HAL_GPIO_ReadPin(DHT11_GPIO_Port,DHT11_Pin)

extern uint16_t temperature;
extern uint16_t humidity;
extern char temp,humi;

void delay_us(uint16_t us);
//IO方向设置
void DHT11_IO_IN(void);
void DHT11_IO_OUT(void);

   	
uint8_t DHT11_Init(void);//初始化DHT11
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi);//读取温湿度
uint8_t DHT11_Read_Byte(void);//读出一个字节
uint8_t DHT11_Read_Bit(void);//读出一个位
uint8_t DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11  

#endif

2、dht11.c

#include "dht11.h"

uint16_t temperature;
uint16_t humidity;
char temp,humi;

//微秒延时
void delay_us(uint16_t us)
{     
	uint16_t differ = 0xffff-us-5;				
	__HAL_TIM_SET_COUNTER(&htim7,differ);	//设定TIM1计数器起始值
	HAL_TIM_Base_Start(&htim7);		//启动定时器	
	
	while(differ < 0xffff-5){	//判断
		differ = __HAL_TIM_GET_COUNTER(&htim7);		//查询计数器的计数值
	}
	HAL_TIM_Base_Stop(&htim7);
}

//IO方向设置
void DHT11_IO_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = DHT11_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
}

void DHT11_IO_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = DHT11_Pin;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(DHT11_GPIO_Port,&GPIO_InitStructure);
}


//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//设置为输出
	DHT11_DQ_OUT_LOW; 	//拉低DQ
	HAL_Delay(20);    	//拉低至少18ms
	DHT11_DQ_OUT_HIGH; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
}

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void) 	   
{   
	uint8_t retry=0;
	DHT11_IO_IN();      //设置为输出	 
	while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
	while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}

//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit(void) 			 
{
 	uint8_t retry=0;
	while(DHT11_DQ_IN&&retry<100)//等待变为低电平
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待变高电平
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}

//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)    
{        
	uint8_t i,dat;
	dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi)    
{        
 	uint8_t buf[5];
	uint8_t i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=(buf[0]<<8) + buf[1];
			*temp=(buf[2]<<8) + buf[3];
		}
	}else return 1;
	return 0;	    
}

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在     	 
uint8_t DHT11_Init(void)
{ 
  DHT11_Rst();
	return DHT11_Check();
}


3、printf重定向

添加在usart.c中

/* USER CODE BEGIN 1 */
#if 1
#include <stdio.h>

int fputc(int ch, FILE *stream)
{
    /* 堵塞判断串口是否发送完成 */
    while((USART1->ISR & 0X40) == 0);

    /* 串口发送完成,将该字符发送 */
    USART1->TDR = (uint8_t) ch;

    return ch;
}
#endif
/* USER CODE END 1 */

4、mian.c

/* USER CODE BEGIN Includes */
#include "dht11.h"
#include "stdio.h"
/* USER CODE END Includes */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM7_Init();
  /* USER CODE BEGIN 2 */
	while(DHT11_Init())													//初始化DHT11
			{
				printf("DHT11 初始化失败!\r\n");
				HAL_Delay(500);
			}
			printf("DHT11 初始化成功!\r\n");
			
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
	
  {
    /* USER CODE END WHILE */
		uint8_t res = DHT11_Read_Data(&temperature,&humidity);		//设置缓存区
		if(res == 0)	//判断是否读取到温湿度数据
		 {
				DHT11_Read_Data(&temperature,&humidity); 	//读取温湿度数据
				printf("DHT11 Temperature = %d.%d ℃\r\n",temperature>>8,temperature&0xff);
				printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);

		 }
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

五、运行效果

下载程序后通过串口助手可以看到
在这里插入图片描述
至此,本实验完成。

  • 15
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
STM32F407单片机读写OneWire_DHT11湿度传感器(串口屏显示)软件工程源码,可以做为你的学习设计参考。 int main(void) { /* 复位所有外设,初始化Flash接口和系统滴答定时器 */ HAL_Init(); /* 配置系统时钟 */ SystemClock_Config(); /* 初始化串口并配置串口中断优先级 */ MX_DEBUG_USART_Init(); HMI_USARTx_Init(); DHT11_Init(); /* 无限循环 */ while (1) { /*调用DHT11_Read_TempAndHumidity读取湿度,若成功则输出该信息*/ if(DHT11_Read_TempAndHumidity(&DHT11_Data)==SUCCESS) { HMI_value_setting("page1.gross.val",DHT11_Data.humidity*10); HMI_value_setting("page1.net.val",DHT11_Data.temperature*10); printf("读取DHT11成功!-->湿度为%.1f %RH ,温度为 %.1f℃ \n",DHT11_Data.humidity,DHT11_Data.temperature); } else { printf("读取DHT11信息失败\n"); } HAL_Delay(1000); } } /** * 函数功能: 向串口屏发送数据 * 输入参数: 无 * 返 回 值: 无 * 说 明: 无 */ void HMI_value_setting(const char *val_str,uint32_t value) { uint8_t tmp_str[30]={0}; uint8_t i; sprintf((char *)tmp_str,"%s=%d",val_str,value); for(i=0;iDR=tmp_str[i]; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); } HMI_USARTx->DR=0xFF; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); HMI_USARTx->DR=0xFF; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); HMI_USARTx->DR=0xFF; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); } /** * 函数功能: 向串口屏发送浮点数据 * 输入参数: 无 * 返 回 值: 无 * 说 明: 无 */ void HMI_string_setting(const char *val_str,int32_t value) { uint8_t tmp_str[50]={0}; uint8_t i; float temp=(float)value; sprintf((char *)tmp_str,"%s=\"%.1f\"",val_str,temp/100); for(i=0;iDR=tmp_str[i]; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); } HMI_USARTx->DR=0xFF;
好的,我可以为您提供一些代码和步骤,但在开始之前,您需要先了解一下DHT11的工作原理和STM32L431的相关知识。 DHT11是一种数字温湿度传感器,它有一个单一的数据线,通过该线传输温湿度数据。在STM32L431中,您可以使用GPIO模块来操作该数据线。 下面是实现该功能的步骤和代码: 1. 在CubeMX中配置STM32L431的GPIO,USART和TIM模块。将DHT11的数据线连接到其中一个GPIO引脚。 2. 在main函数中初始化GPIO和USART模块,并启动定时器。 ```c #include "main.h" #include "stm32l4xx_hal.h" #include <stdio.h> UART_HandleTypeDef huart2; TIM_HandleTypeDef htim2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); static void MX_TIM2_Init(void); int main(void) { /* MCU 基础模块初始化 */ HAL_Init(); /* 系统时钟初始化 */ SystemClock_Config(); /* GPIO 初始化 */ MX_GPIO_Init(); /* USART 初始化 */ MX_USART2_UART_Init(); /* 定时器初始化 */ MX_TIM2_Init(); /* 启动定时器 */ HAL_TIM_Base_Start_IT(&htim2); while (1) { /* 循环等待定时器中断 */ } } ``` 3. 在定时器中断处理函数中读取DHT11的温度和湿度数据,并将其发送到串口。在每个两秒钟中断中,发送温度或湿度数据。 ```c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint8_t flag = 0; static uint8_t cnt = 0; static uint8_t data[5] = {0}; if (htim == &htim2) { if (cnt == 0) { /* 发送读取DHT11数据的信号 */ HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET); HAL_Delay(18); HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_SET); HAL_Delay(40); HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET); /* 等待DHT11响应 */ HAL_Delay(40); /* 切换到输入模式 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DHT11_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct); /* 读取DHT11数据 */ uint8_t i; for (i = 0; i < 5; i++) { data[i] = 0; for (uint8_t j = 0; j < 8; j++) { while (HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_RESET) ; HAL_Delay(30); if (HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_SET) data[i] |= (1 << (7 - j)); while (HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_SET) ; } } /* 切换到输出模式 */ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct); /* 校验数据 */ if ((data[0] + data[1] + data[2] + data[3]) == data[4]) { flag = 1; } } /* 发送数据到串口 */ if (flag == 1) { if (cnt == 0) { printf("Temperature: %d\n", data[2]); } else { printf("Humidity: %d\n", data[0]); } cnt++; if (cnt == 2) { cnt = 0; flag = 0; } } } } ``` 在以上代码中,我们使用了HAL库提供的函数来读取DHT11的数据,并使用串口输出数据。同时,我们使用了定时器中断来触发读取数据和发送数据的操作。 希望这些代码能够对您有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值