NEXYS4_DDR迪芝伦XC7A100TCSG324-1型,DHT11测温湿度(野火)

0. 注意

0.1 本示例只显示了温度,并未显示湿度

0.2 等待的时间间隔为2秒,低于2秒时发生数据读取错误;

0.2.1成功读取一次数据后,可能出现程序卡死在 REPLY 状态

0.2.2发送数据在 bit_cnt = 28 时突然清0,数据出现错误,并卡死在下一个循环的 REPLY 状态

1. DHT11简介

1.1 DHT11数据时序图

在这里插入图片描述

1.2 数据

dht11在读数据阶段会发送40位数据,且高位先出
在这里插入图片描述

2. 总体框图

在这里插入图片描述

3.状态转移图

在这里插入图片描述

4. 时序图

在这里插入图片描述

5. 设计文件

5.1 dht11.v

module  dht11
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    
    inout   wire            dht11       ,
    
    output  wire    [7:0]   sel         ,
    output  wire    [7:0]   seg         
);

wire    [19:0]  data_out;

dht11_ctrl  dht11_ctrl_inst
(
    .sys_clk     (sys_clk  ),
    .sys_rst_n   (sys_rst_n),

    .dht11       (dht11    ),

    .data_out    (data_out )
);

seg_dynamic
#(
    .CNT_MAX(17'd99_999)
)
seg_dynamic_inst
(
    .sys_clk     (sys_clk  ),
    .sys_rst_n   (sys_rst_n),
    .data        (data_out ),

    .sel         (sel      ),
    .seg         (seg      ) 
);

ila_0 ila_inst (
	.clk(sys_clk), // input wire clk

	.probe0(dht11_ctrl_inst.clk_us), // input wire [0:0]  probe0  
	.probe1(dht11_ctrl_inst.state), // input wire [5:0]  probe1 
	.probe2(dht11_ctrl_inst.cnt_us), // input wire [20:0]  probe2 
	.probe3(dht11_ctrl_inst.cnt_low), // input wire [19:0]  probe3 
	.probe4(dht11_ctrl_inst.dht11_reg1), // input wire [0:0]  probe4 
	.probe5(dht11_ctrl_inst.dht11_reg2), // input wire [0:0]  probe5 
	.probe6(dht11_ctrl_inst.dht11_rise), // input wire [0:0]  probe6 
	.probe7(dht11_ctrl_inst.dht11_fall), // input wire [0:0]  probe7 
	.probe8(dht11_ctrl_inst.bit_cnt), // input wire [5:0]  probe8 
	.probe9(dht11_ctrl_inst.data_temp), // input wire [39:0]  probe9 
	.probe10(dht11_ctrl_inst.data), // input wire [31:0]  probe10 
	.probe11(dht11_ctrl_inst.data_flag), // input wire [0:0]  probe11 
	.probe12(dht11_ctrl_inst.data_out) // input wire [0:0]  probe12
);

endmodule

5.2 dht11_ctrl.v

module  dht11_ctrl
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    
    inout   wire            dht11       ,
    
    output  reg     [19:0]  data_out    
);

parameter   WAIT_1S = 6'b000_001,
            START   = 6'b000_010,
            DLY_1   = 6'b000_100,
            REPLY   = 6'b001_000,
            DLY_2   = 6'b010_000,
            RD_DATA = 6'b100_000;

parameter   WAIT_1S_MAX = 21'd1_999_999,
            LOW_20MS_MAX = 20'd19_999;

parameter   CNT_100MS_MAX = 27'd19_999;

wire            dht11_rise  ;
wire            dht11_fall  ;

reg     [19:0]  data_100ms  ;
reg     [26:0]  cnt_100ms   ;
reg             clk_us      ;
reg     [6:0]   cnt         ;
reg     [5:0]   state       ;
reg     [20:0]  cnt_us      ;
reg     [19:0]  cnt_low     ;
reg             dht11_reg1  ;
reg             dht11_reg2  ;
reg     [5:0]   bit_cnt     ;
reg     [39:0]  data_temp   ;
reg     [31:0]  data        ;
reg             data_flag   ;
reg             dht11_en    ;
reg             dht11_out   ;


assign  dht11 = (dht11_en == 1'b1) ? dht11_out : 1'bz;
assign  dht11_rise = (~dht11_reg2) && (dht11_reg1);
assign  dht11_fall = (dht11_reg2) && (~dht11_reg1);


//cnt,计数器,计数50,50*10ns
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 6'd0;
    else    if(cnt == 6'd49)
        cnt <= 6'd0;
    else
        cnt <= cnt + 1'b1;
//clk_us,1us的信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        clk_us <= 1'b0;
    else    if(cnt == 6'd49)
        clk_us <= ~clk_us;
    else
        clk_us <= clk_us;
//cnt_100ms
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_100ms <= 27'd0;
    else    if(cnt_100ms == CNT_100MS_MAX)
        cnt_100ms <= 27'd0;
    else
        cnt_100ms <= cnt_100ms + 1'b1;
//state,状态转移
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        state <= WAIT_1S;
    else
        case(state)
            WAIT_1S :
                if(cnt_us == WAIT_1S_MAX)
                    state <= START;
                else
                    state <= WAIT_1S;
            START   :
                if(cnt_us == LOW_20MS_MAX)
                    state <= DLY_1;
                else
                    state <= START;
            DLY_1   :
                if(cnt_us == 20'd10)
                    state <= REPLY;
                else
                    state <= DLY_1;
            REPLY   :
                if(dht11_rise == 1'b1 && cnt_low > 80)
                    state <= DLY_2;
                else    if(clk_us >= 1000)
                    state <= START;
                else
                    state <= REPLY;
            DLY_2   :
                if(dht11_fall == 1'b1 && cnt_us > 80)
                    state <= RD_DATA;
                else
                    state <= DLY_2;
            RD_DATA :
                if(bit_cnt == 40 && dht11_rise == 1'b1)
                    state <= WAIT_1S;
                else
                    state <= RD_DATA;
            default:state <= WAIT_1S;
        endcase

always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            cnt_us  <= 20'd0;
            cnt_low <= 20'd0;
        end
    else
        case(state)
            WAIT_1S :
                if(cnt_us == WAIT_1S_MAX)
                    cnt_us <= 20'd0;
                else
                    cnt_us <= cnt_us + 1'b1;
            START   :
                if(cnt_us == LOW_20MS_MAX)
                    cnt_us <= 20'd0;
                else
                    cnt_us <= cnt_us + 1'b1;
            DLY_1   :
                if(cnt_us == 10)
                    cnt_us <= 20'd0;
                else
                    cnt_us <= cnt_us + 1'b1;
            REPLY   :
                if(dht11_rise == 1'b1 && cnt_low > 80)
                    begin
                        cnt_us  <= 20'd0;
                        cnt_low <= 20'd0;
                    end
                else    if(dht11 == 1'b0)
                    begin
                        cnt_us  <= cnt_us + 1'b1;
                        cnt_low <= cnt_low + 1'b1;
                    end
                else    if(cnt_us > 1000)
                    begin
                        cnt_us  <= 20'd0;
                        cnt_low <= 20'd0;
                    end
                else
                    begin
                        cnt_us  <= cnt_us + 1'b1;
                        cnt_low <= cnt_low;
                    end
            DLY_2   :
                if(dht11_fall == 1'b1 && cnt_us > 80)
                    cnt_us <= 20'd0;
                else
                    cnt_us <= cnt_us + 1'b1;
            RD_DATA :
                if(dht11_fall == 1'b1 || dht11_rise == 1'b1)
                    cnt_us <= 20'd0;
                else
                    cnt_us <= cnt_us + 1'b1;
            default:
                begin
                    cnt_us  <= 20'd0;
                    cnt_low <= 20'd0;
                end
    endcase
//dht11打两拍,dht11_reg2
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            dht11_reg1 <= 1'b1;
            dht11_reg2 <= 1'b1;
        end
    else
        begin
            dht11_reg1 <= dht11;
            dht11_reg2 <= dht11_reg1;
        end

//bit_cnt
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        bit_cnt <= 6'd0;
    else    if(bit_cnt == 40 && dht11_rise == 1'b1)
        bit_cnt <= 6'd0;
    else    if(state == RD_DATA && dht11_fall == 1'b1)
        bit_cnt <= bit_cnt +1'b1;

//data_temp
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_temp <= 40'b0;
    else    if(state == RD_DATA && dht11_fall == 1'b1 && cnt_us <= 50)
        data_temp[39 - bit_cnt] <= 1'b0;
    else    if(state == RD_DATA && dht11_fall == 1'b1 && cnt_us > 50)
        data_temp[39 - bit_cnt] <= 1'b1;
    else
        data_temp <= data_temp;
//data
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data <= 32'd0;
    else    if(data_temp[7:0] == (data_temp[39:32] + data_temp[31:24] 
                + data_temp[23:16] + data_temp[15:8]))
        data <= data_temp[39:8];
    else
        data <= data;
//dht11_en
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        dht11_en <= 1'b0;
    else    if(state == START)
        dht11_en <= 1'b1;
    else
        dht11_en <= 1'b0;
//dht11_out
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        dht11_out <= 1'b0;
    else
        dht11_out <= 1'b0;



//data_flag
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_flag <= 1'b0;
    else    if(data_temp[7:0] == (data_temp[39:32] + data_temp[31:24] 
                + data_temp[23:16] + data_temp[15:8]) && (bit_cnt == 40))
        data_flag <= 1'b1;
    else
        data_flag <= 1'b0;
//data_out
always@(posedge data_flag or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_out <= 20'd0;
    else    
        data_out <= data[15:8] * 10 + data[3:0];


/* //data_out
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_out <= 20'd0;
    else    
        data_out <= data[15:8] * 10 + data[3:0]; */

/* //data_100ms
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_100ms <= 20'd0;
    else    if(state == RD_DATA)
        data_100ms <= data[15:8] * 10 + data[3:0];
    else
        data_100ms <= data_100ms;
//data_out
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_out <= 20'd0;
    else    if(cnt_100ms == CNT_100MS_MAX)
        data_out <= data_100ms;
    else
        data_out <= data_out; */


/* //data_flag
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_flag <= 1'b0;
    else    if(key_flag == 1'b1)
        data_flag <= ~data_flag;
    else
        data_flag <= data_flag;
//data_out
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_out <= 20'd0;
    else    if(data_flag == 1'b0)
        data_out <= data[31:24] * 10;
    else    if(data_flag == 1'b1)
        data_out <= (data[15:8] * 10) + data[3:0];
//sign
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sign <= 1'b0;
    else    if(data_flag == 1'b1 && data[7] == 1'b1)
        sign <= 1'b1;
    else
        sign <= 1'b0; */

endmodule

5.3 seg_dynamic.v

module  seg_dynamic
#(
    parameter   CNT_MAX =   17'd99_999
)
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    input   wire    [26:0]  data        ,

    output  reg     [7:0]   sel         ,
    output  reg     [7:0]   seg          
);



wire     [3:0]   in          ;
wire     [3:0]   ten         ;
wire     [3:0]   hun         ;
wire     [3:0]   tho         ;
wire     [3:0]   ten_tho     ;
wire     [3:0]   hun_tho     ;
wire     [3:0]   mil         ;
wire     [3:0]   must        ;


reg     [3:0]   seg_data    ;
reg     [2:0]   cnt_sel     ;

reg     [16:0]  cnt_1ms     ;
reg             flag_1ms    ;

//cnt_1ms:1ms循环计数
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_1ms <=  17'd0;
    else    if(cnt_1ms == CNT_MAX)
        cnt_1ms <=  17'd0;
    else
        cnt_1ms <=  cnt_1ms + 1'b1;

//flag_1ms:1ms标志信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        flag_1ms    <=  1'b0;
    else    if(cnt_1ms == CNT_MAX - 1'b1)
        flag_1ms    <=  1'b1;
    else
        flag_1ms    <=  1'b0;

//cnt_sel:从0到7循环数,用于选择当前显示的数码管
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_sel <=  3'd0;
    else    if((cnt_sel == 3'd7) && (flag_1ms == 1'b1))
        cnt_sel <=  3'd0;
    else    if(flag_1ms == 1'b1)
        cnt_sel <=  cnt_sel + 1'b1;
    else
        cnt_sel <=  cnt_sel;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg_data <= 8'b0000_0011;
    else
        begin
            case(cnt_sel)
                3'd0: seg_data <= in     ;
                3'd1: seg_data <= ten    ;
                3'd2: seg_data <= hun    ;
                3'd3: seg_data <= tho    ;
                3'd4: seg_data <= ten_tho;
                3'd5: seg_data <= hun_tho;
                3'd6: seg_data <= mil    ;
                3'd7: seg_data <= must   ;
            endcase
        end

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sel <= 8'b0111_1111;
    else    if(flag_1ms == 1'b1)
        begin
            case(cnt_sel)
                3'd0: sel <= 8'b0111_1110;
                3'd1: sel <= 8'b1111_1101;
                3'd2: sel <= 8'b1111_1011;
                3'd3: sel <= 8'b1111_0111;
                3'd4: sel <= 8'b1110_1111;
                3'd5: sel <= 8'b1101_1111;
                3'd6: sel <= 8'b1011_1111;
                3'd7: sel <= 8'b0111_1111;
            endcase
        end


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg <= 8'b0000_0011;
    else    if(flag_1ms == 1'b1)
        begin
            case(seg_data)
                4'd0: seg <= 8'b0000_0011;
                4'd1: seg <= 8'b1001_1111;
                4'd2: seg <= 8'b0010_0101;
                4'd3: seg <= 8'b0000_1101;
                4'd4: seg <= 8'b1001_1001;
                4'd5: seg <= 8'b0100_1001;
                4'd6: seg <= 8'b0100_0001;
                4'd7: seg <= 8'b0001_1111;
                4'd8: seg <= 8'b0000_0001;
                4'd9: seg <= 8'b0000_1001;
            endcase
        end
    else
        seg <= seg;



bcd_8421    bcd_8421_inst
(
    .sys_clk    (sys_clk  ),
    .sys_rst_n  (sys_rst_n),
    .data       (data     ),

    .in         (in       ), //个
    .ten        (ten      ), //十
    .hun        (hun      ), //百
    .tho        (tho      ), //千
    .ten_tho    (ten_tho  ), //万
    .hun_tho    (hun_tho  ), //十万
    .mil        (mil      ), //百万
    .must       (must     )  //千万
);


endmodule

5.4 bcd_8421.v

module  bcd_8421
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    input   wire    [26:0]  data        ,
    
    output  reg     [3:0]   in          , //个
    output  reg     [3:0]   ten         , //十
    output  reg     [3:0]   hun         , //百
    output  reg     [3:0]   tho         , //千
    output  reg     [3:0]   ten_tho     , //万
    output  reg     [3:0]   hun_tho     , //十万
    output  reg     [3:0]   mil         , //百万
    output  reg     [3:0]   must          //千万

);

reg     [4:0]   cnt_shift   ;
reg     [58:0]  data_shift  ;
reg             shift_flag  ;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_shift <= 5'd0;
    else    if((cnt_shift == 5'd28) && (shift_flag == 1'b1))
        cnt_shift <= 5'd0;
    else    if(shift_flag == 1'b1)
        cnt_shift <= cnt_shift + 1'b1;
    else
        cnt_shift <= cnt_shift;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_shift <= 59'd0;
    else    if(cnt_shift == 5'd0)
        data_shift <= {32'b0,data};
    else    if((cnt_shift <= 5'd27) && (shift_flag == 1'b0))
        begin
            data_shift[30:27] <= (data_shift[30:27] > 4) ? (data_shift[30:27] + 2'd3) : (data_shift[30:27]);
            data_shift[34:31] <= (data_shift[34:31] > 4) ? (data_shift[34:31] + 2'd3) : (data_shift[34:31]);
            data_shift[38:35] <= (data_shift[38:35] > 4) ? (data_shift[38:35] + 2'd3) : (data_shift[38:35]);
            data_shift[42:39] <= (data_shift[42:39] > 4) ? (data_shift[42:39] + 2'd3) : (data_shift[42:39]);
            data_shift[46:43] <= (data_shift[46:43] > 4) ? (data_shift[46:43] + 2'd3) : (data_shift[46:43]);
            data_shift[50:47] <= (data_shift[50:47] > 4) ? (data_shift[50:47] + 2'd3) : (data_shift[50:47]);
            data_shift[54:51] <= (data_shift[54:51] > 4) ? (data_shift[54:51] + 2'd3) : (data_shift[54:51]);
            data_shift[58:55] <= (data_shift[58:55] > 4) ? (data_shift[58:55] + 2'd3) : (data_shift[58:55]);
        end
    else    if((cnt_shift <= 5'd27) && (shift_flag == 1'b1))    
        data_shift <= data_shift << 1;
    else
        data_shift <= data_shift;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        shift_flag <= 1'b0;
    else
        shift_flag <= ~shift_flag;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            in      <= 4'b0;
            ten     <= 4'b0;
            hun     <= 4'b0;
            tho     <= 4'b0;
            ten_tho <= 4'b0;
            hun_tho <= 4'b0;
            mil     <= 4'b0;
            must    <= 4'b0;
        end
    else    if(cnt_shift == 5'd28)
        begin
            in      <= data_shift[30:27];
            ten     <= data_shift[34:31];
            hun     <= data_shift[38:35];
            tho     <= data_shift[42:39];
            ten_tho <= data_shift[46:43];
            hun_tho <= data_shift[50:47];
            mil     <= data_shift[54:51];
            must    <= data_shift[58:55];
        end

endmodule

6. NEXYS4_DDR迪芝伦XC7A100TCSG324-1型的原理图与管脚绑定

dht11.xdc

set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports dht11]

set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports {sel[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[0]}]

set_property PACKAGE_PIN E3 [get_ports sys_clk]
set_property PACKAGE_PIN J15 [get_ports sys_rst_n]
set_property PACKAGE_PIN G17 [get_ports dht11]


set_property PACKAGE_PIN J17 [get_ports {sel[0]}]
set_property PACKAGE_PIN J18 [get_ports {sel[1]}]
set_property PACKAGE_PIN T9  [get_ports {sel[2]}]
set_property PACKAGE_PIN J14 [get_ports {sel[3]}]
set_property PACKAGE_PIN P14 [get_ports {sel[4]}]
set_property PACKAGE_PIN T14 [get_ports {sel[5]}]
set_property PACKAGE_PIN K2  [get_ports {sel[6]}]
set_property PACKAGE_PIN U13 [get_ports {sel[7]}]

set_property PACKAGE_PIN H15 [get_ports {seg[0]}]
set_property PACKAGE_PIN L18 [get_ports {seg[1]}]
set_property PACKAGE_PIN T11 [get_ports {seg[2]}]
set_property PACKAGE_PIN P15 [get_ports {seg[3]}]
set_property PACKAGE_PIN K13 [get_ports {seg[4]}]
set_property PACKAGE_PIN K16 [get_ports {seg[5]}]
set_property PACKAGE_PIN R10 [get_ports {seg[6]}]
set_property PACKAGE_PIN T10 [get_ports {seg[7]}]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值