DHT11温湿度传感器的FPGA驱动代码
发布日期:2021-05-07 22:56:16 浏览次数:22 分类:精选文章

本文共 6175 字,大约阅读时间需要 20 分钟。

一、说明书主要内容

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 SIMmodule	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
上一篇:US100超声波测距模块的FPGA驱动
下一篇:基于FPGA的数字钟 ——最终实现

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2025年04月04日 18时57分48秒