FPGA读取DHT11数字温湿度传感器

这篇具有很好参考价值的文章主要介绍了FPGA读取DHT11数字温湿度传感器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在做一个DHT11相关的东西,写了一个DHT11控制模块。参考了正点原子和野火电子的文档资料后总觉得又乱又杂,所以自己跟着数据手册写了一遍,当然了也很感谢正点原子和野火文档的帮助。

DHT11是一种数字温湿度传感器,有4个引脚但只有三个有效引脚,分别是VDD,DATA和GND,如图1所示,使用的是典型的单总线通信,即一根数据线。这根数据线需要通过上拉电阻连接到电源,使得数据线在空闲时保持高电平。数据手册建议每2秒种对数据进行一次读取,来保证数据的稳定性。

FPGA读取DHT11数字温湿度传感器
图1 外观

单总线数据传输位定义:一次传输40位数据,高位先出。

数据格式:8bit湿度整数+8bit湿度小数+8bit温度整数+8bit温度小数+8bit校验位。

示例数据:

00110101  00000000  00011000  00000100  01010001

湿度高8位  湿度低8位  温度高8位  温度低8位  校验位8bit

计算:

00110101+00000000+00011000+00000100=01010001

湿度:00110101 = 35H = 53

  00000000 = 00H = 0  湿度为53.0%

温度:00011000 = 18H = 24

  00000100 = 04H = 0.4 温度为24.4℃

并且当温度低于0时温度数据的低8位的最高位置1。由于一般不会出现负数,所以此次设计不关心此处。

时序图如图2:

 文章来源地址https://www.toymoban.com/news/detail-451430.html

FPGA读取DHT11数字温湿度传感器
图2 时序图

 

外设读取步骤:

①设备上电,等待1s越过不稳定状态,由于2秒读取一次数据较稳定,所以我们等待2s。

②主机发送开始信号,数据线拉低至少18ms。此时总线由FPGA控制。

③主机将数据线拉高后释放总线等待从机响应,时间为13us。

④从机相应低电平,时间为83us。

⑤从机相应高电平,时间为87us。

⑥FPGA读取DHT11的温湿度数据。

图3为时间参数表。

FPGA读取DHT11数字温湿度传感器
图3 时间参数

由此我们可以确定使用状态机实现该设计,很轻松便可以画出状态转换图,如图4,图中状态分别对应上述外设读取的6个步骤。

FPGA读取DHT11数字温湿度传感器
图4 状态转换

 

 接下来就根据状态转换图来进行verilog代码的编写,代码如下。

/*
	description : dht11 control
*/
module dht11(
	input	sys_clk		,	//system clock
	input	sys_rst_n	,	//system reset negedge
	
	inout	dht11_data	,	//dht11 inout port
	
	output	reg	[39:0]	t_h_data
);

//---------state code
parameter	WAIT			=	6'b000_001,//wait state 2s
			START			=	6'b000_010,//make bus low 20ms
			WAIT_RES		=	6'b000_100,//wait respond
			RES_LOW			=	6'b001_000,//respond low
			RES_HIGH		=	6'b010_000,//respong high
			REC_DATA		=	6'b100_000;//receive datas
//---------time parameter
//parameter	CNT_2S_MAX		=	100	,
//			CNT_20MS_MAX	=	1_0	,
//			CNT_1US_MAX		=	50	;
parameter	CNT_2S_MAX		=	100_000_000	,
			CNT_20MS_MAX	=	1_000_000	,
			CNT_1US_MAX		=	50			;
//---------state define
reg	[5:0] 	state_cur;//current state
reg [5:0] 	state_nex;//next state
//---------flag define
wire		end_2s		;	//wait 2s end
wire		end_20ms    ;	//wait 20ms end
wire		res_ok      ;	//respond ok
wire		res_no      ;	//no respond
wire		end_res_low ;	//wait respond low end 83us
wire		end_res_high;	//wait respond high end 87us
wire		end_rec     ;	//data receive end 40bits
//---------dht11_data regist
reg			dht11_data_r1;
reg			dht11_data_r2;
wire		dht11_posedge;
wire		dht11_negedge;
reg			data;
reg			output_en;
wire		check;			//the datas is correct or wrong ?
reg	[39:0]	t_h_data_temp;//temperature and huminity data
//---------counter define
reg	[26:0]	cnt_2s;
reg [19:0]	cnt_20ms;
reg	[6:0]	cnt_nus;
reg	[5:0]	cnt_1us;
reg			cnt_us_rst;
reg	[5:0]	cnt_bit;
//---------flag assignments
assign	end_2s 			= (state_cur == WAIT && cnt_2s == CNT_2S_MAX - 1'b1) ? 1'b1 : 1'b0;
assign	end_20ms 		= (state_cur == START && cnt_20ms == CNT_20MS_MAX - 1'b1) ? 1'b1 : 1'b0;
assign	res_ok 			= (state_cur == WAIT_RES && cnt_nus < 20 && dht11_negedge) ? 1'b1 : 1'b0;
assign 	res_no 			= (state_cur == WAIT_RES && cnt_nus > 20) ? 1'b1 : 1'b0;
assign 	end_res_low 	= (state_cur == RES_LOW && cnt_nus > 70 && dht11_posedge) ? 1'b1 : 1'b0;
assign 	end_res_high 	= (state_cur == RES_HIGH && cnt_nus > 70 && dht11_negedge) ? 1'b1 : 1'b0;
assign	end_rec 		= (state_cur == REC_DATA && cnt_bit >= 40) ? 1'b1 : 1'b0;
//---------dht11 assignments
assign dht11_posedge = dht11_data_r1 & ~dht11_data_r2;
assign dht11_negedge = ~dht11_data_r1 & dht11_data_r2;
assign dht11_data = output_en ? data : 1'bz;
assign check = (t_h_data_temp[39:32]+t_h_data_temp[31:24]+
					t_h_data_temp[23:16]+t_h_data_temp[15:8] == t_h_data_temp[7:0])
					? 1'b1 : 1'b0;//the datas is correct or wrong ?
//*********posedge and negedge detect
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		dht11_data_r1 <= 1'b0;
		dht11_data_r2 <= 1'b0;
	end
	else begin
		dht11_data_r1 <= dht11_data;
		dht11_data_r2 <= dht11_data_r1;
	end
end
//*********counter
always@(*)begin
	case(state_cur)
		WAIT		:	cnt_us_rst = 1'b1;
	    START		:	cnt_us_rst = 1'b1;
	    WAIT_RES	:	begin
			if(res_ok)
				cnt_us_rst = 1'b1;
			else
				cnt_us_rst = 1'b0;
		end
	    RES_LOW		:	begin
			if(end_res_low)
				cnt_us_rst = 1'b1;
			else
				cnt_us_rst = 1'b0;
		end
	    RES_HIGH	:	begin
			if(end_res_high)
				cnt_us_rst = 1'b1;
			else
				cnt_us_rst = 1'b0;
		end
	    REC_DATA	:	begin
			if(dht11_posedge || dht11_negedge)
				cnt_us_rst = 1'b1;
			else
				cnt_us_rst = 1'b0;
		end
		default		:cnt_us_rst = 1'b1;
	endcase
end
//---------cnt_2s
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		cnt_2s <= 27'd0;
	end
	else begin
		if(state_cur == WAIT)begin
			if(cnt_2s <= CNT_2S_MAX - 1'b1)
				cnt_2s <= cnt_2s + 1'b1;
			else
				cnt_2s <= cnt_2s;
		end
		else if(state_cur == REC_DATA)begin
			cnt_2s <= 27'd0;
		end
		else begin
			cnt_2s <= cnt_2s;
		end
	end
end
//---------cnt_20ms
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		cnt_20ms <= 20'd0;
	end
	else begin
		if(state_cur == START)begin
			if(cnt_20ms <= CNT_20MS_MAX - 1'b1)
				cnt_20ms <= cnt_20ms + 1'b1;
			else
				cnt_20ms <= cnt_20ms;
		end
		else if(state_cur == REC_DATA)begin
			cnt_20ms <= 20'd0;
		end
		else begin
			cnt_20ms <= cnt_20ms;
		end
	end
end
//---------cnt_1us
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		cnt_1us <= 6'd0;
	end
	else begin
		if(cnt_1us == CNT_1US_MAX - 1'b1)
			cnt_1us <= 6'd0;
		else if(cnt_us_rst)
			cnt_1us <= 6'd0;
		else
			cnt_1us <= cnt_1us + 1'b1;
	end
end
//---------cnt_nus
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		cnt_nus <= 7'd0;
	end
	else begin
		if(cnt_us_rst)
			cnt_nus <= 7'd0;
		else if(cnt_1us == CNT_1US_MAX - 1'b1)
			cnt_nus <= cnt_nus + 1'b1;
		else
			cnt_nus <= cnt_nus;
	end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		cnt_bit <= 6'd0;
	end
	else begin
		if(state_cur == REC_DATA)begin
			if(dht11_negedge)
				cnt_bit <= cnt_bit + 1'b1;
			else
				cnt_bit <= cnt_bit;
		end
		else begin
			cnt_bit <= 6'd0;
		end
	end
end
//*********three stages state machine
//---------the first stage : state transmission
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)
		state_cur <= WAIT;
	else
		state_cur <= state_nex;
end
//---------the second stage : conditions
always@(*)begin
	case(state_cur)
		WAIT	:begin
			if(end_2s)
				state_nex = START;	//count 2s finish 
			else
				state_nex = WAIT;
		end		
		START	:begin
			if(end_20ms)
				state_nex = WAIT_RES;//count 20ms finish 
			else
				state_nex = START;
		end			
		WAIT_RES:begin	
			if(res_ok)				//respond 
				state_nex = RES_LOW;	
			else if(res_no)			//no respond 
				state_nex = WAIT;
			else
				state_nex = WAIT_RES;
		end			
		RES_LOW	:begin
			if(end_res_low)
				state_nex = RES_HIGH;
			else
				state_nex = RES_LOW;
		end			
		RES_HIGH:begin
			if(end_res_high)
				state_nex = REC_DATA;
			else
				state_nex = RES_HIGH;
		end			
		REC_DATA:begin
			if(end_rec)
				state_nex = WAIT;
			else
				state_nex = REC_DATA;
		end		
		default	:begin
			state_nex = WAIT;
		end			
	endcase
end
//---------the third stage : outputs
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		output_en <= 1'b0;
		data <= 1'b0;
	end
	else begin
		case(state_cur)
			WAIT	 :begin
				output_en <= 1'b1;//output
				data <= 1'b1;
			end
		    START	 :begin
				output_en <= 1'b1;//output
				data <= 1'b0;
				if(end_20ms)
					data <= 1'b1;
			end
		    WAIT_RES :begin
				output_en <= 1'b0;//input
				data <= 1'b0;
			end
		    RES_LOW	 :begin
				output_en <= 1'b0;//input
				data <= 1'b0;
			end
		    RES_HIGH :begin
				output_en <= 1'b0;//input
				data <= 1'b0;
			end
		    REC_DATA :begin
				output_en <= 1'b0;//input
				data <= 1'b0;
			end
			default  :begin
				output_en <= 1'b0;//input
				data <= 1'b0;
			end
		endcase
	end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		t_h_data_temp <= 40'd0;
	end
	else begin
		if(state_cur == REC_DATA)begin
			if(cnt_nus > 50 && dht11_negedge)
				t_h_data_temp[39 - cnt_bit] <= 1'b1;
			else if(cnt_nus < 50 && dht11_negedge)
				t_h_data_temp[39 - cnt_bit] <= 1'b0;
			else 
				t_h_data_temp <= t_h_data_temp;
		end
		else begin
			t_h_data_temp <= t_h_data_temp;
		end
	end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(~sys_rst_n)begin
		t_h_data <= 40'd0;
	end
	else begin
		if(state_cur == REC_DATA)begin
			if(end_rec && check)
				t_h_data <= t_h_data_temp;
			else
				t_h_data <= t_h_data;
		end
		else begin
			t_h_data <= t_h_data;
		end
	end
end
endmodule

 完成代码后仿真观察前三个状态,modelsim仿真结果如图5,可以清晰地观察到状态的转换以及转换条件。

FPGA读取DHT11数字温湿度传感器
图5 仿真图

由于没有dht11仿真模型,所以只好使用signaltap直接对实际波形进行抓取,在抓取了几次之后并且更改代码后得到了最终的正确结果,如图6,读取波形数据后可得湿度为18,温度为25,并且校验通过,数据读取正确。

FPGA读取DHT11数字温湿度传感器
图6 signaltap波形

 

随后通过数码管进行显示,数码管模块的代码非常简单,这里就不再贴出,直接查看最后的上板实验效果,只显示了温湿度的整数位,如图7,左侧为湿度,右侧为温度。

FPGA读取DHT11数字温湿度传感器
图7 上板测试

参考资料:

1.dht11数据手册

2.征途Mini《FPGA Verilog开发实战指南——基于Altera EP4CE10》

3.新起点FPGA开发指南

 

到了这里,关于FPGA读取DHT11数字温湿度传感器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA实验笔记_Vivado:DDS信号发生器;数码管;基于DHT11的温湿度传感器

    目录 1、 FPGA的DDS信号发生器 1.1、DDS简介 1.2、ROM IP核的生成 1.3、波形数据的生成 1.4、 ROM的调用 1.5、 完整代码(包括拓展部分) 2、数码管显示 2.1、数码管简要说明 2.2、SM410564 3、基于DHT11的温湿度传感器 3.1、DHT11 3.2、基本思路 3.3、数据分离模块(BTD) 3.4、数据转换模块(

    2024年02月04日
    浏览(56)
  • DHT11温湿度传感器学习

     DHT11温湿度传感器共有四个引脚 1个VCC高电平,1个GND接地低电平,1个数据输出引脚,一个空引脚 工作时候,通过out引脚可以向传感器传递应答信号并返回40位的温湿度数据,也就是5个字节 前2个字节表示温度的整数位和小数位,后面两个字节是湿度的整数位和小数位,最后

    2024年02月07日
    浏览(66)
  • 温湿度传感器DHT11介绍

    温湿度传感器DHT11简介       DHT11数字温湿度传感器是一种出厂时经过校准的数字信号输出的温湿度数字温湿度传感器 。DHT11 数字温湿度传感器应用温湿度传感技术和数字采集技术,确保其具有极高的可靠性和卓越的长期稳定性。       DHT11 数字温湿度传感器内置一个电阻式

    2023年04月22日
    浏览(54)
  • 【mcuclub】温湿度传感器DHT11

    为什么接上拉电阻: 因为DHT11的数据口是漏极开路,如果不接上拉电阻,则只能输出低电平和高阻态,不能输出高电平,因此需要外接上拉电阻,否则无法输出1。DHT11的工作电流约为1mA,VCC一般为5V,则电阻R=5V/1mA=5KΩ。一般3.3k~10k都可以。 DHT11 数字温湿度传感器是一款含有已

    2024年02月06日
    浏览(54)
  • CC2530——温湿度传感器DHT11

    DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH,温度±2℃,量程湿度5~95%RH,温度-20~+60℃。  1、用户主机(单片机)发送一次开始信号后,DHT11从低功耗模式转换到高速模式。 2、到主机开始信号结束后,DHT11发送响应信号。 3、DHT11并送出40bit(5个字节)

    2024年02月04日
    浏览(44)
  • STM32+DHT11温湿度传感器

    DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次 通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数 部分用于以后扩展,现读出为零.操作流程如下: 一次完整的数据传输为40bit,高位先出。 数据格式:8bit湿度整数数据+8bit湿度小数数据

    2023年04月13日
    浏览(50)
  • STM32--DHT11温湿度传感器

    本文介绍基于STM32F103实现的DHT11温湿度传感器数据采集及显示,完整代码见文末链接 一、DHT11传感器简介 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期

    2024年02月16日
    浏览(54)
  • STM32—DHT11温湿度传感器

    (1).下图一是DHT11总的时序图。 (2).图二对应图一的左边黑色部分,图三对应图一的绿色部分,图四的左部分图对应图一的红色部分,图四的右部分对应图一的黄色部分。 (3).首先图二部分是单片机向DHT11发送我要开始的信号,此时单片机IO口处于输出模式,输出低电平至少18MS,

    2024年02月19日
    浏览(56)
  • stm32连接DHT11温湿度传感器

    目录 1. DHT11简介 1.1. 连接电路  1.2. 串行接口 (单线双向)  2. cubeMX设置 3. 代码开发  3.1. 实现定时函数 3.2. 打开串口调试 3.4. 测试代码实现 4. 运行效果 信息如下: 建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使 用合适的上拉电阻  DHT11的供电电压为 3-5

    2023年04月16日
    浏览(50)
  • DHT11温湿度传感器(配合树莓派使用)

    DHT11是一种数字温湿度传感器,可以测量周围环境的温度和相对湿度。该传感器使用单个数字信号线与微控制器通信,具有较高的可靠性和稳定性。它适用于许多应用领域,如气象观测、室内环境监测、工业控制等。 DHT11传感器使用的基本原理是通过感应元件测量周围环境的

    2024年02月06日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包