本篇主要讨论基于 FPGA 的温度传感器(ds18b20)驱动设计---第一版
设计实现:利用 FPGA 驱动 DS18b20,读取到温度数值显示到数码管上。
首先介绍 DS18b20。
DS18B20 是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
DS18B20 数字温度计提供 9-12 位摄氏温度测量(9-12 位是测量精度),它的测温范围为-55 ~+ 125℃。
可编程的分辨率为 9-12 位,对应的分辨率温度分别为 0.5 度、0.25 度、0.125 度、0.0625 度。
测量温度是需要转换时间的(将外界的问题转换为数字量),9bit 的精度需要最大 93.75ms;10bit 的精度需要最大 187.5ms;11bit 的精度需要最大 375ms;12bit 的精度需要最大 750ms。
上电后,默认的精度为 12 位,我们一般也采用这个精度。如果觉得这个转换时间较长,可以考虑配置为其他的精度。
每个 DS18B20 都有一个独特的 64 位序列号,从而允许多只 DS18B20 同时连在一根单线总线上;因此很简单就可以用一个微控制器去控制很多覆盖在一大片区域的 DS18B20。这一特性在 HVAC 环境控制、探测建筑物、仪器或机器的温度以及过程监测和控制等方面非常有用。
通过上述实物图可以看到,DS18B20 有三个管脚,VDD(电源管脚),DQ(数据线),GND(地线)。
在使用时,也可以不通过 VDD 供电,而采用 DQ 供电(此种模式在此不再介绍)。
在平常使用时,VDD 接电源 3V~5V,GND 接地,DQ 上面需要接一个上拉电阻(阻值通常为 4.7K,或者 10K),DQ 就是进行通信的数据线(单数据总线)。
了解了使用的电路特性后,就得琢磨一下,如何利用一个数据线 DQ 来进行控制这个温度传感器。
下图是 DS18B20 的框图:
64bit 的 rom 中的数值时固定的。高八位为:28h(表示为 DS18b20);后续的 48 位为:芯片的序列号(每一个 DS18B20 都不相同);最后八位:前面 56 位的 CRC 校验序列。
DS18B20 支持在一个总线上面加载多个 DS18B20,那么此时就需要获取每一个 DS18B20 的 ROM,这样就可以精准的控制每一个器件了。
在此我们不对在一个总线上加载多个 DS18B20 的情况,只讨论加载一个 DS18B20 的情况。
读取 ROM 的 64bit 的命令为 33H,后面跟着读取 64bit,就是器件的 ROM 值(只能用在总线上只有一个器件的情况)。
匹配 ROM 的命令为 55H,后面跟着写入 64bit 数据,只有和这 64bit 的数据相同的器件才会开始工作。
跳过 ROM 的命令为 CCH,接收到这个命令的器件,不需要匹配就可以直接工作(只能用在总线上只有一个器件的情况)。
在此我们不做多器件的情况,所以可以直接发送跳过 ROM 的命令。
DS18B20 的测温是需要被通知的,也就说我们需要给器件发送一个开始测温的命令,他才会开始测量温度,并且转换称为数字信号(16bit 的有符号数)。
分频率为 12 位,使用 16bit 后面的 12 位(11:0)。
分频率为 11 位,则 16bit 的最后一个 bit 不使用(11:1)。
······
上图为默认精度(12bit、0.0625 度),如果第 12 位为 0,表示为正温度,测量出来的数据乘以 0.0625 就可以了。如果第 12 为 1,表示为负温度,则需要将测量出来的数据减去 1,然后所有位取反,得到的结果再乘以 0.0625 度。上述的表示方式就是有符号数在数字电路中的表示形式。
16bit 的数字信息存储在内部暂存器中,占用两个字节(在 0、1 字节)。
测温的命令为 44H。
暂存器的第四个 4 字节就是配置分辨率的寄存器。
TM 设置为 0 即可;
可以通过配置这个寄存器的值,来配置我们想要的分辨率。在此,我将不配置此寄存器,使用默认分辨率 12bit。
写入暂存器的命令为 4EH,后面跟着写入 3 个字节的数据,这三个字节写入到暂存器的 2、3、4 的位置。
读出暂存器的命令为 BEH,后面跟着读出 N 个字节的数据,如果只是想读取温度,那么只需要读出两个字节的数据就可以了。
基本的命令差不多都介绍完事了,那么下面开始介绍时序。
首先:在发送命令之前,器件要求必须要被初始化。时序如下:
控制器需要拉低 DQ,至少保持 480us(最大不超过 960us,建议:600us),然后释放总线控制(由于 DQ 被上拉,所以会被拉成高电平)。如果器件存在并且可以正常工作,器件会拉低 DQ 一段时间 60-240us。
所以建议:控制器拉低 DQ960us,释放总线控制,检测 DQ 是否还会拉低。主机从释放总线控制开始,要等待 600us 的时间去检测 DQ 是否拉低,如果有拉低则证明器件存在并且可以工作,如果没有拉低,则证明器件不存在或者不可以工作。
证明器件存在并且可以工作后,我们就可以向器件发送命令了。
发送命令和和数据以低位优先。
发送 1bit 的时序为:
如果控制器想要发送 1bit0,那么直接拉低 DQ100us 即可,然后释放总线;如果控制器想要发送 1bit1,那么拉低 DQ5us,然后释放总线即可。无论是写 0,还是写 1,建议每一 bit 的时长 110us。
读取命令和数据以低位优先。
读取 1bit 的时序为:
如果控制器想要读取的话,那么拉低 DQ5us 的时间,释放总线,在 10us 时,读取总线的电平值即可获得读取值。建议每一 bit 的时长 110us。
实现 DS18B20 的驱动主要有三步:
第一步:初始化 DS18B20;
第二步:ROM 命令(紧跟任何数据交换请求);
第三步:DS18B20 功能命令(紧跟任何数据交换请求);
所以我们上电后,工作的过程如下:
初始化、发送跳过 ROM 命令 、发送转换温度命令;等待 750ms;初始化、发送跳过 ROM 命令、发送读取暂存器的命令、读取两个字节的数据。不断重复以上的过程即可。
上面的工作方式模式为:总线上是一个器件、分辨率为默认的 12bit、没有匹配 ROM。
DS18B20 一般会制作到一个板卡上面,下面是笔者自制的板卡;
如果有需要的小伙伴,可以点击下面的链接:
https://item.taobao.com/item.htm?ft=t&id=862024382902
设计实现:利用 FPGA 驱动 DS18b20,读取到温度数值显示到数码管上。
1. 温度传感器为 DS18B20。
2. 总线上只有一个器件、温度分辨率为 12bit(默认)、跳过 ROM 指令。
3. 将温度显示到数码管上。
4. 温度精确到小数点后 2 位。
5. 数码管共计 6 个,最前面显示是否为负温度(不显示为正温度,显示一横杠为负温度)。
6. 数码管共计 6 个,后面五个显示温度,前面三个显示整数、后面两个显示小数。
7. 数码管共计 6 个,整数与小数中间点亮小数点。
8. 利用 LED 显示是否初始化成功,LED 点亮表示初始化成功,LED 熄灭表示初始化失败。
使用平台:本次设计应用 Altera 的平台设计(芯片:EP4CE10F17C8)、使用的 DS18B20 板卡为市面上常见的,如果没有的同学,可以联系笔者购买。
开发软件:quartus 18.0
开发语言:Verilog HDL
作者 QQ:746833924
说明:本篇设计中不涉及到 ip 电路,如果在其他平台,rtl 代码依然可以适用,当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;
设计思想如下:
ds18b20_drive 模块的功能为驱动 ds18b20,获取温度,并且输出符号和温度的 BCD 码;seven_tube_drive 模块的功能将符号和温度的 BCD 码输出,并且在右侧第三个数码管点亮小数点用以区分整数和小数。
ds18b20_drive 模块采用状态机的方式实现。
读取到温度信息后,转换为 BCD 码输出;
首先判断温度的正负性,然后计算它的绝对值。
绝对值要乘以 0.0625,此时乘以 625,相当于扩大了 10000 倍,然后除以 100,则表示扩大了 100 倍(因为我们需要保留两位小数 ,正好扩大 100 倍使小数都变成了整数)。
if (data_r[12] == 1'b1) begin
temp_sign <= 4'he;
data_1 = (~(data_r - 1'b1)) * 16'd625 /7'd100;
end
else begin
temp_sign <= 4'hf;
data_1 <= (data_r * 16'd625) /7'd100;
end
数码管驱动采用最基本动态驱动即可,在此不做介绍;
相关参考代码为:
通过网盘分享的文件:温度传感器DS18b20驱动--第一版
链接: https://pan.baidu.com/s/1es-KpmP4PqZbaR76kTDlYA?pwd=vins
提取码: vins
END
来源:FPGA技术江湖
相关文章推荐
更多 FPGA 干货请关注 FPGA 的逻辑技术专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。