完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32F103 HAL库 DHT11温度传感器实验
绝对不坑人,保证有用,亲测有效。 作为刚刚接触STM32的小白,我深知找不到非常有效的参考资料的痛苦,同时也避免以后忘记相关的方法,因此写下这篇博客,作为学习笔记。 元器件准备:由于我使用的是野火的STM32F103mini开发板,因此没有购买单独的温度传感器模块,使用了自带的温度传感器。 对于DHT11的资料介绍就不在这里赘述,我相信你肯定已经找到了许多相关资料,我们废话少说,直接上代码。 第一部分:CUBEMX 配置 KEY1,KEY2 用于产生按键中断 LED1,LED2 是开发板上的LED,用于按键中断实验,也用于发送提示信息 Beep 是蜂鸣器的引脚,蜂鸣器用于在温度异常的时候发出报警信号 实验需要使用串口,用户指令通过串口发送到单片机,单片机的信息通过串口发送到上位机,串口的具体配置如下: 这部分保持默认配置即可。 需要使能串口接收中断。用于处理用户指令。 DHT11引脚的配置。 其他的引脚只需要配置为默认的推挽输出即可。 时钟以及工程配置不在赘述。 接下来是代码部分。 /* /*DHT11.C文件*/ # include "DHT11.h" # include "tim.h" /*根据DHT11的工作特性,需要改变引脚的工作状态*/ // 输入模式 void DHT11_IO_IN(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_0; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(GPIOC,&GPIO_InitStructure); } // 输出模式 void DHT11_IO_OUT(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_0; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC,&GPIO_InitStructure); } /* 触发DHT11工作状态的信号,涉及到IO口电平的拉高以及拉低, 一次在.h文件中进行宏定义,方便程序移植*/ void DHT11_Start (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处于工作状态,这里需要定义一个函数,用于检测DHT11是否处于工作状态*/ /*检测原理:DHT11收到触发信号后可以正常工作,将会产生80us的低电平,80us 的高电平*/ /*通过检测电平状态,确定是否处于工作状态,返回值为0 表示正常工作,返回值为1,表示工作异常*/ uint8_t DHT11_Check (void) { //避免程序被卡死在某一个循环 uint8_t Retry = 0 ; //设置为输入模式 DHT11_IO_IN (); //需要读取电平,为了方便程序移植,使用宏定义 //通过循环等待低电平结束,如果超过等待期限,则跳出循环 while (DHT11_IN == GPIO_PIN_RESET && Retry < 100) { Retry ++ ; Delay_us (1); }; //通过判断Retry 的值来判断是否有DHT11 //如果大于100,直接结束函数,返回工作异常 if(Retry >= 100) { return 1; } //如果小于100,说明正常工作,Retry = 0 ;进入高电平检测阶段 else Retry = 0 ; /*低电平检测完成之后进入高电平检测*/ while (DHT11_IN == GPIO_PIN_SET && Retry < 100) { Retry ++ ; Delay_us (1); } //通过判断Retry 的值来判断是否有DHT11 //如果大于100,直接结束函数,返回工作异常 if(Retry >= 100) return 1; //如果一切正常,默认返回值为0 return 0 ; } /*完成以上阶段之后,进入数据读取阶段,数据读取的方式为:读取一个字->读取一个字节->读取完整数据*/ /*读取一个字节*/ uint8_t DHT11_ReadBit(void) { uint8_t Retry = 0; /*数据读取都是以50us 的低电平开始,然后进入高电平,如果高电平持续时间为26-28us则为数据“0”*/ /*如果高电平为70us 则为数据“1”*/ //等待高电平结束.这里的高电平为响应信号的80us 高电平 while(DHT11_IN == GPIO_PIN_SET && Retry<100) { Retry++; Delay_us(1); }; Retry = 0 ; //等待低电平结束(数据传输之前的50us低电平) while (DHT11_IN == GPIO_PIN_RESET && Retry < 100) { Retry ++ ; Delay_us (1); }; //延时等待 Delay_us (40); //延时结束仍然为高电平 if(DHT11_IN == GPIO_PIN_SET ) return 1 ; //延时结束已经变成低电平 else return 0 ; } /*读取一字节:循环调用八次读取一字的函数,将读取到的数据放在一字节的存储空间中*/ uint8_t DHT11_ReadByte(void) { uint8_t i, Data = 0 ; //循环八次 for(i = 0 ;i < 8 ;i ++) { Data <<=1 ; Data |= DHT11_ReadBit() ; } return Data ; } //从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 uint8_t DHT11_ReadData(uint16_t *temp,uint16_t *humi) { //定义五位数组,用于存放读取的数据 uint8_t buf[5]; uint8_t i; //发送开始信号 DHT11_Start (); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf=DHT11_ReadByte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=(buf[0]<<8) + buf[1]; *temp=(buf[2]<<8) + buf[3]; } } //如果检测到DHT11工作异常,返回异常信号 else return 1; return 0; } //初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 uint8_t DHT11_Init(void) { DHT11_Start (); return DHT11_Check(); } DHT11.h文件 # ifndef __DHT11_H # define __DHT11_H #include "main.h" /*IO电平高低状态宏定义*/ //拉高 # define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET) //拉低 # define DHT11_DQ_OUT_LOW HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET) /*电平读取宏定义*/ # define DHT11_IN HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_0) // 输入模式 void DHT11_IO_IN(void); // 输出模式 void DHT11_IO_OUT(void); /* 触发DHT11工作状态的信号,涉及到IO口电平的拉高以及拉低, 一次在.h文件中进行宏定义,方便程序移植*/ void DHT11_Start (void); /*延时函数申明,在tim.c文件中定义,如果此处不申明,会有警告*/ void Delay_us (uint32_t us); /*一字数据读取*/ uint8_t DHT11_ReadBit(void); /*读取一字节数据*/ uint8_t DHT11_ReadByte(void); /*读取一次完整数据*/ uint8_t DHT11_ReadData(uint16_t *temp,uint16_t *humi); /*DHT11状态检测函数*/ uint8_t DHT11_Check (void); //初始化DHT11的IO口 DQ 同时检测DHT11的存在 uint8_t DHT11_Init(void); # endif main.c /*用户变量定义,需要放在最开始部分*/ /*定义接收缓冲区*/ uint8_t Rx_Data = 0 ; /*定义温度全局变量*/ uint16_t temperature; /*定义湿度全局变量*/ uint16_t humidity; /*用于发送起始信号*/ uint8_t START = 0 ; /*用于程序的循环结构变量*/ uint8_t i = 0 ; /* 用户宏定义*/ # define Beep_Start HAL_GPIO_WritePin (Beep_GPIO_Port ,Beep_Pin ,GPIO_PIN_SET ); # define Beep_Stop HAL_GPIO_WritePin (Beep_GPIO_Port ,Beep_Pin ,GPIO_PIN_RESET ); /*用户代码*/ /* USER CODE BEGIN 2 */ /*打印开启系统提示,提高系统的人机交互体验*/ printf ("**************************************rn"); printf ("Hello! Welcome to use this system!rn"); printf ("**************************************rn"); /*用于检测DHT11是否正常工作,初始化失败不断提醒用户 DHT11 Checked failed!!!*/ while(DHT11_Init()) { printf("DHT11 Checked failed!!!rn"); HAL_Delay(1000); }; /*初始化成功*/ printf ("**************************************rn"); printf ("DHT11 Checked Sucess!!!rn"); printf ("**************************************rn"); /*用户需要开启温度湿度异常警告时,输入指令*/ printf ("If you need to send an alert message, please enter 0xA0 !rn "); printf ("**************************************rn"); /*关闭异常警告*/ printf ("If you need to stop alert message, please enter 0xA1 !rn "); printf ("**************************************rn"); /*温湿度输出指令*/ printf ("If you need to view the current indoor temperature, please enter 0xA2 !rn "); printf ("**************************************rn"); /*按键中断指令*/ printf ("If you need to turn on LED1, please press KEY 1! rn"); printf ("**************************************rn"); printf ("If you need to toggle LED2, please press KEY 2! rn"); printf ("**************************************rn"); /*使能串口通信接收中断*/ HAL_UART_Receive_IT (&huart1 ,&Rx_Data ,1); /* USER CODE END 2 */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /*用于等待用户输入指令*/ while(!START ); START = 0 ; /*五次打印出实时温度与湿度*/ while(i<5) { //调用数据读取函数,读取完整数据 DHT11_ReadData (&temperature,&humidity); //打印出温度 printf("DHT11 Temperature = %d.%d degreern",temperature>>8,temperature&0xff); //打印出湿度 printf("DHT11 Humidity = %d.%d%%rn",humidity>>8,humidity&0xff); //翻转电平,提示打印完成 HAL_GPIO_TogglePin(LED1_GPIO_Port ,LED1_Pin ); HAL_Delay(1000); HAL_GPIO_TogglePin(LED1_GPIO_Port ,LED1_Pin ); /*循环体变量自加*/ i++; } /*提示用户温度打印完毕*/ printf ("**************************************rn"); printf ("Indoor temperature and humidity have been printed! rn"); printf ("**************************************rn"); } /* USER CODE END 3 */ } /* USER CODE BEGIN 4 */ /*按键中断回调函数*/ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { uint8_t i ; /*判断中断来源*/ if(GPIO_Pin == KEY1_Pin ) { /*中断处理任务,翻转电平*/ HAL_GPIO_TogglePin (LED1_GPIO_Port ,LED1_Pin ); __HAL_GPIO_EXTI_CLEAR_IT (KEY1_Pin ); } else if (GPIO_Pin == KEY2_Pin ) { for(i = 0;i<10;i++) { HAL_GPIO_TogglePin (LED2_GPIO_Port ,LED2_Pin ); HAL_Delay (500); __HAL_GPIO_EXTI_CLEAR_IT (KEY1_Pin ); } } } /*串口接收与发送中断回调函数*/ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /*判断具体的接受中断来源*/ if(huart == &huart1 ) { /*判断接收指令*/ if(Rx_Data == 0xA0) { /*具体的中断处理任务*/ Beep_Start ; printf ("**************************************rn"); printf ("Beep Open !rn"); printf ("**************************************rn"); /*处理完毕,再次开启接收中断*/ HAL_UART_Receive_IT (&huart1 ,&Rx_Data ,1); } else if (Rx_Data == 0xA1) { /*具体的中断处理任务*/ Beep_Stop ; printf ("**************************************rn"); printf ("Beep Off !rn"); printf ("**************************************rn"); /*处理完毕,再次开启接收中断*/ HAL_UART_Receive_IT (&huart1 ,&Rx_Data ,1); } else if (Rx_Data == 0xA2) { /*具体的中断处理任务*/ START = 1 ;//输入指令0xA2,开启温湿度采集 /*处理完毕,再次开启接收中断*/ HAL_UART_Receive_IT (&huart1 ,&Rx_Data ,1); } else { /*输入错误提示*/ printf ("**************************************rn"); printf ("Input Error!rn"); printf ("**************************************rn"); /*处理完毕,再次开启接收中断*/ HAL_UART_Receive_IT (&huart1 ,&Rx_Data ,1); } } } /* USER CODE END 4 */ */ 效果图如上。 只要建立相对应的文件,把代码复制到正确的位置,保证能够运行,亲测有效。 如果有不到位的地方还请大佬批评指正。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 04:18 , Processed in 0.797967 second(s), Total 76, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号