-

实验展示

DHT11相关文档

程序部分

顶层模块:

dht11.v
module dht11( input wire sys_clk, input wire sys_rst_n, inout wire dht11, input wire key, output wire [7:0]segdata, output wire [2:0]segcs ); wire key_flag; wire [19:0] data_out; key_filter #( .CNT_MAX(20'd999_999) ) key_filter_inst ( .sys_clk (sys_clk) , .sys_rst_n (sys_rst_n) , .key_in (key) , .led_out(), .key_flag(key_flag) ); dht11_ctrl dht11_ctrl_inst ( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .key_flag(key_flag), .dht11(dht11), .data_out(data_out), .sign() ); seg seg_inst ( .clk(sys_clk), .rst_n(sys_rst_n), .tenvalue(data_out), // 这里连接没有问题 .segdata(segdata), .segcs(segcs) ); endmodule

6位数码管驱动模块:

seg.v
/* 数码管显示驱动,目前是直接设置固定数据 通过将tenvalue设置到输入端口,可以作为子模块,通过传入数据显示在数码管上面 */ module seg( input clk, input rst_n, input [19:0]tenvalue, output reg [7:0]segdata, output reg [2:0]segcs ); reg[31:0] count; reg[24:0]count1ms; reg[2:0]number; reg clk1ms; parameter sample=2'b00, display=2'b01; //-----------数码管驱动时钟----------- always@(posedge clk) begin if(count1ms >= 25'd50000) // 1ms的计数器 begin clk1ms <= ~clk1ms; count1ms <= 1'd0; end else count1ms <= count1ms + 1'd1; end //-----------从0开始显示数字----------- //assign tenvalue = 20'd99999; //固定显示999 //-----------数码管译码----------- function [7:0] leddata; input [3:0] datain; begin case(datain) 4'd0: leddata = 8'b11000000; // 0 4'd1: leddata = 8'b11111001; // 1 4'd2: leddata = 8'b10100100; // 2 4'd3: leddata = 8'b10110000; // 3 4'd4: leddata = 8'b10011001; // 4 4'd5: leddata = 8'b10010010; // 5 4'd6: leddata = 8'b10000010; // 6 4'd7: leddata = 8'b11111000; // 7 4'd8: leddata = 8'b10000000; // 8 4'd9: leddata = 8'b10010000; // 9 4'd10: leddata = 8'b10111111; // - 4'd11: leddata = 8'b01111111; // . default: leddata = 8'b11111111; endcase end endfunction //-----------数码管扫描----------- always@(posedge clk1ms or negedge rst_n) begin if(!rst_n) number <= 3'd0; else if(number == 3'd5) number <= 3'd0; else number <= number + 1; case(number) 3'd0: begin segdata <= leddata(tenvalue % 10); // 个位 segcs <= 3'b101; end 3'd1: begin segdata <= leddata((tenvalue / 10) % 10); // 十位 segcs <= 3'b100; end 3'd2: begin segdata <= leddata((tenvalue / 100) % 10); // 百位 segcs <= 3'b011; end 4'd3: begin segdata<=leddata((tenvalue/1000)%10);//千位 segcs<=3'b010; end 4'd4: begin segdata<=leddata((tenvalue/10000)%10);//万位 segcs<=3'b001; end 4'd5: begin segdata<=leddata((tenvalue/100000)%10);//十万位 segcs<=3'b000; end default: begin segdata <= 8'b11111111; // 或者其他默认值 segcs <= 3'b111; // 或者其他默认值 end endcase end endmodule

dht11驱动模块

dht11_ctrl.v
module dht11_ctrl( input wire sys_clk, input wire sys_rst_n, input wire key_flag, inout wire dht11, output reg [19:0] data_out, output reg sign ); // 状态转移变量的赋值 parameter S_WAIT_1S = 3'd1 , //上电等待1s状态 S_LOW_18MS = 3'd2 , //主机拉低18ms,发送开始信号状态 S_DLY1 = 3'd3 , //等待20-40us状态 S_REPLY = 3'd4 , //DHT11响应80us状态 S_DLY2 = 3'd5 , //拉高等待80us状态 S_RD_DATA = 3'd6 ; //接收数据状态 parameter T_1S_DATA = 999999 ; //1s时间计数值 parameter T_18MS_DATA = 17999 ; //18ms时间计数值 // 内部参数的定义 reg clk_us; reg [4:0] cnt; reg [5:0] state; // 状态机变量 reg [19:0] cnt_us ; // 计数器 reg [19:0] cnt_low; // reg dht11_reg1; // reg dht11_reg2; // wire dht11_rise; // wire dht11_fall; // reg [5:0] bit_cnt; // 发送的bit计数,总共发送40bit的数据 reg [39:0] data_temp; reg [31:0] data; reg data_flag; // 数据发送的标志信号 reg dht11_en; // dht11使能信号 wire dht11_out; // // 生成us时钟信号 always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt <= 5'd0; else if(cnt == 5'd24) cnt <= 5'd0; else cnt <= cnt+1'd1; end always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) clk_us <= 1'd0; else if(cnt == 5'd24) clk_us <= ~clk_us; else clk_us <= clk_us; end //状态机状态跳转 always@(posedge clk_us or negedge sys_rst_n) if(sys_rst_n == 1'b0) state <= S_WAIT_1S ; else case(state) S_WAIT_1S: if(cnt_us == T_1S_DATA) //上电1s后跳入起始状态 state <= S_LOW_18MS ; else state <= S_WAIT_1S ; S_LOW_18MS: if(cnt_us == T_18MS_DATA) state <= S_DLY1 ; else state <= S_LOW_18MS ; S_DLY1: if(cnt_us == 10) //等待10us后进入下一状态 state <= S_REPLY ; else state <= S_DLY1 ; S_REPLY: //上升沿到来且低电平保持时间大于70us,则跳转到下一状态 if(dht11_rise == 1'b1 && cnt_low >= 70) state <= S_DLY2 ; //若1ms后,dht11还没响应,则回去继续发送起始信号 else if(cnt_us >= 1000) state <= S_LOW_18MS ; else state <= S_REPLY ; S_DLY2: //下降沿到来且计数器值大于70us,则跳转到下一状态 if(dht11_fall == 1'b1 && cnt_us >= 70) state <= S_RD_DATA ; else state <= S_DLY2 ; S_RD_DATA: //读完数据后,回到起始状态 if(bit_cnt == 40 && dht11_rise == 1'b1) state <= S_LOW_18MS ; else state <= S_RD_DATA ; default: state <= S_WAIT_1S ; endcase //各状态下的计数器赋值 //cnt_us:每到一个新的状态就让该计数器重新计数 always@(posedge clk_us or negedge sys_rst_n) if(sys_rst_n == 1'b0) begin cnt_low <= 7'd0 ; cnt_us <= 21'd0 ; end else case(state) S_WAIT_1S: if(cnt_us == T_1S_DATA) cnt_us <= 21'd0 ; else cnt_us <= cnt_us + 1'b1; S_LOW_18MS: if(cnt_us == T_18MS_DATA) cnt_us <= 21'd0 ; else cnt_us <= cnt_us + 1'b1; S_DLY1: if(cnt_us == 10) cnt_us <= 21'd0 ; else cnt_us <= cnt_us + 1'b1; S_REPLY: if(dht11_rise == 1'b1 && cnt_low >= 70) begin cnt_low <= 7'd0 ; cnt_us <= 21'd0 ; end //当dht11发送低电平回应时,计算其低电平的持续时间 else if(dht11 == 1'b0) begin cnt_low <= cnt_low + 1'b1 ; cnt_us <= cnt_us + 1'b1 ; end //若1ms后,dht11还没响应,则回去继续发送起始信号 else if(cnt_us >= 1000) begin cnt_low <= 7'd0 ; cnt_us <= 21'd0 ; end else begin cnt_low <= cnt_low ; cnt_us <= cnt_us + 1'b1 ; end S_DLY2: if(dht11_fall == 1'b1 && cnt_us >= 70) cnt_us <= 21'd0 ; else cnt_us <= cnt_us + 1'b1; S_RD_DATA: if(dht11_fall == 1'b1 || dht11_rise == 1'b1) cnt_us <= 21'd0 ; else cnt_us <= cnt_us + 1'b1; default: begin cnt_low <= 7'd0 ; cnt_us <= 21'd0 ; end endcase // 打两拍,提取dht11的输入信号的上升沿和下降沿 always @(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) begin dht11_reg1 <= 1'd1; dht11_reg2 <= 1'd1; end else begin dht11_reg1 <= dht11; dht11_reg2 <= dht11_reg1; end end assign dht11_rise = (~dht11_reg2) && (dht11_reg1) ; assign dht11_fall = (dht11_reg2) && (~dht11_reg1) ; // bit_cnt的搭建 always @(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) bit_cnt <= 6'd0; else if(bit_cnt == 6'd40 && dht11_rise == 1'd1) bit_cnt <= 6'd0; else if(state == S_RD_DATA && dht11_fall == 1'd1) bit_cnt <= bit_cnt + 1'd1; else bit_cnt <= bit_cnt; end // data_temp always @(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) data_temp <= 40'd0; else if(state == S_RD_DATA && dht11_fall == 1'd1 && cnt_us <=50) data_temp[39-bit_cnt] <= 1'd0; else if(state == S_RD_DATA && dht11_fall == 1'd1 && cnt_us >50) data_temp[39-bit_cnt] <= 1'd1; else data_temp <= data_temp; end //数据校验和赋值 always@(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) 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; end // dht11_en 的赋值 always @(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) dht11_en <= 1'd0; else if(state == S_LOW_18MS) dht11_en <= 1'd1; else dht11_en <= 1'd0; end // dht11_out 的赋值 assign dht11_out = 1'd0 ; // data_flag 的赋值 always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) data_flag <= 1'd0; else if(key_flag == 1'd0) data_flag <= ~data_flag; else data_flag <= data_flag; end // 输出信号 always @(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) data_out <= 20'd0; else if(data_flag == 1'd0) data_out <= data[31:24]*10; else if(data_flag == 1'd1) data_out <= (data[15:8]*10) + data[3:0]; end // 符号位 always @(posedge clk_us or negedge sys_rst_n) begin if(!sys_rst_n) sign <= 1'd0; else if(data_flag == 1'd1 && data[7] == 1'd1) sign <= 1'd1; else sign <= 1'd0; end // 如果使能是高电平,则吧dht11_out赋值给dht11输出端口。否则dht11端口作为输入端口为高阻态状态 assign dht11 = (dht11_en == 1'd1) ? dht11_out : 1'bz; endmodule

按键消抖模块

key_filter.v
module key_filter #( parameter CNT_MAX = 32'd99999 ) ( input wire sys_clk , input wire sys_rst_n , input wire key_in , output reg key_flag , output reg led_out ); reg [31:0] cnt_20ms; always @(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) cnt_20ms<=20'd0; else if(key_in == 1'b1) cnt_20ms<=20'd0; else if(cnt_20ms == CNT_MAX) cnt_20ms<=CNT_MAX; else cnt_20ms<=cnt_20ms+20'd1; always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) key_flag<=1'b0; else if(cnt_20ms == (CNT_MAX-20'd1)) key_flag<=1'b1; else key_flag<=1'b0; end always @(*) begin if(!sys_rst_n) led_out<=1'b0; else if(cnt_20ms == CNT_MAX) led_out<=1'b0; else led_out<=1'b1; end endmodule

引脚配置

参考链接

[1] ChatGPT3.5

[2] 128-第三十九讲-DHT11数字温湿度传感器(一)_哔哩哔哩_bilibili


本站由 John Doe 使用 Stellar 1.28.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本"页面"访问 次 | 👀总访问 次 | 🥷总访客