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]}]