基于FPGA驱动DS18B20
文章目录
一、 目的
通过ds18b20实现基本的温度采集
二、 原理
1. 理论原理
1.rs232串口
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。UART是一种通用的数据通信协议,也是异步串行通信口(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。它包括了RS 232、RS499、RS423、RS422和RS485等接口标准规范和总线标准规范。
串口作为常用的三大低速总线(UART、SPI、IIC)之一,在设计众多通信接口和调试时占有重要地位。但UART和SPI、IIC不同的是,它是异步通信接口,异步通信中的接收方并不知道数据什么时候会到达,所以双方收发端都要有各自的时钟,在数据传输过程中是不需要时钟的,发送方发送的时间间隔可以不均匀,接受方是在数据的起始位和停止位的帮助下实现信息同步的。而SPI、IIC是同步通信接口,同步通信中双方使用频率一致的时钟,在数据传输过程中时钟伴随着数据一起传输,发送方和接收方使用的时钟都是由主机提供的。
UART通信只有两根信号线,一根是发送数据端口线叫tx(Transmitter),一根是接收数据端口线叫rx(Receiver),对于PC来说它的tx要和对于通讯设备来说的rx连接,同样PC的rx要和通讯设备的tx连接,如果是两个tx或者两个rx连接那数据就不能正常被发送出去和接收到,所以不要弄混,记住rx和tx都是相对自身主体来讲的。UART可以实现全双工,即可以同时进行发送数据和接收数据。
RS232是UART的一种,没有时钟线,只有两根数据线,分别是rx和tx,这两根线都是1bit位宽的。其中rx是接收数据的线,tx是发送数据的线。
rx位宽为1bit,PC机通过串口调试助手往FPGA发8bit数据时,FPGA通过串口线rx一位一位地接收,从最低位到最高位依次接收,最后在FPGA里面位拼接成8比特数据。
tx位宽为1bit,FPGA通过串口往PC机发8bit数据时,FPGA把8bit数据通过tx线一位一位的传给PC机,从最低位到最高位依次发送,最后上位机通过串口助手按照RS232协议把这一位一位的数据位拼接成8bit数据。
串口数据的发送与接收是基于帧结构的,即一帧一帧的发送与接收数据。每一帧除了中间包含8bit有效数据外,还在每一帧的开头都必须有一个起始位,且固定为0;在每一帧的结束时也必须有一个停止位,且固定为1,即最基本的帧结构(不包括校验等)有10bit。在不发送或者不接收数据的情况下,rx和tx处于空闲状 态,此时rx和tx线都保持高电平,如果有数据帧传输时,首先会有一个起始位,然后是8bit的数据位,接着有1bit的停止位,然后rx和tx继续进入空闲状态,然后等待下一次的数据传输。
2. ds18b20
DS18B20使用的是1-Wire总线协议,该总线协议仅需一个控制信号进行通信。在该总线系统中,微控制器(主设备)通过设备的64位序列号来识别该总线上的设备,因为每个设备的序列号都是不同的。DS18B20可以无需外部电源供电,当数据线DQ为高时由数据线为设备供电。当总线拉高时给内部电容(Cpp)充电 ,当总线拉低时由该电容给设备供电。这种由总线给设备供电的方式称为“寄生电源”。此外,DS18B20也可以由外部电源通过VDD供电。
DS18B20的核心功能是直接温度—数字测量。其温度转换可由用户自定义为9、10、11、12位,精度分别为0.5℃、0.25℃、0.125℃、0.0625℃分辨率,若不设置则默认为12位的转换精度。若要测量温度,主设备必须向DS18B20发送温度转换命令[44h]才能开始温度转换。温度转换后,转换的 温度值将会保存在高速缓存器的温度寄存器中。只有通过读高速缓存器命令[BEh]才能将数据读出,数据通过1-Wire总线传输,传输顺序为低位到高位依次传输。温度数据中包含“符号”(S)位,表示温度的正负。
DS18B20的温度输出数据是在摄氏度下校准的;若是在华氏度下应用的话,可以用查表法或者常规的数据换算。温度以一个16位标志扩展二进制补码的形式存储在温度寄存器中。符号标志位(S)温度的正负极性:若S=0,则为正数;若S=1,则为负数。如果DS18B20被定义为12位的转换精度,温度寄存器中所有位都将包含有效数据。若定义为11位转换精度,则bit 0(最低位)为未定义的。若定义为10位转换精度,则bit 0和bit 1为未定义的。若定义9位转换精度,则bit 0、bit 1和bit 2为未定义的。
高速缓存器中第四个字节即为配置寄存器;用户通过改变R1和R0的值来配置DS18B20的分辨率。上电默认为R1=1以及R0=1(12位分辨率)。需要注意的是转换时间与分辨率时间是有关系的。另外寄存器中最高位和低5位作为内部使用而保留使用,不可被写入。
R1 | R0 | 转换位数 | 最大转换时间 |
---|---|---|---|
0 | 0 | 9 | 93.75ms (tconv/8) |
0 | 1 | 10 | 187.5ms (tconv/4) |
1 | 0 | 11 | 375ms (tconv/2) |
1 | 1 | 12 | 750ms (tconv) |
ds18b20初始化
1-Wire总线上的所有事件都必须以初始化为开始。初始化序列由总线上的主设备发出的复位脉冲以及紧跟着从设备回应的存在脉冲构成。该存在脉冲是让总线主设备知道DS18B20在总线上并准备好运行。具体的初始化时序后面再详细介绍。
ROM命令
当初始化完成之后,就可以执行ROM命令。这些命令是对每个设备的64位ROM编码进行操作的,当总线上连接有多个设备时,可以通过这些命令识别各个设备。总共包含有5种ROM命令,每个命令的长度都是8bit。
- 搜索ROM[F0h]
当系统上电初始化后,主设备可识别该总线上所有的从设备的ROM编码,这样就可以使得主设备确定总线上的从设备的类型以及数量。
- 读ROM[33h]
该命令允许主设备读取DS18B20的64位ROM编码,只有在总线上只有一个DS18B20时才能使用这个命令。如果总线上存在多个从设备,发送此命令,则当所有从设备都会回应时,将会引起数据冲突。
- 匹配ROM[55h]
该匹配ROM命令之后接着发出64位ROM编码,使主设备在多点总线上定位一只特定的DS18B20。只有和64位ROM序列完全匹配的DS18B20才会做出响应。总线上的其他从设备都将等待下一个复位脉冲。此命令在总线上有单个或多个器件时都可以使用。
- 跳过ROM[CCh]
这条命令可以不用提供64位ROM编码就进行下一步操作,在单点总线(一个DS18B20传感器)情况下可以节省时间。如果总线上不止一个从设备,在跳过ROM命令之后跟着发一条读命令,则所有从设备将会同时执行温度转换,总线上就会发生数据冲突。
- 警报搜索[ECh]
该命令的操作与跳过ROM命令基本相同,但是不同的是只有温度高于TH或低于TL(达到报警条件)的从设备才会响应。只要不掉电,警报状态将一直保持,直到温度不在警报范围内为止。
功能命令
当总线上的主设备通过ROM命令确定了哪个DS18B20可以进行通信时,主设备就可以向其中一个从设备发送功能命令。这些命令可以使得主设备操控从设备进行一系列的操作。下面对这些功能命令做个简单的描述。
- 温度转换[44h]
此命令为初始化单次温度转换,温度转换完后,转换的温度数据会寄存在高速缓存器的byte0(温度数据低八位)和byte1(温度数据高八位)中,之后DS18B20恢复到低功耗的闲置状态。如果总线在该命令后发出读时隙,若DS18B20正在进行温度转换则会响应“0”,若完成了温度转换则响应“1”。如果是用的“ 寄生电源”供电模式,则在命令发出后应立即强制拉高总线,拉高时间应大于表格 28‑2中的温度转换时间。
- 写入暂存器[4Eh]
该命令使得主设备向高速缓存器写入3个字节的数据。第一个字节写入高速缓存器的byte2中(TH寄存器),第二个字节的数据写入byte3中(TL寄存器),第三个字节的数据写入byte4中(配置寄存器)。所有的数据都是由低位到高位的顺序写入。复位可随时中断写入。
- 读取高速缓存器[BEh]
该命名是读取高速缓存器里的值,从byte0(温度低八位)开始一直读到byte8(CRC校验),每个字节的数据从低位开始传送。若是不想读取这么多数据则在读取数据时随时可以通过复位来终止。
- 复制高速缓存器[48h]
该命令是将高速缓存器中的TH(byte2)、TL(byte3)以及配置寄存器(byte4)里的值拷贝到非易失性的存储器EEPROM里。如果总线控制器在这条命令之后跟着发出读时隙,而DS18B20又正在忙于把暂存器拷贝到EEPROM存储器,DS18B20就会输出一个“0”,如果拷贝结束的话,DS18B 20则输出“1”。如果设备采用“寄生电源”供电模式,则在该命令发送后,必须立即强制拉高总线至少10ms。
- 召回EEPROM[B8h]
该命令将温度报警触发值(TH和TL)及配置寄存器的数据从EEPROM中召回至高速缓存器中。这个操作会在上电后自动执行一次,所以在上电期间暂存器中一直会存在有效的数据。若在召回命令之后启动读时隙,若DS18B20正在进行召回EEPROM则会响应“0”,若召回完成则响应“1”。
- 读取供电模式[B4h]
该命令可以读取总线上的DS18B20是否是由“寄生电源”供电。在读取数据时序中“0”表示“寄生电源供”模式供电,“1”表示外部电源供电。
1-Wire总线时序控制
DS18B20采用严谨的1-Wire总线通信协议来保证数据的完整性。该协议定义多个信号形式:复位脉冲,存在脉冲,写0,写1,读0,读1 。除了存在脉冲由从设备发出,其他信号都由主设备控制。
- 初始化—复位和存在脉冲
与DS18B20所有的通信都是由初始化开始的,初始化由主设备发出的复位脉冲及DS18B20响应的存在脉冲组成。当DS18B20响应复位信号的存在脉冲后,则其向主设备表明其在该总线上,并且已经做好了执行命令的准备。
在初始化状态,总线上的主设备通过拉低1-Wire总线最少480us来表示发送复位脉冲。发送完之后,主设备要释放总线进入接收模式。当总线释放后,5kΩ的上拉电阻将1-Wire总线拉至高电平。当DS18B20检测到该上升沿信号后,其等待15us至60us后将总线拉低60us至240us来实现发送一个存在 脉冲。
- 写时隙
主设备通过写时隙将命令写入DS18B20中,写时隙有两种情况:写“1”和写“0”时隙。主设备通过写1时隙来向DS18B20中写入逻辑1,通过写0时隙来向DS18B20中写入逻辑0。当主设备将总线从高电平拉至低电平时,启动写时隙,所有的写时隙持续时间最少为60us,每个写时隙间的恢复时间最少为1us。
当总线(DQ)拉低后,DS18B20在15us至60us之间对总线进行采样,如果采的DQ为高电平则发生写1,如果为低电平则发生写0。
如果要产生写1时隙,必须先将总线拉至逻辑低电平然后释放总线,允许总线在写时隙开始后15us内上拉至高电平。若要产生写0时隙,必须将总线拉至逻辑低电平并保持不变最少60us。
- 读时隙
当我们发送完读取供电模式[B4h]或读高速缓存器[BEh]命令时,必须及时地生成读时隙,只有在读时隙DS18B20才能向主设备传送数据。每个读时隙最小必须有60us的持续时间以及每个读时隙间至少要有1us的恢复时间。当主设备将总线从高电平拉至低电平超过1us,启动读时隙。
当启动读时隙后,DS18B20将会向主设备发送“0”或者“1”。DS18B20通过将总线拉高来发送1,将总线拉低来发送0 。当读时隙完成后,DQ引脚将通过上拉电阻将总线拉高至高电平的闲置状态。从DS18B20中输出的数据在启动读时隙后的15us内有效,所以,主设备在读时隙开始后的15us内必须释放总线,并且对总线进行采样。
[
2. 硬件原理
uart:
通过PL2303实现通过USB与上位机通信
ds18b20:
实物图:
内部图:
三、 系统架构设计
key_debounce按键消抖模块将消抖后的模块提供给后面的模块使用;
ds18b20_ctrl模块根据按键来确定ds18b20的分辨率,通过内部的one_wire模块向ds18b20传感器发送或者接收数据,并根据分辨率转换温度数据,最后输出温度数据、小数点数据以及分辨率状态;
Data_ctrl模块根据分辨率数据以及温度数据控制串口发送模块要发送的数据,再由uart_tx发送数据到上位机;
seg_driver模块根据温度数据以及小数点在数码管上显示。
ds18b20_ctrl:
one_wire模块根据cmd指令来进行工作,当cmd=2’d1时,进行初始化,输出500us的低电平,接着等待500us,如果dq_in在等待的500us内低电平时间超过60us,则初始化完成,cmd_ok[0]=1,否则为0;
cmd=2’d2时根据协议发送8bit的指令,指令数据为输入的send_data,发送完成后cmd_ok[1] = 1;
cmd=2’d3时根据协议读取16bit温度数据,先拉低总线3us再释放,在第12us时读取dq_in的值作为读取的数据,读取完成后cmd_ok[2] = 1。
Data_ctrl:
将温度数据转换为ASCII码并添加"温度"等关键字再交给uart_tx发送。
四、 模块说明
1. 模块端口信号列表
顶层:
输入 | ||
---|---|---|
clk | 系统时钟 | 50MHz |
rst_n | 复位信号 | 低电平有效 |
key[1:0] | 按键信号 | 低电平有效 |
dq | 双端口,ds18b20传入的数据端口 | 1位宽 |
输出 | ||
---|---|---|
tx | 串口数据输出端口 | 1位宽 |
dq | 双端口,FPGA传出数据给ds18b20的端口 | 1位宽 |
sel[5:0] | 数码管位选信号 | 低电平有效 |
seg[7:0] | 数码管段选信号 | 低电平有效 |
ds18b20_ctrl:
输入 | ||
---|---|---|
clk | 系统时钟 | 50MHz |
rst_n | 复位信号 | 低电平有效 |
key[1:0] | 消抖后的按键信号 | 低电平有效 |
dq | 双端口,ds18b20传入的数据端口 | 1位宽 |
输出 | ||
---|---|---|
ratio_num[1:0] | 分辨率计数 | 0:12分辨率、1:11分辨率 、2:10分辨率、3:19分辨率 |
dot[5:0] | 数码管显示的小数点 | 6位宽,低电平有效 |
temp_data[24:0] | 根据分辨率转换后的温度数据 | 25位宽 |
dq | 双端口,ds18b20传入的数据端口 | 1位宽 |
one_wire:
输入 | ||
---|---|---|
clk | 系统时钟 | 50MHz |
rst_n | 复位信号 | 低电平有效 |
cmd[1:0] | 指令信号 | 2位宽,高电平有效 |
dq_in | ds18b20传入的信号 | 1位宽 |
data[7:0] | 需要发送的数据 | 8位宽 |
输出 | ||
---|---|---|
cmd_ok[2:0] | 是否指令执行完成 | 高电平有效 |
rec_data[15:0] | 接收到的温度数据 | 16位宽,rec_data[15]为符号位 |
end_init | 初始化时间结束 | 高电平有效 |
end_bit | 8bit数据发送完成 | 高电平有效 |
dq_out | 传出给ds18b20的数据 | 1位宽,收dq_oe控制 |
dq_oe | dq_out输出使能 | 高电平有效 |
data_ctrl:
输入 | ||
---|---|---|
clk | 系统时钟 | 50MHz |
rst_n | 复位信号 | 低电平有效 |
temp_data[24:0] | 根据分辨率转换后的温度数据 | 25位宽 |
ratio_num[1:0] | 分辨率计数 | 0:12分辨率、1:11分辨率 、2:10分辨率、3:19分辨率 |
输出 | ||
---|---|---|
tx | 数据输出端口 | 1位宽 |
uart_tx:
输入 | ||
---|---|---|
clk | 系统时钟 | 50MHz |
rst_n | 复位信号 | 低电平有效 |
rx_data[7:0] | 接收到的8bit数据8 | 8位宽 |
tx_start | 发送开始信号 | 高电平有效 |
choose[1:0] | 当前校验模式 | 固定为无校验 |
BAUD[31:0] | 波特率 | 固定为115200 |
输出 | ||
---|---|---|
tx | 数据输出端口 | 1位宽 |
tx_idle | 发送状态 | 0为正在发送,1为空闲 |
tx_done | 发送完成 | 高电平有效 |
seg_driver:
输入 | ||
---|---|---|
clk | 系统时钟 | 50MHz |
rst_n | 复位信号 | 低电平有效 |
temp_data[24:0] | 转换后的温度数据 | 25位宽 |
dot[5:0] | 小数点显示位置 | 6位宽,低电平有效 |
输出 | ||
---|---|---|
sel[5:0] | 数码管位选信号 | 低电平有效 |
seg[7:0] | 数码管段选信号 | 低电平有效 |
2. 状态转移图
ds18b20_ctrl:
3. 时序图
one_wire时序图:
ds18b20时序图:
uart_tx时序图
五、 仿真波形图
六、 板级验证效果
七、代码
https://github.com/sunnywindow/DS18B20