DHT11温湿度传感器的FPGA驱动代码

一、说明书主要内容

1、产品概述

在这里插入图片描述

2、接口说明

串行接口:
在这里插入图片描述

3、通讯过程

在这里插入图片描述
从通讯时序可以看出,读取一帧传感器数据的时序为:
主机将data线拉低至少18ms,然后拉高20-40us。然后主机释放data线给dht11,dht11将data线拉低80us作为响应信号,再拉高80us,若主机检测到正确的响应信号,读操作即可开始。
读操作
dht11将data线拉低50us,然后拉高,如果这一位表示‘0’,则拉高时间为26-28us,若表示‘1’,则拉高时间为70us

Verilog驱动

//作者:杨成煜
//日期:2020/4/6
//==================defines=====================
//`define SIM
module	dht11(
	//================System Signal================
	input				clk,
	input				rst_n,
	//================Interface====================
	inout				data,
	input				rd_req,
	output reg[39:0]	data_rd
);
	//================parameters===================
	`ifndef SIM
	localparam			CNT_30US = 1499;
	localparam			CNT_20MS = 999_999;
	localparam			CNT_80US = 3999;
	localparam			CNT_50US = 2499;
	localparam			CNT_70US = 3499;
	localparam			CNT_28US = 1399;
	`else
	
	`endif
	//state
	localparam			S_IDLE = 5'b00001;
	localparam			S_START= 5'b00010;
	localparam			S_DHT_ACK=5'b00100;
	localparam			S_DHT_SEND_DATA = 5'b01000;
	localparam			S_CHECK_DATA_BIT = 5'b10000;
	//================System regs==================
	reg  				DATA;
	reg[19:0]			cnt_20ms;
	reg[10:0]			cnt_30us;
	reg[11:0]			cnt_80us;
	reg[11:0]			cnt_50us;
	reg[11:0]			cnt_70us;
	reg 				cnt_dht_ack_bit;
	reg 				flag_rd;
	reg[3:0]			state;
	reg 				rd_req_t0;
	reg					rd_req_t1;
	wire				trig_rd_rq;
	reg 				data_t0;
	reg 				data_t1;
	wire				data_pedge;
	wire				data_nedge;
	wire 				flag_check_data_bit;
	reg 				flag_check_data_done;
	reg[5:0]			cnt_data_bit;
	reg 				flag_cnt_30us_en;
	//================Main Codes===================
	//flag_cnt_30us_en
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			flag_cnt_30us_en <= 1'b0;
		else if(state==S_START&&cnt_20ms==CNT_20MS)
			flag_cnt_30us_en <= 1'b1;
		else if(state==S_START&&cnt_30us==CNT_30US)
			flag_cnt_30us_en <= 1'b0;
	end
	
	//cnt_data_bit
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_data_bit <= 'd0;
		else if(cnt_data_bit==6'd39&&flag_check_data_done==1'b1)
			cnt_data_bit <= 'd0;
		else if(flag_check_data_done==1'b1)
			cnt_data_bit <= cnt_data_bit + 1'b1;
	end
	
	//flag_check_data_done
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			flag_check_data_done <= 1'b0;
		else if(state==S_CHECK_DATA_BIT&&data_nedge==1'b1)
			flag_check_data_done <= 1'b1;
		else
			flag_check_data_done <= 1'b0;
	end
	
	//flag_check_data_bit
	assign flag_check_data_bit = (state==S_CHECK_DATA_BIT&&flag_check_data_done==1'b0)?1'b1:1'b0;
	//data_rd
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			data_rd <= 'd0;
		else if(state==S_CHECK_DATA_BIT)
			if(cnt_70us<=CNT_28US&&flag_check_data_done==1'b1)
				data_rd <= {data_rd[38:0],1'b0};
			else if(cnt_70us<=CNT_80US&&flag_check_data_done==1'b1)
				data_rd <= {data_rd[38:0],1'b1};
	end
	// DATA;
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			DATA <= 1'b1;
		else if(state==S_IDLE||state==S_START)
			if(trig_rd_rq==1'b1&&flag_rd==1'b0)
				DATA <= 1'b0;
			else if(cnt_20ms==CNT_20MS)
				DATA <= 1'b1;
	end
	//cnt_20ms
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_20ms <= 'd0;
		else if(state==S_START)
			if(cnt_20ms==CNT_20MS)
				cnt_20ms <= 'd0;
			else
				cnt_20ms <= cnt_20ms + 1'b1;
		else
			cnt_20ms <= 'd0;
	end
	//cnt_30us
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_30us <= 'd0;
		else if(state==S_START&&flag_cnt_30us_en==1'b1)
			if(cnt_30us==CNT_30US)
				cnt_30us <= 'd0;
			else
				cnt_30us <= cnt_30us + 1'b1;
		else
			cnt_30us <= 'd0;
	end
	//cnt_80us
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_80us <= 'd0;
		else if(state==S_DHT_ACK)
			if(cnt_80us==CNT_80US)
				cnt_80us <= 'd0;
			else
				cnt_80us <= cnt_80us + 1'b1;
		else
			cnt_80us <= 'd0;
	end
	//cnt_50us
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_50us <= 'd0;
		else if(state==S_DHT_SEND_DATA)
			if(cnt_50us==CNT_50US)
				cnt_50us <= 'd0;
			else
				cnt_50us <= cnt_50us + 1'b1;
		else
			cnt_50us <= 'd0;
	end
	//cnt_70us
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_70us <= 'd0;
		else if(state==S_CHECK_DATA_BIT)
			if(cnt_70us==CNT_70US)
				cnt_70us <= 'd0;
			else
				cnt_70us <= cnt_70us + 1'b1;
		else
			cnt_70us <= 'd0;
	end
	//cnt_dht_ack_bit
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_dht_ack_bit <= 'd0;
		else if(state==S_DHT_ACK)
			if(cnt_dht_ack_bit==1'b0&&cnt_80us==CNT_80US)
				cnt_dht_ack_bit <= 1'b1;
			else if(cnt_dht_ack_bit==1'b1&&cnt_80us==CNT_80US)
				cnt_dht_ack_bit <= 1'b0;
	end
	//flag_rd
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			flag_rd <= 1'b0;
		else if(state==S_IDLE)
			if(trig_rd_rq==1'b1)
				flag_rd <= 1'b1;
			else
				flag_rd <= 1'b0;
		else if(state==S_CHECK_DATA_BIT)
			if(cnt_data_bit==6'd39&&flag_check_data_done==1'b1)
				flag_rd <= 1'b0;
			else
				flag_rd <= 1'b1;
	end
	
	assign data = (state==S_IDLE||state==S_START&&cnt_30us<=CNT_30US)?DATA:1'bz;
	//rd_req_temp
	always	@(posedge clk)begin
		rd_req_t0 <= rd_req;
		rd_req_t1 <= rd_req_t0;
	end
	assign trig_rd_rq = rd_req_t0&(~rd_req_t1);
	
	//data_temp
	always	@(posedge clk)begin
		if(state==S_CHECK_DATA_BIT)
			data_t0 <= data;
			data_t1 <= data_t0;
	end
	assign	data_nedge = (~data_t0)&data_t1;
	assign	data_pedge = data_t0&(~data_t1);
	
	//state machine
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			state <= S_IDLE;
		else case(state)
			S_IDLE:begin
				if(trig_rd_rq==1'b1)
					state <= S_START;
				else
					state <= S_IDLE;
			end
			S_START:begin
				if(cnt_30us==CNT_30US&&cnt_20ms==20'd0)
					state <= S_DHT_ACK;
				else
					state <= S_START;
			end
			S_DHT_ACK:begin
				if(cnt_80us==1999&&data==1'b0&&cnt_dht_ack_bit==1'b0)
					state <= S_DHT_ACK;
				else if(cnt_80us==1999&&cnt_dht_ack_bit==1'b1)
					state <= S_DHT_SEND_DATA;
				else if(cnt_80us==1999&&data==1'b1&&cnt_dht_ack_bit==1'b0)
					state <= S_IDLE;
			end
			S_DHT_SEND_DATA:begin
				if(cnt_50us==CNT_50US)
					state <= S_CHECK_DATA_BIT;
				else
					state <= S_DHT_SEND_DATA;
			end
			S_CHECK_DATA_BIT:begin
				if(cnt_data_bit==6'd39&&flag_check_data_bit==1'b1&&flag_check_data_done==1'b1)
					state <= S_IDLE;
				else if(flag_check_data_bit==1'b1&&flag_check_data_done==1'b1)
					state <= S_DHT_SEND_DATA;
				else
					state <= S_CHECK_DATA_BIT;
			end
			default:state <= S_IDLE;
		endcase
	end
	
endmodule

发布了18 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43650722/article/details/105350506