本帖最后由 abner_ma 于 2020-12-25 18:10 编辑

   DHT11 数字温湿度传感器,是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC 测温元件,并与一个高性能8 位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11 传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP 内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20 米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为4 针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
DHT11信号分析:
      DHT11是通过单总线与单片机进行通信的,这样做的好处就是占用资源少,编程实现简单,发送数据的具体格式为 8bit 湿度整数数据+8bit 湿度小数数据+8bi 温度整数数据+8bit 温度小数数据+8bit校验和。主机先要给DHT11发送一个启动新号,等待DHT11做出响应,然后再进行检测温湿度的发送及传输,下面通过一张图来了解一下DHT11的传输过程。


1.png
     从图上我们可以看出,主机要先把应答线拉低,因为空闲的时候是高状态,然后再次拉高,等待DHT11的响应,也就是等待数据线被拉低,当DHT11准备输出数据时,再把数据线拉低,输出数据给单片机,单片机可以根据高电平时间的长短来判别输出的数据是0还是1,最后在进行校验位的检查,从而成传输。

这个传感器有三个脚,分别是VCC、GND、DATA。这是一个单数据口的传感器,数据口做双向传输使用,这个管脚在FPGA上要设置为inout。

工作原理:    看这张信号图,就可以知道模块和主控之间的通信方式。

  • 上电后等待1s,以越过不稳定状态。
  • IO为信号输出模式,低电平持续18ms以上。(建议20ms)
  • IO电平拉高,持续20~40us。(建议30us)
  • IO为信号输入模式,进入DHT响应时间。(就是模块受到了主控的信息,返回一个数据预发送信号)
  • 低电平延时80us,电平拉高80us,完成DHT响应。
  • 进入数据逻辑0/1发送,持续40位。
  • 逻辑0,电平拉低持续50us,电平拉高持续25us。
  • 逻辑1,电平拉低持续50us,电平拉高持续80us。
  • 数据发送结束后,总线拉高。(此处可以至少延时1s,然后再进行下一次数据采集)

FPGA代码:
// dht11
  • // made by 00
  • //time 2020.4.28
  • module dht11(
  •     input               clk,   
  •     input               rst_n,                                   
  •     inout               dht11,   
  •     output  reg  [31:0] data_valid     
  • );
  • /**************parameter********************/              
  • parameter  POWER_ON_NUM     = 1000_000;              
  • parameter  S_POWER_ON      = 3'd0;      
  • parameter  S_LOW_20MS      = 3'd1;     
  • parameter  S_HIGH_13US     = 3'd2;   
  • parameter  S_LOW_83US      = 3'd3;      
  • parameter  S_HIGH_87US     = 3'd4;      
  • parameter  S_SEND_DATA     = 3'd5;      
  • parameter  S_DEALY         = 3'd6;
  • //reg define
  • reg[2:0]   cur_state;        
  • reg[2:0]   next_state;        
  • reg[20:0]  count_1us;      
  • reg[5:0]   data_count;                                       
  • reg[39:0]  data_temp;        
  • reg[4:0]   clk_cnt;
  • reg        clk_1M;      
  • reg        us_clear;        
  • reg        state;        
  • reg        dht_buffer;        
  • reg        dht_d0;        
  • reg        dht_d1;        
  •                
  • wire       dht_podge;        //data posedge
  • wire       dht_nedge;        //data negedge
  • /*********************main codes*********************/
  • assign dht11     = dht_buffer;
  • assign dht_podge   = ~dht_d1 & dht_d0; // catch posedge
  • assign dht_nedge   = dht_d1  & (~dht_d0); // catch negedge
  • /*********************counters*****************************/
  • //clock with 1MHz
  • always @ (posedge clk or negedge rst_n) begin
  •     if (!rst_n) begin
  •         clk_cnt <= 5'd0;
  •         clk_1M  <= 1'b0;
  •     end
  •     else if (clk_cnt < 5'd24)
  •         clk_cnt <= clk_cnt + 1'b1;      
  •     else begin
  •         clk_cnt <= 5'd0;
  •         clk_1M  <= ~ clk_1M;
  •     end
  • end
  • //counter 1 us
  • always @ (posedge clk_1M or negedge rst_n) begin
  •     if (!rst_n)
  •         count_1us <= 21'd0;
  •     else if (us_clear)
  •         count_1us <= 21'd0;
  •     else
  •         count_1us <= count_1us + 1'b1;
  • end
  • //change state
  • always @ (posedge clk_1M or negedge rst_n) begin
  •     if (!rst_n)
  •         cur_state <= S_POWER_ON;
  •     else
  •         cur_state <= next_state;
  • end
  • // state machine
  • always @ (posedge clk_1M or negedge rst_n) begin
  •     if(!rst_n)
  •          begin
  •         next_state <= S_POWER_ON;
  •         dht_buffer <= 1'bz;   
  •         state      <= 1'b0;
  •         us_clear   <= 1'b0;
  •                   data_temp  <= 40'd0;
  •         data_count <= 6'd0;
  •     end
  •     else
  •          begin
  •         case (cur_state)     
  •             S_POWER_ON :    //wait
  •                                 begin               
  •              if(count_1us < POWER_ON_NUM)
  •                                  begin
  •                                         dht_buffer <= 1'bz;
  •                us_clear   <= 1'b0;
  •                                  end
  •              else
  •                                  begin            
  •                next_state <= S_LOW_20MS;
  •                                         us_clear   <= 1'b1;
  •                                  end
  •             end
  •                
  •             S_LOW_20MS:  // send 20 ms
  •                                 begin
  •              if(count_1us < 20000)
  •                                  begin
  •               dht_buffer <= 1'b0;
  •               us_clear   <= 1'b0;
  •              end
  •                                  else
  •                                  begin
  •                                   next_state   <= S_HIGH_13US;
  •               dht_buffer <= 1'bz;
  •               us_clear   <= 1'b1;
  •                 end   
  •             end
  •                
  •             S_HIGH_13US:  // Hign 13 us
  •                                 begin                     
  •              if (count_1us < 20)
  •                                  begin
  •               us_clear    <= 1'b0;
  •               if(dht_nedge)
  •                                   begin   
  •                                         next_state <= S_LOW_83US;
  •                us_clear   <= 1'b1;
  •               end
  •             end
  •               else                     
  •                 next_state <= st_delay;
  •             end
  •                
  •             S_LOW_83US:   
  •                                 begin                  
  •              if(dht_podge)                  
  •                next_state <= S_HIGH_87US;  
  •             end
  •                
  •             S_HIGH_87US:               // ready to receive data signal
  •                                 begin
  •              if(dht_nedge)
  •                                  begin         
  •               next_state <= S_SEND_DATA;
  •               us_clear    <= 1'b1;
  •              end
  •              else
  •                                  begin               
  •                data_count <= 6'd0;
  •                data_temp  <= 40'd0;
  •                state      <= 1'b0;
  •              end
  •             end
  •                   
  •             S_SEND_DATA:    // have 40 bit
  •                                 begin                                
  •               case(state)
  •                 0: begin               
  •                    if(dht_podge)
  •                                                  begin
  •                      state    <= 1'b1;
  •                      us_clear <= 1'b1;
  •                    end            
  •                    else               
  •                     us_clear  <= 1'b0;
  •                    end
  •                                                 
  •                 1: begin               
  •                    if(dht_nedge)
  •                                                  begin
  •                      data_count <= data_count + 1'b1;
  •                      state    <= 1'b0;
  •                                                         us_clear <= 1'b1;              
  •                      if(count_1us < 60)
  •                        data_temp <= {data_temp[38:0],1'b0}; //0
  •                      else               
  •                                                           data_temp <= {data_temp[38:0],1'b1}; //1
  •                     end
  •                       else                                            //wait for high end
  •                        us_clear <= 1'b0;
  •                     end
  •                 endcase
  •                
  •                 if(data_cnt == 40)                                      //check data bit
  •                                          begin  
  •                  next_state <= st_delay;
  •                  if(data_temp[7:0] == data_temp[39:32] + data_temp[31:24] + data_temp[23:16] + data_temp[15:8])
  •                    data_valid <= data_temp[39:8];  
  •                 end
  •             end
  •                
  •             S_DELAY:                                      // after data received delay 2s
  •                                 begin
  •              if(count_1us < 2000_000)
  •               us_cnt_clr <= 1'b0;
  •              else
  •                                  begin                 
  •               next_state <= S_LOW_20MS;              // send signal again
  •               us_cnt_clr <= 1'b1;
  •              end
  •            end
  •             default :
  •                                         cur_state <= cur_state;
  •         endcase
  •     end
  • end
  • //edge
  • always @ (posedge clk_1M or negedge rst_n) begin
  •     if (!rst_n) begin
  •         dht_d0 <= 1'b1;
  •         dht_d1 <= 1'b1;
  •     end
  •     else begin
  •         dht_d0 <= dht11;
  •         dht_d1 <= dht_d0;
  •     end
  • end
  • endmodule  
  • 复制代码