目录
所用的工具:
知识概括:
DHT11介绍:
DHT11性能说明:
接口说明
电源引脚
串行接口
工程创建
1、设置RCC
2、时钟设置
3、项目文件设置
4、设置IO口(DATA)
5、TIM时钟配置
6、USART配置
程序编写:
1、TIM3实现微秒(us)级延时函数:
2、IO口配置
3、DHT11检测起始信号(这里的DHT11_LOW,DHT11_HIGH 在下面的的第8点)
4、DHT11检测响应信号(这里的DHT11_IO_IN在下面的第8点)
5、DHT11读取一bit数据
6、DHT11读取一个Byte数据
7、DHT11读取湿度和温度的数据
8、IO口输出高、低电平以及读取IO口电平定义和需要添加的头文件
9、温度、湿度和数据缓存数组的声明,函数的声明
10、主循环,(DHT11数据的读取和串口发送)
效果展示
1、将程序下载到开发板
2、串口助手查看数据编辑
总结
附录(完整程序)
所用的工具:
1、芯片:STM32F103C8T6
2、软件:STM32CubeMX软件
3、IDE : MDK_Keil软件
知识概括:
DHT11基本知识和原理
DHT11通讯方式
STM32CubeTIM和USART的配置
DHT11数据采集实现
DHT11介绍:
DHT11性能说明:
接口说明
建议连接线短语20m时用5K的上拉电阻,大于20m时根据实际情况使用合适的上拉电阻
电源引脚
DHT11的供电电压为 3.3~5v。传感器上电后,要等待1s,以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100uf电容,用以去耦滤波。
串行接口
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。
工程创建
1、设置RCC
2、时钟设置
3、项目文件设置
- 1 设置项目名称
- 2 设置存储路径
- 3 选择所用IDE
1、 复制所用文件的.C和.H
2、每个功能生成独立的.C和.H文件
4、设置IO口(DATA)
第二步的Moed设置GPIO_OUTPUT和GPIO_INPUT都可以,因为DHT11是单线双向的 ,所以在编写程序时我们需要改写的它IO模式。
5、USART配置
第二步 Mode设置为异步通信
程序编写:
首先来编写函数部分:
1、微秒(us)级延时函数:
/**
* @brief us级延时函数
* @param delay 控制延时的时长
* @retval 无
*/
void Delay_us(uint32_t udelay)
{
uint32_t startval,tickn,delays,wait;
startval = SysTick->VAL;
tickn = HAL_GetTick();
delays =udelay * 72;
if(delays > startval)
{
while(HAL_GetTick() == tickn)
{
}
wait = 72000 + startval - delays;
while(wait < SysTick->VAL)
{
}
}
else
{
wait = startval - delays;
while(wait < SysTick->VAL && HAL_GetTick() == tickn)
{
}
}
}
该函数用了逻辑分析仪进行了比较,示图如下:
100us:
10us:
1us:
2、IO口配置
/**
* @brief DATA引脚(PA7)设置为输出模式
* @param 无
* @retval 无
*/
void DHT11_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
* @brief DATA引脚(PA7)设置为输入模式
* @param 无
* @retval 无
*/
void DHT11_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
3、DHT11检测起始信号(这里的DHT11_LOW,DHT11_HIGH 在下面的的第8点)
/**
* @brief DHT11检测起始信号
* @param 无
* @retval 无
*/
void DHT11_Strat(void)
{
DHT11_OUT(); //PA7设置为输出模式
DHT11_LOW; //主机拉低总线
HAL_Delay(20); //延迟必须大于18ms ;
DHT11_HIGH; //主机拉高总线等待DHT11响应
Delay_us(30);
}
4、DHT11检测响应信号(这里的DHT11_IO_IN在下面的第8点)
/**
* @brief DHT11发送响应信号
* @param 无
* @retval 返回值0/1 0:响应成功 1:响应失败
*/
uint8_t DHT11_Check(void)
{
uint8_t retry = 0 ;
DHT11_IN();
//采用while循环的方式检测响应信号
while(DHT11_IO_IN && retry <100) // DHT11会拉低 40us ~80us
{
retry++;
Delay_us(1);//1us
}
if(retry>=100) //判断当DHT11延迟超过80us时return 1 , 说明响应失败
{return 1;}
else retry = 0 ;
while(!DHT11_IO_IN && retry<100)// // DHT11拉低之后会拉高 40us ~80us
{
retry++;
Delay_us(1);//1us
}
if(retry>=100)
{return 1;}
return 0 ;
}
5、DHT11读取一bit数据
/**
* @brief DHT11读取一位数据
* @param 无
* @retval 返回值0/1 1:读取成功 0:读取失败
*/
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry = 0 ;
while(DHT11_IO_IN && retry <100)//同上采用while循环的方式去采集数据
{
retry++;
Delay_us(1);
}
retry = 0 ;
while(!DHT11_IO_IN && retry<100)
{
retry++;
Delay_us(1);
}
Delay_us(40); //结束信号,延时40us
if(DHT11_IO_IN) return 1; //结束信号后,总线会被拉高 则返回1表示读取成功
else
return 0 ;
}
6、DHT11读取一个Byte数据
/**
* @brief DHT11读取一个字节数据
* @param 无
* @retval 返回值:dat 将采集到的一个字节的数据返回
*/
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 ;
}
7、DHT11读取湿度和温度的数据
/**
* @brief DHT11读取数据
* @param temp:温度值 humi :湿度值
* @retval 返回值0/1 0:读取数据成功 1:读取数据失败
*/
uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi)
{
uint8_t buf[5]; //储存五位数据
uint8_t i;
DHT11_Strat(); //起始信号
if(DHT11_Check() == 0) //响应信号
{
for(i=0; i<5; i++)
{
buf[i] = DHT11_Read_Byte();
}
if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校验数据
{
*humi = buf[0]; // 湿度
*temp = buf[2]; // 温度
}
}else return 1;
return 0 ;
}
以上就是需要用到的函数部分的编写,接下来是一些声明和定义:
8、IO口输出高、低电平以及读取IO口电平定义和需要添加的头文件
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define DHT11_HIGH HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_SET) //输出高电平
#define DHT11_LOW HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_RESET)//输出低电平
#define DHT11_IO_IN HAL_GPIO_ReadPin(GPIOA, DHT11_Pin)//读取IO口电平
/* USER CODE END PD */
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
9、温度、湿度和数据缓存数组的声明,函数的声明
/* USER CODE BEGIN 1 */
uint8_t temperature = 1; //温度
uint8_t humidity = 1; //湿度
uint8_t aTXbuf[32]; //串口发送缓存数组
DHT11_Strat(void);
/* USER CODE END 1 */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Delay_us(uint16_t delay); //us级延时函数
//DHT11_DATA ,IO口设置为输出模式(这里的IO口指的是STM32CubeMX中配置的IO口)
void DHT11_OUT(void);
void DHT11_IN(void); //DHT11_Data IO设置为输入模式
void DHT11_Strat(void); //主机发出起始信号
uint8_t DHT11_Check(void); //DHT11发送响应信号
uint8_t DHT11_Read_Bit(void); //读取DHT11一个BIT的数据
uint8_t DHT11_Read_Byte(void); //读取DHT11一个Byte的数据
uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi); //读取DHT11湿度和温度的数据
/* USER CODE BEGIN PFP */
10、主循环,(DHT11数据的读取和串口发送)
while (1)
{
//接收DHT11的温度和湿度的值
DHT11_Read_Data(&temperature , &humidity);
//将数据存放到aTXbuf这个数组当中去。 不了解"sprintf"用法的可以去查一下...
sprintf((char*)aTXbuf,"温度:%d℃,湿度: %d %%\r\n" ,temperature ,humidity);
//将数据通过串口发送到主机上的串口助手
HAL_UART_Transmit(&huart1, aTXbuf, strlen((const char*)aTXbuf), 200);
//延时500ms
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
到这里DHT11的程序就编写完了 ,下面就来看看效果吧
效果展示
1、将程序下载到开发板
文章来源:https://www.toymoban.com/news/detail-491665.html
2、串口助手查看数据
总结
通过本次DHT11温湿度传感器的学习,掌握了单线双向的数据通信方式,DHT11和主机之间数据通讯过程,而且在此过程中要注意延时函数的把控精度,在编写程序中DHT11数据读取方式,数据传输方式和数据存储方式,以及微秒级延迟函数的编写,本设计参考正点原子探索者开发板教程和STM32Cube高效开发指南(高级篇)。文章来源地址https://www.toymoban.com/news/detail-491665.html
附录(完整程序)
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define DHT11_HIGH HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_SET)
#define DHT11_LOW HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_RESET)
#define DHT11_IO_IN HAL_GPIO_ReadPin(GPIOA, DHT11_Pin)
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Delay_us(uint16_t delay);
void DHT11_OUT(void);
void DHT11_IN(void);
void DHT11_Strat(void);
uint8_t DHT11_Check(void);
uint8_t DHT11_Read_Bit(void);
uint8_t DHT11_Read_Byte(void);
uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t temperature = 1 ;
uint8_t humidity = 1;
uint8_t aTXbuf[32] ;
/* 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_TIM3_Init();
/* USER CODE BEGIN 2 */
DHT11_Strat();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
DHT11_Read_Data(&temperature , &humidity);
sprintf((char*)aTXbuf,"温度:%d℃ , 湿度:%d %% \r\n" ,temperature ,humidity);
HAL_UART_Transmit(&huart1, aTXbuf, strlen((const char*)aTXbuf), 200);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
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_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void Delay_us(uint16_t delay)
{
__HAL_TIM_DISABLE(&htim3);
__HAL_TIM_SET_COUNTER(&htim3,0);
__HAL_TIM_ENABLE(&htim3);
uint16_t curCnt=0;
while(1)
{
curCnt=__HAL_TIM_GET_COUNTER(&htim3);
if(curCnt>=delay)
break;
}
__HAL_TIM_DISABLE(&htim3);
}
void DHT11_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void DHT11_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void DHT11_Strat(void)
{
DHT11_OUT();
DHT11_LOW;
HAL_Delay(20);
DHT11_HIGH;
Delay_us(30);
}
uint8_t DHT11_Check(void)
{
uint8_t retry = 0 ;
DHT11_IN();
while(DHT11_IO_IN && retry <100)
{
retry++;
Delay_us(1);//1us
}
if(retry>=100)
{return 1;}
else retry = 0 ;
while(!DHT11_IO_IN && retry<100)
{
retry++;
Delay_us(1);//1us
}
if(retry>=100)
{return 1;}
return 0 ;
}
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry = 0 ;
while(DHT11_IO_IN && retry <100)
{
retry++;
Delay_us(1);
}
retry = 0 ;
while(!DHT11_IO_IN && retry<100)
{
retry++;
Delay_us(1);
}
Delay_us(40);
if(DHT11_IO_IN) return 1;
else
return 0 ;
}
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 ;
}
uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_Strat();
if(DHT11_Check() == 0)
{
for(i=0; i<5; i++)
{
buf[i] = DHT11_Read_Byte();
}
if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4])
{
*humi = buf[0];
*temp = buf[2];
}
}else return 1;
return 0 ;
}
/* USER CODE END 4 */
到了这里,关于[STM32]HAL库STM32CubeMX+DHT11温湿度传感器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!