完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html 第二十六章 DHT11数字温湿度传感器实验 DHT11是奥松(AoSong)公司生产的一款数字温湿度复合传感器。该传感器用途广泛、抗 干扰能力强、可靠性高,在家电、汽车、医疗等方面有广泛的应用。本章我们将使用FPGA开发 板实现对DHT11数据的采集,并将温湿度数据显示在数码管上。 本章包括以下几个部分: 26.1 DHT11简介 26.2 实验任务 26.3 硬件设计 26.4 程序设计 26.5 下载验证 DHT11简介 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它使用专 用的数字模块采集技术和温湿度传感技术,具有极高的可靠性与卓越的长期稳定性。传感器包 括一个电阻式感湿元件和一个NTC(负温度系数热敏电阻器)测温元件,并与一个高性能8位MCU 相连接。每个DHT11传感器都在湿度校验室中校准过,校准系数以程序的形式储存在OTP(一次 性可编程)内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。DHT11使用单 线制串行接口,4针单排引脚封装,信号传输距离可达20米以上,在各类应用甚至很苛刻的环 境中都能正常工作。 图 26.1.1 DHT11内部原理图 上图为DHT11的内部原理图,可以看出感湿原件、感温元件和OTP内存直接连接在内部一个 八位MCU上,该MCU通过计算得出测量数值。 DATA用于FPGA与DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右, 数据分为整数部分和小数部分,数据格式如下: 一次完整的数据传输为40bit,高位在前。 数据格式:8bit湿度整数数据+8bit湿度小数数据 +8bit温度整数数据+8bit温度小数数据 +8bit校验和数据 数据传送正确时校验和数据等于“8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度 整数数据 + 8bit温度小数数据”所得结果的末8位)。 接下来我们介绍一下DHT11的传输时序,DHT11的数据发送流程如图 26.1.2错误!未找到 引用源。所示。 图 26.1.2 DHT11数据发送流程 主机(此处指FPGA)首先发送一次开始信号,即:拉低数据线,保持t1(至少18ms)时间; 然后拉高数据线保持t2(20~40us)时间,随后开始读取DHT11的响应;如果操作正确的话,DHT11 会拉低数据线,保持t3(80us)时间,作为响应信号;接下来DHT11会拉高数据线,保持t4(80us) 时间,随后开始输出有效数据。 DHT11共输出40bit有效数据,每1bit数据都是以50us低电平开始,高电平的持续时间作为 判断数据位的条件。当数据位为0时,高电平的持续时间为26~28us;当数据位为1时,高电平 的持续时间为70us。 DHT11数据位“0”时序图和数据位“1”时序图如图 26.1.3和图 26.1.4所示。 图 26.1.3 DHT11数据位“0”时序图 图 26.1.4 DHT11数据位“1”时序图 需要注意的是,DHT11的温度和湿度转换较慢,如果读取速度过快会导致DHT11无法响应的 情况。本次实验每100ms读取一次,如果DHT11长时间未响应,则重新发起开始信号。 实验任务 本节实验任务是使用开拓者FPGA开发板完成对DHT11温湿度数据的采集,并通过按键KEY0 控制温度和湿度在数码管上的切换显示。 硬件设计 我们的开拓者开发板上有一个DS18B20/DTH11的扩展接口,该接口可以用来连接DS18B20或 DHT11。其原理图如图 26.3.1所示。 图 26.3.1 DHT11/DS18B20扩展接口原理图 DHT11通过4个排针与外部连接,如图 26.3.2所示,将DHT11直接插在开发板上即可,接插 之前注意正负极的方向,以免短路。 图 26.3.2 DHT11连接实物图 本次实验的管脚分配如下表所示: 表 26.3.1 管脚分配 程序设计 根据实验任务,我们可以大致规划出系统的工作流程:FPGA控制DHT11采集温度和湿度, 并将收到的温度和湿度数据转换成十进制显示在数码管上。本次实验使用按键来控制数码管显 示温度和湿度,所以还需要添加消抖模块来对按键进行消抖,以及按键控制模块控制数码管切 换显示温度和湿度。由此画出的系统框图如下图所示。 图 26.4.1 DHT11数字温湿度传感器系统框图 各模块端口及信号连接如图 26.4.2所示: 图 26.4.2 顶层模块原理图 FPGA部分包括5个模块,顶层模块(top_dht11)、DHT11驱动模块(dht11_drive)、按键 消抖模块(key_debounce)、按键控制模块(dht11_key)、数码管驱动模块(seg_led)。其 中在顶层模块完成对其他模块的例化。 DHT11驱动模块(dht11_drive):dht11_drive模块通过单总线引脚读取DHT11的温度值和湿度值,并将读取到的数据输出至按键控制模块。 按键消抖模块(key_debounce):消除按键抖动,在检测到有按键按下或释放时对按键数 据进行消抖处理。 按键控制模块(dht11_key):根据输入的按键控制信号,将温度数据和湿度数据选择输 出至数码管显示模块。 数码管显示模块(seg_led):将输入的数据显示到数码管上。 顶层模块代码如下: 1 module top_dht11( 2 input sys_clk , //系统时钟 3 input sys_rst_n , //系统复位 4 5 input key , //按键 6 inout dht11 , //dht11总线 7 output [5:0] sel , //数码管位选信号 8 output [7:0] seg_led //数码管段选信号 9 ); 10 //wire define 11 wire [31:0] data_valid; 12 wire [19:0] data ; 13 wire [5:0] point ; 14 15 //***************************************************** 16 //** main code 17 //***************************************************** 18 19 //dht11驱动模块 20 dht11_drive u_dht11_drive ( 21 .sys_clk (sys_clk) , 22 .rst_n (sys_rst_n), 23 .dht11 (dht11) , 24 .data_valid (data_valid) 25 ); 26 27 //数码管模块 28 seg_led u_seg_led ( 29 .clk (sys_clk), 30 .rst_n (sys_rst_n), 31 .sel (sel), 32 .seg_led (seg_led), 33 .data (data), 34 .point (point), 35 .en (en), 36 .sign (sign) 37 ); 38 39 //消抖模块 40 key_debounce u_key_debounce( 41 .sys_clk (sys_clk), 42 .sys_rst_n (sys_rst_n), 43 .key (key), 44 .key_flag (key_flag), 45 .key_value (key_value) 46 ); 47 48 //按键控制 49 dht11_key u_dht11_key( 50 .sys_clk (sys_clk), //系统时钟 51 .sys_rst_n (sys_rst_n), //系统复位 52 .key_flag (key_flag), //按键有效 53 .key_value (key_value), 54 .data_valid (data_valid), 55 .data (data), 56 .sign (sign), 57 .en (en), 58 .point (point) 59 ); 60 61 endmodule 顶层模块完成对其他模块的例化,dht11_drivr模块输出的数据信号(data_valid)和 key_debounce模块输出的按键信号(key_flag和key_value)连接至dht11_key模块,dht11_key 模块输出的温度/湿度数据(data)以及数码管控制信号连接至seg_led模块。 由本章简介部分介绍的DHT11传输时序可以发现,DHT11的传输时序适合用状态机来编写。 DHT11驱动模块状态跳转图如下所示。 图 26.4.3 DHT11驱动状态跳转图 DHT11驱动模块使用三段式状态机来读取DHT11的温度和湿度值,从上图可以比较直观的看 到每个状态实现的功能以及跳转都下一个状态的条件。这里需要注意的一点是,由于DHT11温 度和湿度转换较慢,如果读取速度过快会导致DHT11无法响应的情况,所以我们在每次读操作 结束后延时两秒。 由于DHT11驱动模块的代码较长,我们仅贴出部分源代码。 131 case (cur_state) 132 //上电后延时1秒等待DHT11稳定 133 st_power_on_wait : begin 134 if(us_cnt < POWER_ON_NUM) begin 135 dht11_buffer <= 1'bz; //空闲状态释放总线 136 us_cnt_clr <= 1'b0; 137 end 138 else begin 139 next_state <= st_low_20ms; 140 us_cnt_clr <= 1'b1; 141 end 142 end 143 //FPGA发送起始信号(20ms的低电平) 144 st_low_20ms: begin 145 if(us_cnt < 20000) begin 146 dht11_buffer <= 1'b0; //起始信号为低电平 147 us_cnt_clr <= 1'b0; 148 end 149 else begin 150 dht11_buffer <= 1'bz; //起始信号结束后释放总线 151 next_state <= st_high_13us; 152 us_cnt_clr <= 1'b1; 153 end 154 end 155 //等待DHT11的响应信号(等待10~20us) 156 st_high_13us:begin 157 if (us_cnt < 20) begin 158 us_cnt_clr <= 1'b0; 159 if(dht11_neg) begin //检测到DHT11响应信号 160 next_state <= st_rec_low_83us; 161 us_cnt_clr <= 1'b1; 162 end 163 end 164 else //超过20us未响应 165 next_state <= st_delay; 166 end 167 //等待DHT11的83us低电平响应信号结束 168 st_rec_low_83us: begin 169 if(dht11_pos) 170 next_state <= st_rec_high_87us; 171 end 172 //DHT11拉高87us通知FPGA准备接收数据 173 st_rec_high_87us: begin 174 if(dht11_neg) begin //准备时间结束 175 next_state <= st_rec_data; 176 us_cnt_clr <= 1'b1; 177 end 178 else begin //高电平准备接收数据 179 data_cnt <= 6'd0; 180 data_temp <= 40'd0; 181 step <= 1'b0; 182 end 183 end 184 //连续接收40位数据 185 st_rec_data: begin 186 case(step) 187 0: begin //接收数据低电平 188 if(dht11_pos) begin 189 step <= 1'b1; 190 us_cnt_clr <= 1'b1; 191 end 192 else //等待数据低电平结束 193 us_cnt_clr <= 1'b0; 194 end 195 1: begin //接收数据高电平 196 if(dht11_neg) begin 197 data_cnt <= data_cnt + 1'b1; 198 //判断接收数据为0/1 199 if(us_cnt < 60) 200 data_temp <= {data_temp[38:0],1'b0}; 201 else 202 data_temp <= {data_temp[38:0],1'b1}; 203 step <= 1'b0; 204 us_cnt_clr <= 1'b1; 205 end 206 else //等待数据高电平结束 207 us_cnt_clr <= 1'b0; 208 end 209 endcase 210 211 if(data_cnt == 40) begin //数据传输结束,验证校验位 212 next_state <= st_delay; 213 if(data_temp[7:0] == data_temp[39:32] + data_temp[31:24] 214 + data_temp[23:16] + data_temp[15:8]) 215 data_valid <= data_temp[39:8]; 216 end 217 end 218 //完成一次数据采集后延时2s 219 st_delay:begin 220 if(us_cnt < 2000_000) 221 us_cnt_clr <= 1'b0; 222 else begin //延时结束后重新发送起始信号 223 next_state <= st_low_20ms; 224 us_cnt_clr <= 1'b1; 225 end 226 end 227 default : ; 228 endcase 从代码的第165行可知,在st_high_13us状态下,当DHT11长时间未响应时(超时20us),则进入延时状态(st_delay),延时两秒后重新发起开始信号。 图 26.4.4为SignalTap抓取的波形图,从图中可以清晰的看到DHT11驱动模块各个状态跳 转的时序图。st_rec_data为解析数据的状态,数据解析完成之后,开始进入st_delay(延时) 状态,延时状态结束之后,准备重新发起开始信号。 图 26.4.4 SignalTap抓取的波形图 按键控制模块的代码如下所示: 1 module dht11_key( 2 input sys_clk , //系统时钟 3 input sys_rst_n , //系统复位 4 5 input key_flag , //按键有效 6 input key_value , 7 input [31:0] data_valid , 8 output [31:0] data , 9 output reg sign , 10 output reg en , 11 output reg [5:0] point 12 ); 13 14 //reg define 15 reg flag ; 16 reg [7:0] data0; 17 reg [7:0] data1; 18 19 //***************************************************** 20 //** main code 21 //***************************************************** 22 23 //采集按键上升沿 24 assign key_pos = (~key_value) & key_flag; 25 //由于要显示的数值由整数部分和小数部分组成,所以需要合并起来 26 assign data = data1 * 100 + data0*10; 27 28 //确定显示的数据是温度值还是湿度值,flag为“0”时显示温度,为“1”时显示湿度 29 always @ (posedge sys_clk or negedge sys_rst_n) begin 30 if(!sys_rst_n) 31 flag <= 1'b0; 32 else if (key_pos) 33 flag <= flag + 1'b1; 34 end 35 36 always @ (posedge sys_clk or negedge sys_rst_n) begin 37 if(!sys_rst_n) begin 38 data0 <= 8'b0; 39 data1 <= 8'b0; 40 end 41 else if (flag == 1'b0) begin 42 data1 <= data_valid[15:8]; 43 data0 <= data_valid[7:0]; 44 end 45 else begin 46 data1 <= data_valid[31:24]; 47 data0 <= data_valid[23:16]; 48 end 49 end 50 51 //确定小数点显示的位置,这里在百位显示小数点 52 always @ (posedge sys_clk or negedge sys_rst_n) begin 53 if(!sys_rst_n) begin 54 point <= 6'b111111; 55 en <= 1'b0; 56 sign <= 1'b0; 57 end 58 else begin 59 point <= 6'b000100; 60 en <= 1'b1; 61 sign <= 1'b0; 62 end 63 end 64 65 endmodule 在代码的第29行开始的always中,每按下一次按键KEY0,flag的值会改变一次,当flag的 值等于0时,输出的值为温度值;当flag的值等于1时,输出的值为湿度值。在代码的第26行中, 我们将温湿度值的整数部分放大100倍,小数部分放大10倍,显示在数码管上。 按键消抖模块和数码管显示模块分别在“按键控制蜂鸣器试验”和“动态数码管显示试验” 中作出了详细介绍,在此不再赘述。 下载验证 首先我们打开DHT11数字温湿度传感器实验工程,在工程所在的路径下打开top_dht11/par 文件夹,在里面找到“top_dht11.qpf”并双击打开。注意工程所在的路径名只能由字母、数 字以及下划线组成,不能出现中文、空格以及特殊字符等。工程打开后如图 26.5.1所示。 图 26.5.1 DHT11工程打开界面 将DHT11接插到开拓者开发板上的单总线接口,如下图所示。然后将下载器一端连电脑, 另一端与开发板上对应端口连接,最后连接电源线并打开电源开关。 图 26.5.2 DHT11接插至开拓者开发板 工程打开后通过点击工具栏中的“Programmer”图标(图中红框位置)打开下载界面,通过 “Add File”按钮选择DHT11数字温湿度传感器工程中top_dht11/par/output_files目录下 “top_dht11.sof”文件,下载界面如图 26.5.3所示(图中已下载完毕)。 图 26.5.3 下载界面 接下来我们点击左侧的Start,下载程序,验证温湿度传感器数码管显示功能。 下载完成后,数码管默认显示的是温度值,当按下KEY0按键后,数码管会显示湿度值,说 明本次DHT11数字温湿度传感器实验验证成功。这里需要注意的是温度值的单位是:℃(摄氏 度);湿度值的单位是:%RH(相对湿度),温度值和湿度值的单位在数码管上没有显示。 图 26.5.4 开发板KEY0按键 |
|
相关推荐
|
|
如何配置Linux操作系统设备树让我的开发板可以将板子上的GPIO接口用作 I2S输出??
1675 浏览 1 评论
1450 浏览 0 评论
2078 浏览 0 评论
2019 浏览 2 评论
1118 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-20 02:48 , Processed in 0.476208 second(s), Total 33, Slave 26 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号