DHT11之Verilog 驱动代码

测试平台: Vivado 2018.3+Xilinx XC7A35TFGG484-2
关于DHT11时序,优缺点网上很多,就不说了.
话不多说了,直接上代码:
代码有不懂的地方欢迎与我交流.微信1247652780

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2020 All rights reserved
// -----------------------------------------------------------------------------
// Author : zhufu.liang	e-mail:1247652780@qq.com
// File   : dht11.v
// Create : 2020-12-12 21:04:12
// Revise : 2020-12-13 10:45:10
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------

module dht11(
	input	wire			clk,//100MHz
	input	wire			rst,
	input	wire			start,
	inout	wire			data_io,
	output	reg				vld_falg,
	output	reg		[7:0]	himi,
	output	reg		[7:0]	temp
);
	parameter	START_MAX 	=2000000-1;
	parameter	RESP_MAX  	=8200-1;
	parameter	LOW_MIN	  	=2200-1;
	parameter	LOW_MAX	  	=2800-1;
	parameter	HIGH_MIN	=6700-1;
	parameter	HIGH_MAX	=7500-1;
	parameter	END_MAX		=5300-1;


	parameter	IDLE	=5'b00_001;
	parameter	START	=5'b00_010;
	parameter	RESP	=5'b00_100;
	parameter	RECE	=5'b01_000;
	parameter	END 	=5'b10_000;

	reg	[4:0]	state;	
	reg	[1:0]	data_dly;
	reg			pos_flag;
	reg			neg_flag;
	reg	[21:0]	level_cnt;
	reg	[5:0]	bit_cnt;

	reg	[42:0]	data_temp;

	reg			oe;
	reg			data_o;
	reg			check_ok;

	always @(posedge clk) begin
		if (rst) begin
			oe<=1'b0;
		end
	    else if(state==START)begin
	        oe<=1'b1;
	    end
	    else begin
	    	oe<=1'b0;
	    end
	end

	assign data_io = (oe==1'b1)?data_o:1'bz;

	always @(posedge clk) begin
		if (rst) begin
			data_o<=1'b1;
		end
		else if (state==START && level_cnt==START_MAX) begin
			data_o<=1'b1;
		end
	    else if (state==START) begin
			data_o<=1'b0;
		end
	end

	always @(posedge clk) begin
		data_dly<={data_dly[0],data_io};
	end

	always @(*) begin
		if(data_dly==2'b10)begin
			neg_flag =1'b1;
		end
		else begin
			neg_flag =1'b0;
		end
	end

	always @(*) begin
		if(data_dly==2'b01)begin
			pos_flag =1'b1;
		end
		else begin
			pos_flag =1'b0;
		end
	end

	//state
	always @(posedge clk) begin
		if (rst) begin
			state<=IDLE;
		end
		else  begin
			case(state)
				IDLE:begin
					if(start==1'b1)begin
						state<=START;
					end
				end
				START:begin
					if(level_cnt == START_MAX)begin
						state<=RESP;
					end
				end
				RESP:begin
					if(pos_flag==1'b1 && level_cnt > RESP_MAX)begin
						state<=RECE;
					end
				end
				RECE:begin
					if(bit_cnt=='d41)begin
						state<=END;
					end
				end
				END:begin
					if(pos_flag==1'b1 && level_cnt > END_MAX)begin
						state<=IDLE;
					end
				end

				default:state<=IDLE;
			endcase
		end
	end

	//low_cnt
	always @(posedge clk) begin
		if (rst) begin
			level_cnt<='d0;
		end
		else begin
			case(state)
				START:begin
					if(level_cnt==START_MAX)begin
						level_cnt<='d0;
					end
					else if(data_o==1'b0)begin
						level_cnt<=level_cnt+1'b1;
					end
				end
				RESP:begin
					if(pos_flag==1'b1)begin
						level_cnt<='d0;
					end
					else if(data_dly[1]==1'b0)begin
						level_cnt<=level_cnt+1'b1;
					end
				end
				RECE:begin
					if(neg_flag==1'b1)begin
						level_cnt<='d0;
					end
					else if(data_dly[1]==1'b1)begin
						level_cnt<=level_cnt+1'b1;
					end
				end
				END:begin
					if(pos_flag==1'b1)begin
						level_cnt<='d0;
					end
					else if(data_dly[1]==1'b0)begin
						level_cnt<=level_cnt+1'b1;
					end
				end

				default:level_cnt<='d0;
			endcase
		end
	end

	//bit_cnt
	always @(posedge clk) begin
		if (rst) begin
			bit_cnt<='d0;
		end
		else if(state!=RECE)begin
			bit_cnt<='d0;
		end
		else if (state==RECE && neg_flag==1'b1 && level_cnt > LOW_MIN) begin
			bit_cnt<= bit_cnt+1'b1;
		end
	end

	//data_temp
	always @(posedge clk) begin
		if (rst) begin
			data_temp<='d0;
		end
		else if(state==RECE && neg_flag==1'b1 && level_cnt > LOW_MIN && level_cnt < LOW_MAX ) begin
			data_temp<={data_temp[38:0],1'b0};
		end
	    else if(state==RECE && neg_flag==1'b1 && level_cnt > HIGH_MIN && level_cnt < HIGH_MAX )begin
	        data_temp<={data_temp[38:0],1'b1};
	    end
	end

	//check_ok
	always @(posedge clk) begin
		if (rst) begin
			check_ok<=1'b0;
		end
		else if (state==END) begin
			check_ok<=({data_temp[39:32]+data_temp[15:8]+data_temp[23:16]+data_temp[31:24]}==data_temp[7:0])?1'b1:1'b0;
		end
	    else begin
	        check_ok<=1'b0;
	    end
	end

	//himi
	always @(posedge clk) begin
		if (rst) begin
			himi<='d0;
		end
		else if (state==END && pos_flag==1'b1) begin
			himi<= (data_temp[42:36]<<3) +(data_temp[40:36]<<1)+data_temp[35:32];
		end
	end

	//temp
	always @(posedge clk) begin
		if (rst) begin
			temp<='d0;
		end
		else if (state==END && pos_flag==1'b1 && data_temp[15]==1'b0) begin
			temp<= (data_temp[26:20]<<3)+(data_temp[24:20]<<1)+data_temp[19:16];
		end
		else if (state==END && pos_flag==1'b1 && data_temp[15]==1'b1) begin
			temp[6:0]	<= ~((data_temp[26:20]<<3)+(data_temp[24:20]<<1)+data_temp[19:16])+1'b1;
			temp[7]		<= 1'b1;
		end
	end

	//vld_falg
	always @(posedge clk) begin
		if (rst) begin
			vld_falg<=1'b0;
		end
		else if (state==END && pos_flag==1'b1) begin
			vld_falg<=1'b1;
		end
	    else begin
	        vld_falg<=1'b0;
	    end
	end

endmodule 

下面为顶层:

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2020 All rights reserved
// -----------------------------------------------------------------------------
// Author : zhufu.liang	e-mail:1247652780@qq.com
// File   : top_dht11.v
// Create : 2020-12-12 21:03:56
// Revise : 2020-12-12 22:54:08
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------

module top_dht11(
		input	wire		clk,//50MHz
		input	wire		rst_n,//active low
		inout	wire		data_io//data input/output
    );

	parameter	TIME_MAX = 200000000-1;//2s ==need more than 2s
	reg			start;//signal of start =2s
	wire		vld_falg;//valid data flag
	wire[7:0]	himi;//data of humidity
	wire[7:0]	temp;//data of temperature

	reg	[31:0]	time_cnt;//timer for 2s
	wire sclk;
	wire	rst;

	assign rst = ~rst_n;

	gen_clk100 inst_gen_clk100(
   		 // Clock out ports
   		 .clk_100m(sclk),     // output clk_100m
   		// Clock in ports
   		 .clk_in1(clk)
    );      // input clk_in1


	always @(posedge sclk) begin
		if (rst) begin
			time_cnt<='d0;
		end
		else if (time_cnt==TIME_MAX) begin
			time_cnt<='d0;
		end
	    else begin
	        time_cnt<=time_cnt+1'b1;
	    end
	end
	always @(posedge sclk) begin
		if (rst) begin
			start<=1'b0;
		end
		else if (time_cnt==TIME_MAX) begin
			start<=1'b1;
		end
	    else begin
	        start<=1'b0;
	    end
	end

	dht11  inst_dht11 (
			.clk      (sclk),
			.rst      (rst),//active high
			.start    (start),
			.data_io  (data_io),
			.vld_falg (vld_falg),
			.himi     (himi),
			.temp     (temp)
		);


	wire [127:0] probe0;
	assign  probe0 ={
		start,
		time_cnt,
		vld_falg,
		himi,
		temp
	} ;
	ila_0 ila_0_inst (
	.clk(sclk), // input wire sclk
	.probe0(probe0) // input wire [31:0] probe0
);

endmodule

最后为testbench:

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2020 All rights reserved
// -----------------------------------------------------------------------------
// Author : zhufu.liang	e-mail:1247652780@qq.com
// File   : tb_dht11.v
// Create : 2020-12-12 21:04:19
// Revise : 2020-12-12 21:04:21
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------


`timescale 1ns/1ns

module tb_dht11 (); /* this is automatically generated */

	reg 		clk;
	reg			start;
	reg       	data_io_r;
	wand		data_io;
	wire       	vld_falg;
	wire [7:0] 	himi;
	wire [7:0] 	temp;

	// clock
	initial begin
		clk = 0;
		forever #(5) clk = ~clk;
	end

	// synchronous reset
	reg       	rst;
	initial begin
		start=0;
		data_io_r=1;
		rst <= 1;
		repeat(100)@(posedge clk)
		rst <= 0;
		#100;
		gen_data(32'h33005500);
		@(negedge vld_falg);
		#1000;

		gen_data(32'h77004480);
		@(negedge vld_falg);
		#1000;

		gen_data(32'h88006680);
		@(negedge vld_falg);
		#10000;
		$stop;
	end

	assign data_io = data_io_r;
	dht11 inst_dht11(
			.clk      (clk),
			.rst      (rst),
			.start	  (start),
			.data_io  (data_io),
			.vld_falg (vld_falg),
			.himi     (himi),
			.temp     (temp)
		);

	task gen_data;
		input [31:0] data;
		integer i;
		reg	[7:0]	check_sum;
		reg	[39:0]	temp;
		reg	[21:0]	tiem_cnt;
		begin
			check_sum={data[7:0]+data[15:8]+data[23:16]+data[31:24]};
			temp={data,check_sum};
			start=0;
			tiem_cnt=0;
			#10;
			start=1;
			#10;
			start=0;
			@(negedge data_io)
			@(posedge data_io)
			data_io_r=1;
			#13_000;
			data_io_r=0;
			#83_000;
			data_io_r=1;
			#87_000;
			for(i=0;i<40;i=i+1)begin
				data_io_r=0;
				#54_000;
				if(temp[39])begin
					data_io_r=1;
					#71_000;
				end
				else begin
					data_io_r=1;
					#24_000;
				end
				temp=temp<<1;
			end
			data_io_r=0;
			#54_000;
			data_io_r=1;
		end
	endtask

endmodule

板级验证:
在这里插入图片描述

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是使用Qt编写的DHT11传感器驱动代码,可以通过调用该驱动代码,获取DHT11传感器的温湿度数据: DHT11.h文件 ```c++ #ifndef DHT11_H #define DHT11_H #include <QObject> #include <wiringPi.h> class DHT11 : public QObject { Q_OBJECT public: explicit DHT11(QObject *parent = nullptr); public slots: void readData(); signals: void humidityAndTemperature(double humidity, double temperature); private: int dht11_val[5]={0,0,0,0,0}; }; #endif // DHT11_H ``` DHT11.cpp文件 ```c++ #include "DHT11.h" #include <iostream> using namespace std; #define DHT11PIN 7 DHT11::DHT11(QObject *parent) : QObject(parent) { if(wiringPiSetup()==-1) exit(1); } void DHT11::readData() { unsigned char lststate=HIGH; unsigned char counter=0; unsigned char j=0,i; for(i=0;i<5;i++) dht11_val[i]=0; pinMode(DHT11PIN,OUTPUT); digitalWrite(DHT11PIN,LOW); delay(18); digitalWrite(DHT11PIN,HIGH); delayMicroseconds(40); pinMode(DHT11PIN,INPUT); for(i=0;i<85;i++) { counter=0; while(digitalRead(DHT11PIN)==lststate) { counter++; delayMicroseconds(1); if(counter==255) break; } lststate=digitalRead(DHT11PIN); if(counter==255) break; if((i>=4)&&(i%2==0)) { dht11_val[j/8]<<=1; if(counter>16) dht11_val[j/8]|=1; j++; } } if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xff))) { double humidity = dht11_val[0] + dht11_val[1] * 0.1; double temperature = dht11_val[2] + dht11_val[3] * 0.1; emit humidityAndTemperature(humidity, temperature); } else cout << "Invalid Data!!" << endl; } ``` 在DHT11类中,实现了一个readData()函数,用于读取DHT11传感器的温湿度数据。在读取完数据后,通过信号humidityAndTemperature(),将温湿度数据发送出去。在主程序中,可以通过连接该信号,实现对温湿度数据的获取。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值