你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103VET6实现采集温湿度数据

[复制链接]
STMCU小助手 发布时间:2023-2-5 18:50
前言
了解DHT11温湿度传感器相关知识,进行DHT11传感器的开发及数据获取,并通过串口调试助手查看

一、温湿度传感器相关知识

1. DHT11简介
DHT11温湿度传感器是一种比较便宜的常见的温湿度传感器,它的内部由两个元件构成,一个是电阻式的感湿元件用来检测环境湿度,另一个是NTC测温元件来测量温度,在测得数据后,两个元件会将数据传送给内部一个集成的8位的处理器来对数据进行处理,并将它们转换为数字量,这些数据可以通过串口传送给主机。DHT11温湿度传感器有四个管脚,只有一条是数据线接口,所以在传输数据时仅需要1个I/O就能同时传输测得的温度以及湿度,在进行程序编写时更加简洁方便。因为DHT11集成度较好,体积比较小,所以消耗也很小,抗干扰能力更强,稳定性较好,不易受到外界干扰。

Pin1 VDD 供电 3-5.5V DC
Pin2 DATA 串行数据,单总线
Pin3 NC 空脚,悬空
Pin4 GND 接地,电源负极

DHT11集成度很高,封装的很简洁,只有四个管脚,所以连接也是相对比较方便。DHT11管脚Pin1接一个3-5.5V的直流电源的正极,管脚Pin2为数据端,主要用于传输数据,但是在接线时需要加一个5KΩ的上拉电阻连接到主机MCU上,用来保证数据传输的稳定性,同时还要注意这个5KΩ是在管脚Pin2与主机之间的接线小于20m时才有用,在大于20m时就需要根据实际情况来确定需要加多大的上拉电阻来保持稳定性。管脚Pin3不起什么作用,只需要将其悬空不接线即可,管脚Pin4接地。


2.数据格式
DHT11和DS18B20不同,DHT11不需要配置,可以直接读取数据,一次完整的数据传输为40bit,先传输高字节的数据再传输低字节的数据,也就是低位后出,高位先出模式。
数据格式: 8bit湿度整数数据 + 8bit湿度小数数据
+8bit温度整数数据 + 8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于
8bit湿度整数数据 + 8bit湿度小数数据
+8bit温度整数数据 + 8bit温度小数数据
所得结果的末8位。


3.数据传输
数据线一开始处于高电平状态,用户MCU将总线电平拉低,表示用户要开始获取数据,然后将电平拉高并延时等待一段时间,等待DHT11回复,如果DHT11将总线拉低,表示已经收到主机信号,并响应主机信号,准备输出,然后将总线电平拉高,并延时一段时间,表示准备传输40bit的数据。然后将数据总线拉低一段时间开始传输数据,主要是进行2进制数据传输,传输0和1,并用不同的拉高电平延时时间来表示数据0和1。用户可以选择读取湿度还是温度,整数还是小数。并且数据传输是需要DHT11收到主机MCU发送的开始信号,才会开始采集数据传输数据,而且此时DHT11会转到低速模式。

1d4a7e41310f44198a2a3914b9f59db3.png

总线在空闲时因为上拉电阻会处于高电平状态,主机用户MCU会发送信号将电平拉低至少18us,太短DHT11可能会检测不到主机的起始信号。之后主机会再将电平拉高20-40us,DHT11识别到后,会将电平拉低80us,表示DHT11已经接收到主机发送的开始信号,之后再将总线切换到输入模式,然后DHT11会再将电平拉高80us表示竹北开始传输数据。之后会再将电平拉低,然后开始传输数据。

当接收到主机的开始信号后,DHT11会将总线拉低80us来发送响应信号,表示已经接收到,然后会将总线拉高80us,并准备发送数据,每一位的数据都以50us的低电平间隙开始,就是每两个数据之间都有一个50us的低电平信号来表示一位数据传输完成。DHT11用电平拉高延时的时间来表示数据为位0还是1。通常用拉高26-28us来表示数据‘0’,用拉高70us来表示数据‘1’。当最后一位数据传输完成后,DHT11会将总线拉低50us,随后总线又会因为上拉电阻将总线拉高,并处于空闲状态。

DHT11读取数据“0”时序图

ea92ef3f20334c68aa75e8b83aefa06f.png

DHT11读数据“1”时序图

d7d734cf63a942ecbe48dc4f2ae1fc4b.png


二、程序实现
1.dht11.h
DHT11的程序实现主要是根据它的读写时序来实现的,因此在进行程序的编写时要根据它的读写时序进行模拟,实现单片机与DHT11之间的数据通信。

代码如下(示例):
  1. #ifndef __DHT11_H
  2. #define __DHT11_H

  3. #include "stm32f10x.h"

  4. typedef struct
  5. {
  6.         uint8_t  humi_int;                //湿度的整数部分
  7.         uint8_t  humi_deci;                 //湿度的小数部分
  8.         uint8_t  temp_int;                 //温度的整数部分
  9.         uint8_t  temp_deci;                 //温度的小数部分
  10.         uint8_t  check_sum;                 //校验和
  11.                                  
  12. } DHT11_Data_TypeDef;



  13. /************************** DHT11 连接引脚定义********************************/
  14. #define      DHT11_Dout_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
  15. #define      DHT11_Dout_GPIO_CLK                       RCC_APB2Periph_GPIOE

  16. #define      DHT11_Dout_GPIO_PORT                      GPIOE
  17. #define      DHT11_Dout_GPIO_PIN                       GPIO_Pin_6



  18. /************************** DHT11 函数宏定义********************************/
  19. #define      DHT11_Dout_0                                    GPIO_ResetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )
  20. #define      DHT11_Dout_1                                    GPIO_SetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )

  21. #define      DHT11_Dout_IN()                                  GPIO_ReadInputDataBit ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )



  22. /************************** DHT11 函数声明 ********************************/
  23. void                     DHT11_Init                      ( void );
  24. uint8_t                  DHT11_Read_TempAndHumidity      ( DHT11_Data_TypeDef * DHT11_Data );

  25. #endif
复制代码

DHT11用到的数据总线是PE6,接线时,DHT11数据线接到PE6,以及我们需要用到的函数的声明:
Void DHT11_Init(void)为DHT11的初始化函数;
uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data )为DHT11的数据读取函数,这个函数会将读取到的数据赋值给DHT11_Data结构体里的变量,然后还会有一个返回值判断是否读取成功;

2.dht11.c
代码如下(示例):
  1. #include "dht11.h"
  2. #include "delay.h"

  3. static void                           DHT11_GPIO_Config                       ( void );
  4. static void                           DHT11_Mode_IPU                          ( void );
  5. static void                           DHT11_Mode_Out_PP                       ( void );
  6. static uint8_t                        DHT11_ReadByte                          ( void );


  7. /**
  8.   * @brief  DHT11 初始化函数
  9.   * @param  无
  10.   * @retval 无
  11.   */
  12. void DHT11_Init ( void )
  13. {
  14.         DHT11_GPIO_Config ();
  15.        
  16.         DHT11_Dout_1;               // 拉高GPIOB10
  17. }

  18. /*
  19. * 函数名:DHT11_GPIO_Config
  20. * 描述  :配置DHT11用到的I/O口
  21. * 输入  :无
  22. * 输出  :无
  23. */
  24. static void DHT11_GPIO_Config ( void )
  25. {               
  26.         /*定义一个GPIO_InitTypeDef类型的结构体*/
  27.         GPIO_InitTypeDef GPIO_InitStructure;

  28.        
  29.         /*开启DHT11_Dout_GPIO_PORT的外设时钟*/
  30.   DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );       

  31.         /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/                                                                                                                          
  32.           GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;       

  33.         /*设置引脚模式为通用推挽输出*/
  34.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  35.         /*设置引脚速率为50MHz */   
  36.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  37.         /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
  38.           GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );                  
  39.        
  40. }

  41. /*
  42. * 函数名:DHT11_Mode_IPU
  43. * 描述  :使DHT11-DATA引脚变为上拉输入模式
  44. * 输入  :无
  45. * 输出  :无
  46. */
  47. static void DHT11_Mode_IPU(void)
  48. {
  49.           GPIO_InitTypeDef GPIO_InitStructure;

  50.                   /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/       
  51.           GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;

  52.            /*设置引脚模式为浮空输入模式*/
  53.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;

  54.           /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
  55.           GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);         
  56.        
  57. }

  58. /*
  59. * 函数名:DHT11_Mode_Out_PP
  60. * 描述  :使DHT11-DATA引脚变为推挽输出模式
  61. * 输入  :无
  62. * 输出  :无
  63. */
  64. static void DHT11_Mode_Out_PP(void)
  65. {
  66.         GPIO_InitTypeDef GPIO_InitStructure;

  67.                  /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/                                                                                                                          
  68.           GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;       

  69.         /*设置引脚模式为通用推挽输出*/
  70.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  71.         /*设置引脚速率为50MHz */   
  72.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  73.         /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
  74.           GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);                  
  75.        
  76. }

  77. /*
  78. * 从DHT11读取一个字节,MSB先行
  79. */
  80. static uint8_t DHT11_ReadByte ( void )
  81. {
  82.         uint8_t i, temp=0;
  83.        

  84.         for(i=0;i<8;i++)   
  85.         {         
  86.                 /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
  87.                 while(DHT11_Dout_IN()==Bit_RESET);

  88.                 /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
  89.                  *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
  90.                  */
  91.                 delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可                     

  92.                 if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
  93.                 {
  94.                         /* 等待数据1的高电平结束 */
  95.                         while(DHT11_Dout_IN()==Bit_SET);

  96.                         temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行
  97.                 }
  98.                 else         // x us后为低电平表示数据“0”
  99.                 {                          
  100.                         temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
  101.                 }
  102.         }
  103.        
  104.         return temp;
  105.        
  106. }


  107. /*
  108. * 一次完整的数据传输为40bit,高位先出
  109. * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
  110. */
  111. uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
  112. {  
  113.         /*输出模式*/
  114.         DHT11_Mode_Out_PP();
  115.         /*主机拉低*/
  116.         DHT11_Dout_0;
  117.         /*延时18ms*/
  118.         delay_ms(18);

  119.         /*总线拉高 主机延时30us*/
  120.         DHT11_Dout_1;

  121.         delay_us(30);   //延时30us

  122.         /*主机设为输入 判断从机响应信号*/
  123.         DHT11_Mode_IPU();

  124.         /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
  125.         if(DHT11_Dout_IN()==Bit_RESET)     
  126.         {
  127.                 /*轮询直到从机发出 的80us 低电平 响应信号结束*/  
  128.                 while(DHT11_Dout_IN()==Bit_RESET);

  129.                 /*轮询直到从机发出的 80us 高电平 标置信号结束*/
  130.                 while(DHT11_Dout_IN()==Bit_SET);

  131.                 /*开始接收数据*/   
  132.                 DHT11_Data->humi_int= DHT11_ReadByte();

  133.                 DHT11_Data->humi_deci= DHT11_ReadByte();

  134.                 DHT11_Data->temp_int= DHT11_ReadByte();

  135.                 DHT11_Data->temp_deci= DHT11_ReadByte();

  136.                 DHT11_Data->check_sum= DHT11_ReadByte();


  137.                 /*读取结束,引脚改为输出模式*/
  138.                 DHT11_Mode_Out_PP();
  139.                 /*主机拉高*/
  140.                 DHT11_Dout_1;

  141.                 /*检查读取的数据是否正确*/
  142.                 if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
  143.                         return SUCCESS;
  144.                 else
  145.                         return ERROR;
  146.         }
  147.        
  148.         else
  149.                 return ERROR;
  150.        
  151. }


复制代码

3.main.c
  1. #include "stm32f10x.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "dht11.h"

  5. int main()
  6. {
  7.         DHT11_Data_TypeDef Dht_Data;
  8.         char Temp_Str[ 10 ] = { 0 };
  9.         char Hum_Str[ 10 ] = { 0 };
  10.         USART_Config();   //初始化串口
  11.         SysTick_Init();   //初始化系统定时器
  12.         printf("\r\n***Dht11 温湿度传感器实验***\r\n");
  13.         DHT11_Init();  //初始化DTT11的引脚
  14.         while(1)
  15.         {
  16.                         //调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息

  17.                 if(DHT11_Read_TempAndHumidity(&Dht_Data) == SUCCESS)
  18.                 {
  19.                         sprintf(Temp_Str,"%d.%d",Dht_Data.temp_int,Dht_Data.temp_deci);
  20.                         sprintf(Hum_Str,"%d,%d",Dht_Data.humi_int,Dht_Data.humi_deci);
  21.                         printf("温度数据为:%d.%d ℃\r\n",Dht_Data.temp_int,Dht_Data.temp_deci);
  22.                         printf("湿度数据为:%d.%d %RH\r\n",Dht_Data.humi_int,Dht_Data.humi_deci);
  23.                 }
  24.                 else
  25.                 printf("error\r\n");


  26.         delay_ms(2000);
  27.         }
  28. }
复制代码


4.串口显示
将开发板连接电脑,然后打开串口调试助手,就会看到温度以及湿度的数据

3cce415f69ab42c9a24402a6c427c894.png


总结
做到这一步算是已经完成温湿度采集并串口显示,有需要的话可以进行LCD显示。
————————————————
版权声明:清道 夫


收藏 评论0 发布时间:2023-2-5 18:50

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版