基于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)begindata_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;elsedata_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;elsestate <= RD_DATA;default: state <= WAIT_1S;endcasealways @(posedge clk_us)case(state)WAIT_1S:if (cnt_us == WAIT1S_MAX)cnt_us <= 20'd0;elsecnt_us <= cnt_us + 1'b1;START:if (cnt_us == LOW_18MS_MSX)cnt_us <= 20'd0;elsecnt_us <= cnt_us + 1'b1;DLY_1:if (cnt_us == 10)cnt_us <= 20'd0;elsecnt_us <= cnt_us + 1'b1;REPLY:if (dht11_rise == 1'b1 && cnt_low > 80)begincnt_low <= 20'd0;cnt_us <= 20'd0;end else if (dht11 == 1'b0)begincnt_low <= cnt_low + 1'b1;cnt_us <= cnt_us + 1'b1;end else if (cnt_us > 1000)begincnt_low <= 20'd0;cnt_us <= 20'd0;end elsebegincnt_low <= cnt_low;cnt_us <= cnt_us + 1'b1;endDLY_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:begincnt_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;elsestate <= 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;elsecnt_us <= cnt_us+1'b1 ;START    :if (cnt_us==LOW_18MS_MSX)cnt_us <=20'd 0;elsecnt_us <= cnt_us+1'b1 ;DLY_1    :if (cnt_us== 10)cnt_us <=20'd 0;elsecnt_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)begincnt_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  :begincnt_low <= 20'd0;cnt_us <= 20'd0 ;end endcasealways @(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 ;elsedata_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;elsedht11_en <= 1'b0;always @ (posedge clk_us)dht11_out <=1'b0 ;always @ (posedge sys_clk)if (key_flag == 1'b1)data_flag <= ~ data_flag;elsedata_flag <= data_flag;always @ (posedge clk_us)begindata_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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/860079.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot+Vue集成富文本编辑器

1.引入 我们常常在各种网页软件中编写文档的时候&#xff0c;常常会有富文本编辑器&#xff0c;就比如csdn写博客的这个页面&#xff0c;包含了富文本编辑器&#xff0c;那么怎么实现呢&#xff1f;下面来详细的介绍&#xff01; 2.安装wangeditor插件 在Vue工程中&#xff0c;…

基于 SpringBoot + Vue 的图书购物商城项目

本项目是一个基于 SpringBoot 和 Vue 的图书购物商城系统。系统主要实现了用户注册、登录&#xff0c;图书浏览、查询、加购&#xff0c;购物车管理&#xff0c;订单结算&#xff0c;会员折扣&#xff0c;下单&#xff0c;个人订单管理&#xff0c;书籍及分类管理&#xff0c;用…

PCL 使用列文伯格-马夸尔特法计算变换矩阵

目录 一、算法原理1、计算过程2、主要函数3、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、计算过程 2、主要函数 void pcl

EXCEL快速填充空白内容

** EXCEL快速填充空白内容 ** 1.全选所有需要填充的内容&#xff0c;按住电脑的F5或者CTRLG点击定位 2.可以看到空白处被自动选定&#xff0c;之后按电脑和⬆&#xff0c;最后CTRLenter 可以看到空白处已经被填充。

计网入门还没到放弃

TCP报文段格式 源端口&#xff1a;标识报文的返回地址 目的端口&#xff1a;指明计算机上的应用程序接口 序号&#xff1a;通过SYN包传给接收端主机&#xff0c;每传送一次就1&#xff0c;用来解决网络包乱序的问题。 确认号&#xff1a;期望下一次收到的数据的序列号&#xff…

酷开科技用酷开系统打造数字化家庭娱乐与教育的新天地

家庭教育的重要性不言而喻&#xff0c;俗话说&#xff1a;父母是孩子的第一任老师&#xff0c;也是终生的老师。一个人是否能够成长成才&#xff0c;家庭教育是基础和前提&#xff0c;学校教育能够起到促进和引导作用&#xff0c;社会教育也会对一个人的成长产生重要影响。在数…

【YOLOv5/v7改进系列】引入PConv——轻量快速的卷积块

一、导言 《奔跑吧&#xff0c;别走&#xff1a;追求更高的FLOPS以实现更快的神经网络》&#xff0c;主要探讨了如何设计快速且高效的神经网络模型。文章指出&#xff0c;尽管许多研究致力于减少浮点运算次数(FLOPs)来提升模型速度&#xff0c;但FLOPs的减少并不直接等同于延迟…

Zookeeper部署

Zookeeper部署 下载安装包Linux解压安装包修改配置文件编辑zoo.cf配置 启动服务停止服务常用zookeeper指令查看namespace列表创建namespace删除namespace 注意&#xff1a;该文章为简单部署操作&#xff0c;没有复杂的配置内容&#xff0c;用的是3.7.2版本。 下载安装包 进入z…

python爬虫需要什么HTTP代理?

用来爬虫的话&#xff0c;还是建议用高匿名代理&#xff0c;但显然题主用了高匿名代理还是出现了一部分问题&#xff0c;我们可以先找到问题关键再解决它&#xff0c;一般爬虫用了高匿名代理出现被封会有以下几种原因&#xff1a; 1.代理IP的质量不过关 一般来说每个网站都有…

秋招突击——6/20——复习{(单调队列优化)——最大子序列和,背包问题——宠物小精灵收服问题}——新作{两两交换链表中的节点}

文章目录 引言复习单调队列优化——最大子序列和思路分析实现代码参考实现 背包问题——宠物小精灵的收服问题个人实现参考实现 新作两两交换链表中的节点个人实现参考实现 删除有序数组中的重复项个人实现知识补全迭代器的访问和控制vector删除特定的元素erasevector底层删除元…

PHP 数组排序详解与实例

在PHP编程中&#xff0c;数组是一种非常常见和重要的数据结构&#xff0c;而对数组进行排序则是处理和展示数据时必不可少的操作之一。本文将详细介绍PHP中数组排序的各种方法、函数和示例&#xff0c;帮助您掌握如何根据不同需求对数组进行排序。 1. PHP 中的数组排序函数 PH…

Consul入门笔记

简介 Consul&#xff0c;HashiCorp公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案&#xff0c;Consul的方案更一站式&#xff0c;内置服务注册与发现框架、分布一致性协议实现、健康检查、K/V存储、多数据中心方案&…

面试-java并发与多线程的部分函数

1.sleep和wait的区别 基本的差别&#xff1a; Sleep是Thread的方法。Wait是object方法。Wait不传参&#xff0c;最终也是调用wait(native)的传参方法。 Sleep方法可以在任何地方使用。 Wait方法只能在synchronized方法或synchronized方法块中使用。 最主要的本质区别&#xf…

【NOI】C++程序结构入门之嵌套循环一

文章目录 前言一、嵌套循环1.概念2.语法2.1 for循环嵌套for2.2 while循环嵌套for2.3 while循环嵌套while2.4for循环嵌套while2.5 注意2.5.1内层循环之前2.5.2内层循环之后 3.按位检查 二、例题讲解问题&#xff1a;1448. 随机体能测试问题&#xff1a;1469. 数的统计问题&#…

vue中图谱关系插件relation-graph

vue中图谱关系插件relation-graph 一、效果图二、安装下载&#xff08;vue2.0版本的&#xff09;三、直接上代码 一、效果图 二、安装下载&#xff08;vue2.0版本的&#xff09; npm install --save relation-graph var foo bar;三、直接上代码 <template><div cla…

【从0实现React18】 (五) 初探react mount流程 完成核心递归流程

更新流程的目的&#xff1a; 生成wip fiberNode树标记副作用flags 更新流程的步骤&#xff1a; 递&#xff1a;beginWork归&#xff1a;completeWork 在 上一节 &#xff0c;我们探讨了 React 应用在首次渲染或后续更新时的整体更新流程。在 Reconciler 工作流程中&#xff…

LLC开关电源开发:LLC设计参考文档(模态分析)

电源简析和全桥LLC模型分析 1.1模拟电源、开关电源和数字电源简介 1.1.1 模拟电源 模拟电源&#xff1a;即变压器电源&#xff0c;通过铁芯、线圈来实现&#xff0c;线圈的匝数决定了两端的电压比&#xff0c;铁芯的作用是传递变化磁场&#xff0c;&#xff08;我国&#xff09…

摒弃反模式:使用Kotlin委托优化Android BaseActivity

摒弃反模式&#xff1a;使用Kotlin委托优化Android BaseActivity 在Android开发中&#xff0c;许多开发者习惯于创建名为“BaseActivity”或“BaseFragment”的基类&#xff0c;以便在所有Activity或Fragment中共享一些通用行为。这种方法乍一看似乎是个好主意&#xff0c;但实…

零基础女生如何入门人工智能,从哪里下手?学习时间大概要多久?

作为一个理工科早期毕业生&#xff0c;出于近乎本能的敏感&#xff0c;格外关注全网热议的ChatGPT。 本来国内就业环境就不好&#xff0c;各行各业内卷越来越严重&#xff0c;加上人工智能的异军突起&#xff0c;各行各业势必将迎来科技进步跨时代的巨大冲击&#xff0c;在此情…

000005 - HDFS 读写流程

HDFS 读写流程 1 HDFS 写数据流程1.1 HDFS 写数据流程图1.2 HDFS 写数据之网络拓扑 - 节点距离计算1.3 机架感知&#xff08;副本存储节点选择&#xff09; 2 HDFS 读数据流程2.1 HDFS 读数据流程图 3 HDFS 如何做到机架感知 1 HDFS 写数据流程 1.1 HDFS 写数据流程图 &#x…