基于FPGA的温湿度检测

初始化部分就不过多赘述,我会给出对应的文件,我只说明这部分里面涉及到使用的代码部分

1、数据的读取和校验

数据的读取和检验代码如下

always @ (posedge clk_us)
  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;

在这个代码之前,我们已经用data_temp存储了温湿度传感器传输的数据

数据组成

温湿度传感器传过来的是一个四十位的数据,具体的意义对应如下

(1)data_temp[39:32]——湿度整数部分

(2)data_temp[31:24]——湿度小数部分

(3)data_temp[23:16]——温度整数部分

(4)data_temp[15:8]——温度小数部分

(5)data_temp[7:0]——校验和

校验思路

校验思路根据数据本身的意义进行,如果数据正确

则数据的校验和部分等于其他所有部分的相加

数据读取

数据的读取基于校验进行

若校验通过,则将温湿度传感器传回数据的前32位赋值给data[](后八位校验和只用于校验)

若校验不通过,则将data本身的值赋值给data[]

2、数据输出部分

代码部分如下

always @ (posedge clk_us)
  begin
    data_out[11:4] <= data[15:8];      // 输出温度的整数部分
    data_out[3:0] <= data[3:0];        // 输出温度的小数部分
    data_out[19:12] <= data[31:24];    // 输出湿度的整数部分
  end

在之前我们已经介绍了温湿度传过来数据的组成,也说了数据读取的部分,所以这里就不再介绍为什么数据的部分的实际意义

3、按键标志位控制数据标志

always @ (posedge sys_clk)
  if (key_flag == 1'b1)
    data_flag <= ~data_flag;
  else
    data_flag <= data_flag;

data_flag是一个标志位,用来选择要显示的是湿度数据还是温度数据。当data_flag为1时,表示选择的是温度数据。 

4、符号输出

温度的数据是带有符号的,也根据温湿度传输过来的数据确定

温度的符号根据温度数据的最高有效位确定

always @ (posedge clk_us)
  if (data_flag == 1'b1 && data[7] == 1'b1)
    sign <= 1'b1;
  else 
    sign <= 1'b0;

5、状态机

状态机状态转换图

 状态机部分代码

always @(posedge clk_us)
    case (state)
        WAIT_1S:
            if (cnt_us == WAIT1S_MAX)
                state <= START;
            else 
                state <= WAIT_1S;
        START:
            if (cnt_us == LOW_18MS_MSX)
                state <= DLY_1;
            else 
                state <= START;
        DLY_1:
            if (cnt_us == 20'd10)
                state <= REPLY;
            else 
                state <= DLY_1;
        REPLY:
            if (dht11_rise == 1'b1 && cnt_low > 80)
                state <= DLY_2;
            else if (cnt_us > 1000)
                state <= START;
            else 
                state <= REPLY;
        DLY_2:
            if (dht11_fall == 1'b1 && cnt_us > 80)
                state <= RD_DATA;
            else 
                state <= DLY_2;
        RD_DATA:
            if (bit_cnt == 40 && dht11_rise == 1'b1)
                state <= START;
            else
                state <= RD_DATA;
        default: state <= WAIT_1S;
    endcase


always @(posedge clk_us)
    case(state)
        WAIT_1S:
            if (cnt_us == WAIT1S_MAX)
                cnt_us <= 20'd0;
            else
                cnt_us <= cnt_us + 1'b1;
        START:
            if (cnt_us == LOW_18MS_MSX)
                cnt_us <= 20'd0;
            else
                cnt_us <= cnt_us + 1'b1;
        DLY_1:
            if (cnt_us == 10)
                cnt_us <= 20'd0;
            else
                cnt_us <= cnt_us + 1'b1;
        REPLY:
            if (dht11_rise == 1'b1 && cnt_low > 80)
            begin
                cnt_low <= 20'd0;
                cnt_us <= 20'd0;
            end 
            else if (dht11 == 1'b0)
            begin
                cnt_low <= cnt_low + 1'b1;
                cnt_us <= cnt_us + 1'b1;
            end 
            else if (cnt_us > 1000)
            begin
                cnt_low <= 20'd0;
                cnt_us <= 20'd0;
            end 
            else
            begin
                cnt_low <= cnt_low;
                cnt_us <= cnt_us + 1'b1;
            end
        DLY_2:
            if (dht11_fall == 1'b1 && cnt_us > 80)
                cnt_us <= 20'd0;
            else 
                cnt_us <= cnt_us + 1'b1;
        RD_DATA:
            if (dht11_fall == 1'b1 || dht11_rise == 1'b1)
                cnt_us <= 20'd0;
            else 
                cnt_us <= cnt_us + 1'b1;
        default:
        begin
            cnt_low <= 20'd0;
            cnt_us <= 20'd0;
        end 
    endcase

6、模块完整代码

module dht11
(

  input wire  sys_clk ,

  input wire  key_flag,
  
  
  inout wire dht11,
  
  
  output reg [19:0] data_out ,
  output reg sign 
  
);


parameter WAIT_1S =	6'b000_001,
          START   =	6'b000_010,
		    DLY_1   =	6'b000_100,
		    REPLY   =	6'b001_000,
		    DLY_2   =	6'b010_000,
		    RD_DATA =	6'b100_000;

parameter WAIT1S_MAX = 20'd999_999 ;
parameter LOW_18MS_MSX = 20'd17_999 ;


wire dht11_rise ;
wire dht11_fall ;

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 ; 

reg [5:0] bit_cnt ;
reg [39:0] data_temp ;
reg [31:0] data ;
reg data_flag ;
reg dht11_en ;
reg dht11_out ;

always @(posedge sys_clk)
     if (cnt == 5'd24)
	  cnt <=5'd0;
	 else 
	  cnt <=cnt+ 1'b1;


always @(posedge sys_clk)
    if (cnt == 5'd24)
	 clk_us <= ~clk_us ;
	else 
	 clk_us <=clk_us;
	 

always @(posedge clk_us)
    case (state)
      WAIT_1S   :
	      if (cnt_us == WAIT1S_MAX)
		    state <= START;
		  else 
		    state <=WAIT_1S ;
      START     :
	    if (cnt_us == LOW_18MS_MSX)
		    state <= DLY_1;
		  else 
		    state <=START ;
      DLY_1     :
	    if (cnt_us ==20'd10)
		    state <= REPLY ;
		  else 
		    state <=DLY_1 ;
      REPLY     :

	      if (dht11_rise == 1'b1&&cnt_low> 80 )
		     state <= DLY_2;
		  else if (cnt_us >1000)
		    state <=START ;
		  else 
		    state <= REPLY;
      DLY_2     :

	      if (dht11_fall == 1'b1 &&cnt_us > 80 )
             state <= RD_DATA ;
		 else 
		     state <= DLY_2 ;
			 
	 RD_DATA   :
	 
	    if (bit_cnt == 40 && dht11_rise == 1'b1)
		    state <= START;
		else
		   state <= RD_DATA;
	 default : state <= WAIT_1S ;
    endcase 

//转换时钟
always @(posedge clk_us)
    case(state)
	   WAIT_1S  :
	      if (cnt_us==WAIT1S_MAX)
		   cnt_us <=20'd 0;
		  else
		   cnt_us <= cnt_us+1'b1 ;
	   START    :
	     if (cnt_us==LOW_18MS_MSX)
		   cnt_us <=20'd 0;
		  else
		   cnt_us <= cnt_us+1'b1 ;
	   DLY_1    :
	     if (cnt_us== 10)
		   cnt_us <=20'd 0;
		  else
		   cnt_us <= cnt_us+1'b1 ;
			
	   REPLY    :
	       if (dht11_rise == 1'b1&&cnt_low> 80 )
		  
		   begin 
		   cnt_low <= 20'd0 ;
		   cnt_us <= 20'd0 ;
		   end 
		   else if (dht11 == 1'b0)
		    begin 
			  cnt_low <= cnt_low +1'b1;
			  cnt_us <= cnt_us + 1'b1;
			end 
		   else if (cnt_us >1000)
		    begin
              cnt_low <= 20'd0;
              cnt_us <= 20'd0 ;
			end 
		   else 
		    begin 
			  cnt_low <= cnt_low ;
			  cnt_us <= cnt_us + 1'b1;
			end 
		    
	   DLY_2    :
	      if (dht11_fall == 1'b1 &&cnt_us > 80 )
		    cnt_us <= 20'd0 ;
		  else 
		    cnt_us <= cnt_us +1'b1 ;
			
	   RD_DATA  :
	      if (dht11_fall ==1'b1||dht11_rise==1'b1 )
		   cnt_us <= 20'd0 ;
		  else 
		   cnt_us<= cnt_us +1'b1 ;
		   
	   default  :
	        begin
              cnt_low <= 20'd0;
              cnt_us <= 20'd0 ;
			end 
	endcase
	

	
always @(posedge clk_us)
   begin 
    dht11_reg1 <= dht11  ;
	dht11_reg2 <= dht11_reg1 ;
   end 
   

assign dht11_rise = (~dht11_reg2)&&(dht11_reg1);

assign dht11_fall = (dht11_reg2)&&(~dht11_reg1);


always @ (posedge clk_us)
    if (bit_cnt==40 && dht11_rise == 1'b1 )
      bit_cnt <= 6'b0 ;
	else if (state ==RD_DATA && dht11_fall==1'b1)
	  bit_cnt <= bit_cnt +1'b1 ;
	else 
	  bit_cnt <= bit_cnt;
	  

always @ (posedge clk_us)
   if (state ==RD_DATA && dht11_fall==1'b1&& cnt_us <= 50 )
	  data_temp[39-bit_cnt] <= 1'b0 ;
   else if (state ==RD_DATA && dht11_fall==1'b1&& cnt_us >50 )
	  data_temp[39-bit_cnt] <= 1'b1 ;
   else
     data_temp <= data_temp ;


		
//数据校验部分data_temp[39:32]温度整数部分;data_temp[31:24]湿度小数部分;data_temp[23:16]温度整数部分;	
always @ (posedge clk_us)
     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 ;


always @ (posedge clk_us)
      if (state ==START)
	    dht11_en <= 1'b1;
      else
	    dht11_en <= 1'b0;

always @ (posedge clk_us)
      dht11_out <=1'b0 ;




always @ (posedge sys_clk)
      if (key_flag == 1'b1)
        data_flag <= ~ data_flag;
	  else
	    data_flag <= data_flag;
		

 always @ (posedge clk_us)

	  begin
	  
	  data_out[11:4] <= data[15:8];
	  data_out[3:0] <= data[3:0];
	  data_out[19:12] <= data[31:24] ;
	   end 	  

always@(posedge clk_us )
    
//     if(data_flag == 1'b0 ) //湿度小数位为0
//        data_out    <=  data[31:24] * 10;  //为了兼容温度显示的小数,将湿度的个
//		                               //位与十位扩大10倍,小数位为零
//    else    if(data_flag == 1'b1) //温度低四位显示温度小数数据
//        data_out    <=  data[15:8] * 10 + data[3:0];

	  
	  
	  
	 
	  
always @ (posedge clk_us)
		if (data_flag==1'b1 && data[7] == 1'b1)
		 sign <= 1'b1 ;
		else 
		 sign <= 1'b0 ;
		
		
assign dht11 = (dht11_en == 1) ? 1'b0 : 1'bz ;



endmodule

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值