OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3642|回复: 0

[ALTERA] 《新起点之FPGA开发指南 V2.1》第二十八章 DHT11数字温湿度传感器实验

[复制链接]

1107

主题

1118

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4615
金钱
4615
注册时间
2019-5-8
在线时间
1218 小时
发表于 2021-10-16 11:13:52 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2021-10-30 10:11 编辑

1)实验平台:正点原子新起点V2FPGA开发板
2)  章节摘自【正点原子】《新起点之FPGA开发指南 V2.1》
3)购买链接:https://detail.tmall.com/item.htm?id=609758951113
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_xinqidian(V2).html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:712557122 QQ群.png

原子哥.jpg

微信公众号.png


第二十八章 DHT11数字温湿度传感器实验


DHT11是奥松(AoSong)公司生产的一款数字温湿度复合传感器。该传感器用途广泛、抗干扰能力强、可靠性高,在家电、汽车、医疗等方面有广泛的应用。本章我们将使用FPGA开发板实现对DHT11数据的采集,并将温湿度数据显示在数码管上。
本章包括以下几个部分:
2727.1简介
27.2实验任务
27.3硬件设计
27.4程序设计
27.5下载验证


28.1简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它使用专用的数字模块采集技术和温湿度传感技术,具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC(负温度系数热敏电阻器)测温元件,并与一个高性能8位MCU相连接。每个DHT11传感器都在湿度校验室中校准过,校准系数以程序的形式储存在OTP(一次性可编程)内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。DHT11使用单线制串行接口,4针单排引脚封装,信号传输距离可达20米以上,在各类应用甚至很苛刻的环境中都能正常工作。
第二十八章 DHT11数字温湿度传感器实验442.png
图 28.1.1 DHT11内部原理图
上图为DHT11的内部原理图,可以看出感湿原件、感温元件和OTP内存直接连接在内部一个八位MCU上,该MCU通过计算得出测量数值。
DATA用于FPGA与DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分为整数部分和小数部分,数据格式如下:
一次完整的数据传输为40bit,高位在前。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和数据
数据传送正确时校验和数据等于“8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度整数数据 + 8bit温度小数数据”所得结果的末8位)。
接下来我们介绍一下DHT11的传输时序,DHT11的数据发送流程如图 28.1.2错误!未找到引用源。所示。
第二十八章 DHT11数字温湿度传感器实验936.png
图 28.1.2 DHT11数据发送流程
主机(此处指FPGA)首先发送一次开始信号,即:拉低数据线,保持t1(至少18ms)时间;然后拉高数据线保持t2(20~40us)时间,随后开始读取DHT11的响应;如果操作正确的话,DHT11会拉低数据线,保持t3(80us)时间,作为响应信号;接下来DHT11会拉高数据线,保持t4(80us)时间,随后开始输出有效数据。
DHT11共输出40bit有效数据,每1bit数据都是以50us低电平开始,高电平的持续时间作为判断数据位的条件。当数据位为0时,高电平的持续时间为26~28us;当数据位为1时,高电平的持续时间为70us。
DHT11数据位“0”时序图和数据位“1”时序图如图 28.1.3和图 28.1.4所示。
第二十八章 DHT11数字温湿度传感器实验1399.png
图 28.1.3 DHT11数据位“0”时序图
第二十八章 DHT11数字温湿度传感器实验1468.png
图 28.1.4 DHT11数据位“1”时序图
需要注意的是,DHT11的温度和湿度转换较慢,如果读取速度过快会导致DHT11无法响应的情况。本次实验每100ms读取一次,如果DHT11长时间未响应,则重新发起开始信号。
28.2实验任务
本节实验任务是使用新起点FPGA开发板完成对DHT11温湿度数据的采集,并通过按键KEY0控制温度和湿度在数码管上的切换显示。
28.3硬件设计
我们的新起点开发板上有一个DS18B20/DTH11的扩展接口,该接口可以用来连接DS18B20或DHT11。其原理图如图 28.3.1所示。
第二十八章 DHT11数字温湿度传感器实验1811.png
图 28.3.1 DHT11/DS18B20扩展接口原理图
DHT11通过4个排针与外部连接,如图 28.3.2所示,将DHT11直接插在开发板上即可,接插之前注意正负极的方向,以免短路。
第二十八章 DHT11数字温湿度传感器实验1992.png
图 28.3.2 DHT11连接实物图
    本次实验的管脚分配如下表所示:
表 28.3.1 管脚分配
表1.png
本节实验使用的管脚基本都是数码管管脚,这里不再给出TCL文件。
28.4程序设计
根据实验任务,我们可以大致规划出系统的工作流程:FPGA控制DHT11采集温度和湿度,并将收到的温度和湿度数据转换成十进制显示在数码管上。本次实验使用按键来控制数码管显示温度和湿度,所以还需要添加消抖模块来对按键进行消抖,以及按键控制模块控制数码管切换显示温度和湿度。由此画出的系统框图如下图所示。
第二十八章 DHT11数字温湿度传感器实验2847.png
图 28.4.1 DHT11数字温湿度传感器系统框图
各模块端口及信号连接如图 28.4.2所示:
第二十八章 DHT11数字温湿度传感器实验2983.png
图 28.4.2 顶层模块原理图
FPGA部分包括5个模块,顶层模块(top_dht11)、DHT11驱动模块(dht11_drive)、按键消抖模块(key_debounce)、按键控制模块(dht11_key)、数码管驱动模块(seg_led)。其中在顶层模块完成对其他模块的例化。
DHT11驱动模块(dht11_drive):dht11_drive模块通过单总线引脚读取DHT11的温度值和湿度值,并将读取到的数据输出至按键控制模块。
按键消抖模块(key_debounce):消除按键抖动,在检测到有按键按下或释放时对按键数据进行消抖处理。
按键控制模块(dht11_key):根据输入的按键控制信号,将温度数据和湿度数据选择输出至数码管显示模块。
数码管显示模块(seg_led):将输入的数据显示到数码管上。
顶层模块代码如下:
  1. 1   module top_dht11(
  2. 2       input          sys_clk  ,  //系统时钟
  3. 3       input          sys_rst_n,  //系统复位
  4. 4      
  5. 5       inout          dht11    ,  //DHT11总线
  6. 6       input          key      ,  //按键
  7. 7       output  [5:0]  sel      ,  //数码管位选信号
  8. 8       output  [7:0]  seg_led     //数码管段选信号
  9. 9   );
  10. 10  //wire define
  11. 11  wire  [31:0]  data_valid;
  12. 12  wire  [19:0]  data      ;
  13. 13  wire  [5:0]   point     ;
  14. 14  
  15. 15  //*****************************************************
  16. 16  //**                    main code
  17. 17  //*****************************************************
  18. 18  
  19. 19  //dht11驱动模块
  20. 20  dht11_drive u_dht11_drive (
  21. 21      .sys_clk        (sys_clk),
  22. 22      .rst_n          (sys_rst_n),
  23. 23      
  24. 24      .dht11          (dht11),
  25. 25      .data_valid     (data_valid)
  26. 26      );
  27. 27  
  28. 28  
  29. 29  //按键消抖模块
  30. 30  key_debounce u_key_debounce(
  31. 31      .sys_clk        (sys_clk),
  32. 32      .sys_rst_n      (sys_rst_n),
  33. 33      
  34. 34      .key            (key),
  35. 35      .key_flag       (key_flag),
  36. 36      .key_value      (key_value)
  37. 37      );
  38. 38  
  39. 39  //按键控制温/湿度显示
  40. 40  dht11_key u_dht11_key(
  41. 41      .sys_clk        (sys_clk),
  42. 42      .sys_rst_n      (sys_rst_n),
  43. 43      
  44. 44      .key_flag       (key_flag),
  45. 45      .key_value      (key_value),
  46. 46      .data_valid     (data_valid),
  47. 47      
  48. 48      .data           (data),
  49. 49      .sign           (sign),
  50. 50      .en             (en),                     
  51. 51      .point          (point)
  52. 52      );
  53. 53  
  54. 54  //动态数码管显示模块
  55. 55  seg_led u_seg_led (
  56. 56      .clk            (sys_clk),
  57. 57      .rst_n          (sys_rst_n),
  58. 58      
  59. 59      .seg_sel        (sel),
  60. 60      .seg_led        (seg_led),
  61. 61      
  62. 62      .data           (data),
  63. 63      .point          (point),
  64. 64      .en             (en),
  65. 65      .sign           (sign)
  66. 66      );
  67. 67  
  68. 68  endmodule
复制代码


顶层模块完成对其他模块的例化,dht11_drivr模块输出的数据信号(data_valid)和key_debounce模块输出的按键信号(key_flag和key_value)连接至dht11_key模块,dht11_key模块输出的温度/湿度数据(data)以及数码管控制信号连接至seg_led模块。
由本章简介部分介绍的DHT11传输时序可以发现,DHT11的传输时序适合用状态机来编写。DHT11驱动模块状态跳转图如下所示。
第二十八章 DHT11数字温湿度传感器实验5420.png
图 28.4.3 DHT11驱动状态跳转图
DHT11驱动模块使用三段式状态机来读取DHT11的温度和湿度值,从上图可以比较直观的看到每个状态实现的功能以及跳转都下一个状态的条件。这里需要注意的一点是,由于DHT11温度和湿度转换较慢,如果读取速度过快会导致DHT11无法响应的情况,所以我们在每次读操作结束后延时两秒。
由于DHT11驱动模块的代码较长,我们仅贴出部分源代码。  
  1. 131         case (cur_state)
  2. 132                 //上电后延时1秒等待DHT11稳定
  3. 133             st_power_on_wait : begin               
  4. 134                 if(us_cnt < POWER_ON_NUM) begin
  5. 135                     dht11_buffer <= 1'bz; //空闲状态释放总线
  6. 136                     us_cnt_clr   <= 1'b0;
  7. 137                 end
  8. 138                 else begin            
  9. 139                     next_state   <= st_low_20ms;
  10. 140                     us_cnt_clr   <= 1'b1;
  11. 141                 end
  12. 142             end
  13. 143                 //FPGA发送起始信号(20ms的低电平)   
  14. 144             st_low_20ms: begin
  15. 145                 if(us_cnt < 20000) begin
  16. 146                     dht11_buffer <= 1'b0; //起始信号为低电平
  17. 147                     us_cnt_clr   <= 1'b0;
  18. 148                 end
  19. 149                 else begin
  20. 150                     dht11_buffer <= 1'bz; //起始信号结束后释放总线
  21. 151                     next_state   <= st_high_13us;
  22. 152                     us_cnt_clr   <= 1'b1;
  23. 153                 end   
  24. 154             end
  25. 155                 //等待DHT11的响应信号(等待10~20us)
  26. 156             st_high_13us:begin                     
  27. 157                 if (us_cnt < 20) begin
  28. 158                     us_cnt_clr   <= 1'b0;
  29. 159                     if(dht11_neg) begin   //检测到DHT11响应信号
  30. 160                         next_state <= st_rec_low_83us;
  31. 161                         us_cnt_clr <= 1'b1;
  32. 162                     end
  33. 163                 end
  34. 164                 else                      //超过20us未响应
  35. 165                     next_state <= st_delay;
  36. 166             end
  37. 167                 //等待DHT11的83us低电平响应信号结束
  38. 168             st_rec_low_83us: begin                  
  39. 169                 if(dht11_pos)                  
  40. 170                     next_state <= st_rec_high_87us;  
  41. 171             end
  42. 172                 //DHT11拉高87us通知FPGA准备接收数据
  43. 173             st_rec_high_87us: begin
  44. 174                 if(dht11_neg) begin       //准备时间结束   
  45. 175                     next_state <= st_rec_data;
  46. 176                     us_cnt_clr <= 1'b1;
  47. 177                 end
  48. 178                 else begin                //高电平准备接收数据
  49. 179                     data_cnt  <= 6'd0;
  50. 180                     data_temp <= 40'd0;
  51. 181                     step  <= 1'b0;
  52. 182                 end
  53. 183             end
  54. 184                 //连续接收40位数据
  55. 185             st_rec_data: begin                                
  56. 186                 case(step)
  57. 187                     0: begin              //接收数据低电平
  58. 188                         if(dht11_pos) begin
  59. 189                             step   <= 1'b1;
  60. 190                             us_cnt_clr <= 1'b1;
  61. 191                         end            
  62. 192                         else              //等待数据低电平结束
  63. 193                             us_cnt_clr <= 1'b0;
  64. 194                     end
  65. 195                     1: begin              //接收数据高电平
  66. 196                         if(dht11_neg) begin
  67. 197                             data_cnt <= data_cnt + 1'b1;
  68. 198                                           //判断接收数据为0/1
  69. 199                             if(us_cnt < 60)
  70. 200                                 data_temp <= {data_temp[38:0],1'b0};
  71. 201                             else               
  72. 202                                 data_temp <= {data_temp[38:0],1'b1};
  73. 203                             step <= 1'b0;
  74. 204                             us_cnt_clr <= 1'b1;
  75. 205                         end
  76. 206                         else              //等待数据高电平结束
  77. 207                             us_cnt_clr <= 1'b0;
  78. 208                     end
  79. 209                 endcase
  80. 210                 
  81. 211                 if(data_cnt == 40) begin  //数据传输结束,验证校验位
  82. 212                     next_state <= st_delay;
  83. 213                     if(data_temp[7:0] == data_temp[39:32] + data_temp[31:24]
  84. 214                                          + data_temp[23:16] + data_temp[15:8])
  85. 215                         data_valid <= data_temp[39:8];  
  86. 216                 end
  87. 217             end
  88. 218                 //完成一次数据采集后延时2s
  89. 219             st_delay:begin
  90. 220                 if(us_cnt < 2000_000)
  91. 221                     us_cnt_clr <= 1'b0;
  92. 222                 else begin                //延时结束后重新发送起始信号
  93. 223                     next_state <= st_low_20ms;      
  94. 224                     us_cnt_clr <= 1'b1;
  95. 225                 end
  96. 226             end
  97. 227             default : ;
  98. 228         endcase
复制代码


从代码的第165行可知,在st_high_13us状态下,当DHT11长时间未响应时(超时20us),则进入延时状态(st_delay),延时两秒后重新发起开始信号。
图 28.4.4为SignalTap抓取的波形图,从图中可以清晰的看到DHT11驱动模块各个状态跳转的时序图。st_rec_data为解析数据的状态,数据解析完成之后,开始进入st_delay(延时)状态,延时状态结束之后,准备重新发起开始信号。
第二十八章 DHT11数字温湿度传感器实验10254.png
图 28.4.4 SignalTap抓取的波形图
按键控制模块的代码如下所示:
  1. 1   module dht11_key(
  2. 2       input             sys_clk,
  3. 3       input             sys_rst_n,
  4. 4      
  5. 5       input             key_flag,
  6. 6       input             key_value,
  7. 7       input      [31:0] data_valid,
  8. 8      
  9. 9       output     [31:0] data,
  10. 10      output reg        sign,
  11. 11      output            en,                     
  12. 12      output     [ 5:0] point
  13. 13  );
  14. 14  
  15. 15  //reg define                           
  16. 16  reg       flag ; // 温/湿度标志信号
  17. 17  reg [7:0] data0; // 小数部分
  18. 18  reg [7:0] data1; // 整数部分
  19. 19  
  20. 20  //*****************************************************
  21. 21  //**                    main code
  22. 22  //*****************************************************
  23. 23  
  24. 24  //数码管使能信号
  25. 25  assign en    = 1'b1;
  26. 26  
  27. 27  //显示的数值为 (整数 + 0.1*小数)*100
  28. 28  assign data  = data1 * 100 + data0*10;
  29. 29  
  30. 30  //小数点左移两位
  31. 31  assign point = 6'b000100;
  32. 32  
  33. 33  //检测到按键按下时,切换温/湿度标志信号
  34. 34  always [url=home.php?mod=space&uid=95564]@[/url] (posedge sys_clk or negedge sys_rst_n) begin
  35. 35      if(!sys_rst_n)                                    
  36. 36          flag <= 1'b0;
  37. 37      else if (key_flag & (~key_value))
  38. 38          flag <= ~flag;
  39. 39  end
  40. 40  
  41. 41  //flag为“0”时显示温度,为“1”时显示湿度
  42. 42  always @ (posedge sys_clk or negedge sys_rst_n) begin
  43. 43      if(!sys_rst_n) begin
  44. 44          data0 <= 8'd0;
  45. 45          data1 <= 8'd0;
  46. 46          sign  <= 1'b0;
  47. 47      end
  48. 48      else if(flag == 1'b0) begin
  49. 49          data0 <= data_valid[6:0];  //温度小数部分最高位为符号位
  50. 50          data1 <= data_valid[15:8];
  51. 51          if(data_valid[7])
  52. 52              sign <= 1'b1;          //bit7为1表示负温度
  53. 53          else
  54. 54              sign <= 1'b0;
  55. 55      end
  56. 56      else begin
  57. 57          data0 <= data_valid[23:16];
  58. 58          data1 <= data_valid[31:24];
  59. 59          sign  <= 1'b0;
  60. 60      end
  61. 61  end
  62. 62  
  63. 63  endmodule
复制代码


在代码的第34行开始的always中,每按下一次按键KEY0,flag的值会改变一次,当flag的值等于0时,输出的值为温度值;当flag的值等于1时,输出的值为湿度值。在代码的第28行中,我们将温湿度值的整数部分放大100倍,小数部分放大10倍,显示在数码管上。
按键消抖模块和数码管显示模块分别在“按键控制蜂鸣器试验”和“动态数码管显示试验”中作出了详细介绍,在此不再赘述。
28.5下载验证
首先将DHT11接插到新起点开发板上的单总线接口,如下图所示。然后将下载器一端连电脑,另一端与开发板上对应端口连接,最后连接电源线并打开电源开关。
第二十八章 DHT11数字温湿度传感器实验12367.png
图 28.5.1 DHT11接插至新起点开发板
接下来我们下载程序,验证温湿度传感器数码管显示功能。下载完成后,数码管默认显示的是温度值,当按下KEY0按键后,数码管会显示湿度值,说明本次DHT11数字温湿度传感器实验验证成功。这里需要注意的是温度值的单位是:℃(摄氏度);湿度值的单位是:%RH(相对湿度),温度值和湿度值的单位在数码管上没有显示。
第二十八章 DHT11数字温湿度传感器实验12588.png
图 28.5.2 开发板KEY0按键

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-10-3 22:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表