【FPGA】Verilog代码实现温湿度传感器DHT11

#今天也是咸鱼的一天~

因为参加Robei 杯 是要做一个机器人,先不说这个机器人具体怎么机器法,但是和外界互通的传感器肯定少不了,通过获取外界环境数据,进行处理,然后做出各种各样的功能。

先来讲个简单的模块,温湿度传感器DHT11。

DHT11介绍

DHT11是一款价格便宜,易于使用的温度湿度测量二合一传感器。它具有超小体积、极低功耗的特点。它使用单根总线与单片机进行双向的串行数据传输,信号传输距离可达20米以上。非常适用于对精度和实时性要求不高的温湿度测量场合。
本文将以DFRobot开源硬件平台的DHT11模块和DFRduino开发板来演示,讲解DHT11的驱动和使用。
DHT11电气参数
电源电压:3~5.5V(典型值:5V);
温度量程:0~50℃,误差 ±2℃;
湿度量程:20~90%RH,误差 ±5%RH;
采样周期:大于等于1秒/次。

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

工作原理

DHT11使用单一总线通信,即DATA引脚和单片机连接的线。总线总是处于空闲状态通信状态这个2个状态之间。
当单片机没有与DHT11交互时,总线处于空闲状态,在上拉电阻的作用下,处于高电平状态。
当单片机和DHT11正在通信时,总线处于通信状态,一次完整的通信过程如下:
①单片机将驱动总线的IO配置为输出模式。准备向DHT11发送数据。
②单片机将总线拉低至少18ms,以此来发送起始信号。再将总线拉高并延时20~40us,以此来代表起始信号结束。
③单片机将驱动总线的IO配置为输入模式,准备接收DHT11回传的数据。
④当DHT11检测倒单片机发送的起始信号后,就开始应答,回传采集到的传感器数据。DHT11先将总线拉低80us作为对单片机的应答(ACK),然后接着将总线拉高80us,准备回传采集到的温湿度数据。温湿度数据以固定的帧格式发送。
一帧为40个bit,而每一个bit的传输时序逻辑为:每一个bit都以50us的低电平(DHT11将总线拉低)为先导,然后紧接着DHT11拉高总线,如果这个高电平持续时间为26~28us,则代表逻辑0,如果持续70us则代表逻辑1。

在这里插入图片描述
看这张信号图,就可以知道模块和主控之间的通信方式。

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

Verilog驱动代码:

// 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                                     

亲测可用,里头注释都是英文的原因是,我写代码的时候开的英文键盘,写不了中文,这样可以避免中文符号的错误。

实物测试

在这里插入图片描述

这个是准备用在Robei 杯的比赛上的,但是现在还在纠结用Xilinx还是 Altera的板子,因为如果要用RISC-V架构的话,就一定得用Xilinx,调它的硬核。我感觉我还真的做不出来,所以打算先把结构搭出来,然后再试试看能不能用RISC-V 来实现。

  • 14
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: dht11湿度传感器是一种数字式湿度传感器,可以通过单总线接口与微控制器进行通信。在Verilog中,可以使用FPGA或ASIC实现dht11传感器的功能。需要编写Verilog代码来读取传感器的数据,并将其转换为数字信号。这需要使用计时器和状态机等技术来实现。同时,还需要考虑传感器的精度和稳定性等问题,以确保传感器的准确性和可靠性。 ### 回答2: DHT11湿度传感器是一种常用的数字式湿度传感器Verilog是一种硬件描述语言,它通常用于数字电路的设计和验证。那么,如何使用Verilog来设计和实现DHT11湿度传感器呢? 首先,我们需要了解DHT11的工作原理。DHT11传感器通过测量环境中的湿度和度,将其转化为数字信号,通过单总线串行发送给微控制器。因此,我们需要使用Verilog来设计和实现一个接口,使得DHT11传感器可以与微控制器通信。 具体来说,我们需要使用Verilog实现以下功能: 1. 定义DHT11传感器通信协议。DHT11传感器采用单总线串行通信方式,因此需要定义数据传输的时序和格式。 2. 实现DHT11传感器的数据接收和解码。微控制器需要通过Verilog来接收传感器发送的数字信号,并按照事先定义好的协议进行解码,提取出湿度数据。 3. 实现数据读取和处理。将湿度数据读取到寄存器中,并执行必要的数据处理操作,如单位转换和校验计算等。 总的来说,Verilog设计DHT11湿度传感器的过程需要根据具体的实际需求来进行定制化操作,需要对数字电路设计和Verilog语言有一定的掌握能力和经验。同时,需要注意到DHT11传感器通信速率较低,数据传输时序较为严格,因此在设计时需要优化传输速率和时序控制,以确保数据的准确性和稳定性。 ### 回答3: DHT11湿度传感器是一种广泛应用于环境检测和控制的传感器,它可以实时测量周围的度和湿度。Verilog是一种硬件描述语言,用于设计数字电路。通过将DHT11Verilog结合起来,我们可以建立一个完整的数字湿度检测系统。 在设计DHT11湿度传感器Verilog的过程中,我们需要首先了解DHT11的工作原理。DHT11度和湿度转换成数字信号输出,这些信号需要通过数字电路进行处理和解码,才能得到可读的湿度值。基于此,我们可以建立一个Verilog模块,接收来自DHT11的数字信号,并通过解码获得精确的湿度值。 在编写DHT11传感器Verilog代码时,需要考虑多方面的因素。首先,我们需要确定适当的时序和时钟信号来协调不同模块之间的数据传输和处理。其次,我们需要选择合适的解码算法以确保准确读取来自DHT11的信号。最后,我们需要设计一个有效的输出接口,将湿度值传输到其他系统或设备。 总的来说,DHT11湿度传感器Verilog的设计需要深入理解数字电路和传感器工作原理,同时又需要掌握Verilog的基本语法和特点。在实现过程中,我们需要按照逻辑思维和技术规范进行严密的设计和测试,以达到高效、可靠的数字检测系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值