DHT22温湿度传感器verilog驱动代码FPGA开发

之前毕业设计写过的用在FPGA上的DHT22温湿度传感器verilog驱动代码,亲测可用,有什么问题欢迎留言。

module DHT22_drive (
    input                clk   ,   //系统时钟
    input                res     ,   //系统复位                                    
    inout                dht22     ,   //dht22温湿度传感器单总线
	 output  reg  [31:0]  data_out      //温度高位
);                                                                             
//parameter define 
parameter  POWER_ON_NUM     = 1000_000; //上电延时等待时间,单位us
//状态机各个状态                     
parameter  st_power_on_wait = 3'd0;     //上电延时等待 000
parameter  st_low_500us      = 3'd1;     //主机发送500us低电平 001
parameter  st_high_40us     = 3'd2;     //主机释放总线40us 010
parameter  st_rec_low_83us  = 3'd3;     //接收83us低电平响应 011
parameter  st_rec_high_87us = 3'd4;     //等待87us高电平(准备接收数据)100
parameter  st_rec_data      = 3'd5;     //接收40位数据 101
parameter  st_delay         = 3'd6;     //延时等待,延时完成后重新操作DHT22 110

//reg define
reg    [2:0]   cur_state   ;        //当前状态 3位寄存器
reg    [2:0]   next_state  ;        //下一个状态
                                    
reg    [4:0]   clk_cnt     ;        //分频计数器
reg            clk_1m      ;        //1Mhz时钟
reg    [20:0]  us_cnt      ;        //1微秒计数器
reg            us_cnt_clr  ;        //1微秒计数器清零信号
                                    
reg    [39:0]  data_temp   ;        //缓存接收到的数据
reg            step        ;        //数据采集状态
reg    [5:0]   data_cnt    ;        //接收数据用计数器

reg            dht22_buffer;        //DHT22输出信号
reg            dht22_d0    ;        //DHT22输入信号寄存器0
reg            dht22_d1    ;        //DHT22输入信号寄存器1

//wire define                       
wire        dht22_pos      ;        //DHT22上升沿
wire        dht22_neg      ;        //DHT22下降沿

//*****************************************************
//**                    main code
//*****************************************************

assign dht22     = dht22_buffer;
assign dht22_pos = ~dht22_d1 & dht22_d0; //采集上升沿
assign dht22_neg = dht22_d1 & ~dht22_d0; //采集下降沿

//得到1Mhz分频时钟
always @ (posedge clk or negedge res) begin   //posedge上升沿触发或者negedge下降沿触发
    if (!res) 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

//对DHT22输入信号连续寄存两次,用于边沿检测
always @ (posedge clk_1m or negedge res) begin
    if (!res) begin
        dht22_d0 <= 1'b1;
        dht22_d1 <= 1'b1;
    end 
    else begin
        dht22_d0 <= dht22;
        dht22_d1 <= dht22_d0;
    end 
end 

//1微秒计数器
always @ (posedge clk_1m or negedge res) begin
    if (!res)
        us_cnt <= 21'd0;
    else if (us_cnt_clr)
        us_cnt <= 21'd0;
    else 
        us_cnt <= us_cnt + 1'b1;
end 

//状态跳转
always @ (posedge clk_1m or negedge res) begin
    if (!res)
        cur_state <= st_power_on_wait;
    else 
        cur_state <= next_state;
end 

//状态机读取DHT11数据
always @ (posedge clk_1m or negedge res) begin
    if(!res) begin
        next_state   <= st_power_on_wait;
        data_temp    <= 40'd0;
        step         <= 1'b0; 
        us_cnt_clr   <= 1'b0;
        data_cnt     <= 6'd0;
        dht22_buffer <= 1'bz;   
    end 
    else begin
        case (cur_state)
                //上电后延时1秒等待DHT22稳定
            st_power_on_wait : begin                
                if(us_cnt < POWER_ON_NUM) begin
                    dht22_buffer <= 1'bz; //空闲状态释放总线
                    us_cnt_clr   <= 1'b0;
                end
                else begin            
                    next_state   <= st_low_500us;
                    us_cnt_clr   <= 1'b1;
                end
            end
                //FPGA发送起始信号(500us的低电平)    
            st_low_500us: begin
                if(us_cnt < 500) begin
                    dht22_buffer <= 1'b0; //起始信号为低电平 
                    us_cnt_clr   <= 1'b0;
                end
                else begin
                    dht22_buffer <= 1'bz; //起始信号结束后释放总线
                    next_state   <= st_high_40us;
                    us_cnt_clr   <= 1'b1;
                end    
            end 
                //等待DHT22的响应信号(等待20~40us)
            st_high_40us:begin                      
                if (us_cnt < 40) begin
                    us_cnt_clr   <= 1'b0;
                    if(dht22_neg) begin   //检测到DHT22响应信号
                        next_state <= st_rec_low_83us;
                        us_cnt_clr <= 1'b1; 
                    end
                end
                else                      //超过40us未响应
                    next_state <= st_delay;
            end 
                //等待DHT22的83us低电平响应信号结束
            st_rec_low_83us: begin                  
                if(dht22_pos)                   
                    next_state <= st_rec_high_87us;  
            end 
                //DHT22拉高87us通知FPGA准备接收数据
            st_rec_high_87us: begin
                if(dht22_neg) begin       //准备时间结束    
                    next_state <= st_rec_data; 
                    us_cnt_clr <= 1'b1;
                end
                else begin                //高电平准备接收数据
                    data_cnt  <= 6'd0;
                    data_temp <= 40'd0;
                    step  <= 1'b0;
                end
            end 
                //连续接收40位数据 
            st_rec_data: begin                                
                case(step)
                    0: begin              //接收数据低电平
                        if(dht22_pos) begin 
                            step   <= 1'b1;
                            us_cnt_clr <= 1'b1;
                        end            
                        else              //等待数据低电平结束
                            us_cnt_clr <= 1'b0;
                    end
                    1: begin              //接收数据高电平
                        if(dht22_neg) begin 
                            data_cnt <= data_cnt + 1'b1;
                                          //判断接收数据为0/1
                            if(us_cnt < 60)
                                data_temp <= {data_temp[38:0],1'b0};
                            else                
                                data_temp <= {data_temp[38:0],1'b1};
                            step <= 1'b0;
                            us_cnt_clr <= 1'b1;
                        end 
                        else              //等待数据高电平结束
                            us_cnt_clr <= 1'b0;
                    end
                endcase
                
                if(data_cnt == 40) 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_out <= data_temp[39:8];  
                end
            end 
                //完成一次数据采集后延时2s
            st_delay:begin
                if(us_cnt < 2000_000)
                    us_cnt_clr <= 1'b0;
                else begin                //延时结束后重新发送起始信号
                    next_state <= st_low_500us;      
                    us_cnt_clr <= 1'b1;
                end
            end
            default : ;
        endcase
    end 
end

endmodule   
  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值