单总线通信

单总线(1-wire Bus)是所有数据都在一条线上传输,因此主设备与仆从设备只需通过一条I/O线连接即可实现双向通讯。既可传输时钟,又能传输数据。该项技术由Maxim全资子公司Dallas半导体公司推出。

原理

单总线系统使用单总线主机控制一个或多个仆从设备。当总线上只有一个仆从设备时,系统被称为“单点系统(single-drop)”,具有多个设备则可称之为“多点系统(multidrop)”。所有的数据和命令首先通过单总线传输至最低有效位。

以下对单线总线系统的讨论分为三个主题:硬件结构、命令序列和信号方式(信号类型和定时)。

硬件结构

单总线只有一根数据线,因此每个设备(主设备或仆从设备)通过一个漏极开路或三态端口,连接至该数据线。这就相当设备被释放了一样:当设备没有传输数据时,能够保证总线能被其他设备使用。单总线仆从设备的端口为漏极开路,其内部等效电路如下图所示:

单总线需要大约5kΩ的外部上拉电阻,这样能够保证单总线闲置状态下总是高电平

如果由于某些原因,一次传输需要被挂起(撤销),但是同时要保证传输继续,则总线必须被置于闲置状态。

位传输之间的恢复事件没有限制,只要总线再恢复器件处于闲置状态(高电平)。如果总线保持低电平超过480μs,总线上的所有器件将被重置。

命令序列

一般来说,单总线的命令序列包含以下几个部分:

  • 第一步:初始化
  • 第二步:ROM命令(包括需要交换的数据)
  • 第三步:仆从设备特定功能命令(包括需要交换的数据)

每次访问单总线器件(例如DS18B20)都应该严格按照以上步骤,如果命令顺序混乱,那么仆从设备不会响应主设备。搜索命令ROM[F0h]和报警搜索命令ROM[ECh]这两条命令不遵循以上要求:当执行这两条命令中的任何一个之后,主设备不能执行其后的命令,而应当返回到第一步(初始化)。

1.初始化

所有单总线上的传输过程都由初始化开始。初始化过程由主设备发出的复位脉冲和仆从设备响应的应答脉冲组成。应答脉冲让主设备知晓仆从设备位于单总线上并等待下一步操作。

复位脉冲和应答脉冲的时间序列详见下面的“信号时序”部分。

2.ROM命令

当主设备监测到应答脉冲,就可以发出ROM命令。这些命令与各个仆从设备的唯一64位ROM代码相关。当单总线上连接多个仆从设备时,主设备能够通过特定的ROM代码,操作指定的仆从设备。

同时,这些命令还允许主设备分辨单总线上应答的这些仆从设备的数量与种类,或者分辨是否有仆从设备正处于报警状态。

仆从设备可能支持5种ROM命令,而每个命令为8位长度。主设备必须在发出器件特定功能指令之前,发出适当的ROM命令。关于ROM命令的流程顺序,参考下图:

1)搜索(SEARCH)ROM[F0h]

当系统初始上电时,主设备必须找出单总线上所有仆从设备的ROM代码(即其特定地址)。这一命令保证主设备分辨仆从设备的数量以及器件类型。主设备通过重复执行搜索ROM循环,以找出总线上所有的从机设备。搜索ROM的详细说明步骤,请参阅iButton®标准手册www.maxim-ic.com/ibuttonbook

如果总线只有一个仆从设备,则可以采用读取ROM命令来替代搜索ROM命令,见下条(READ ROM[33h])。

在每次执行完搜索ROM命令后,主设备必须返回至命令序列的第一步(初始化)。

2)读取(READ )ROM[33h] (仅适用于单点系统)

该命令适用于总线上只有一个仆从设备的情况(即单点系统)。主设备能够通过该命令直接读取仆从设备的64位ROM代码,而无需执行搜索ROM命令。

3)匹配(MATCH)ROM[55h]

匹配ROM命令,需要跟随64位ROM代码,从而允许主设备访问多节点系统种某个指定的仆从设备(即与64位ROM代码对应)。仅当仆从设备完全匹配64位ROM代码时,才会响应仆从设备随后发出的特定功能命令,而其他仆从设备将处于等待复位脉冲状态。

4)跳越(SKIP)ROM[CCh]

主设备能够采用该命令同时访问总线上的所有仆从设备,而无需发出任何ROM代码。例如,主设备可以在发出跳越ROM命令后跟随DS18B20的转换温度命令,就可以同时命令总线上所有的DS18B20开始转换温度。

注意,只有当单总线上只有一个仆从设备时,才能在读取暂存器(Read Scratchpad [BEh])功能命令前使用跳越ROM指令。在这种情况下,允许主设备直接读取而不用再访问64位ROM代码,这样也能节约一些时间。如果在多点系统中,在跳越ROM指令后跟随读取暂存器功能指令,则将会造成数据混乱。

5)报警搜索[ECh](仅少数单总线器件支持,如DS18B20)

该命令操作与搜索ROM指令基本相同,但是只有那些设置了报警标志的仆从设备会响应。该命令能够让主设备找到那些发生了报警的仆从设备(例如测量的温度过高或者过低)。同搜索ROM命令一样,在报警搜索循环后,主设备必须返回值命令序列的第一步。

3.仆从设备特定功能命令

在主机发出ROM命令,以范文某个指定的单总线器件,接着就可以利用该器件支持的命令对其进行相应操作。具体的仆从设备特定功能命令需要查阅单总线器件的说明书。

例如DS18B20数字温度模块的操作命令。

信号时序

单总线适用于多个主机系统,能够控制一个或多个从机设备。
因此单总线协议对时序要求非常严格以确保数据的完整性。
单总线协议定义了几种信号类型:

  • 复位脉冲
  • 应答脉冲
  • 写0
  • 写1
  • 读0
  • 读1

所有这些信号,除了应答脉冲以外,都由主设备发出同步信号,并且发送所有的命令和数据总是从最低有效位开始(低位在前,这一点和多数串行通信格式不同,后者多为字节的高位在前)。

初始化序列:复位脉冲和应答脉冲

单总线上的所有通信都是初始化序列开始,包括:主设备发出的复位脉冲及仆从设备的应答脉冲,如下图所示。当仆从设备发出响应主机的应答脉冲时,即向主机表明它处于总线上,且工作准备就绪。

在主设备初始化过程,主设备通过拉低单总线至少480μs,以产生(Tx)复位脉冲。接着,主设备释放总线,并进入接收模式(Rx)。

当总线被释放后,5kΩ上拉电阻将单总线拉高。当单总线器件监测到上升沿信号后,延时15-60μs,以产生应答脉冲

读/写时序

在写时序期间,主机向单总线期间写入数据;而在读时序期间,主设备读入来自仆从设备的数据。在每一个时序,总线只传输一位数据。(时序见下图,上一排为写时序,下一排为读时序)

1.写时序

写时序包括写0时序和写1时序。

主设备采取写1时序时,则向仆从设备写入1;而采用写0时序时,则向仆从设备写入0。

所有写时序至少需要 60μs,且在 2 次独立的写时序之间至少需要 1μs 的恢复时间。

两种写时序均起始于主设备拉低总线。

  • 产生写1时序的方法:主设备在拉低总线后,接着必须在15μs之内释放总线,由5kΩ上拉电阻将总线拉至高电平;
  • 产生写0时序的方法:在主设备拉低总线后,只需在整个时序期间保持低电平即可(至少60μs)。

在写时序起始后15-60μs期间,单总线期间采样总线电平状态。如果在此期间采样位高电平,则1被吸入该器件;如果为0.则写0。

2.读时序

单总线器件仅在主机发出读时序时,才向主设备传输数据,所以,在主设备发出读数据命令后,必须马上产生读时序,以便仆从设备能够传输数据。所有读时序至少需要60μs,且在两次独立的读时序之间中少需要1μs的恢复时间。
每个读时序都由主设备发起,至少拉低总线1μs(如上图第二排所示)。在主设备发起读时序之后,单总线器件才开始在总线上发送0或1。若仆从设备发送1,则保持总线为高电平;若发送0,则拉低总线。当发送0时,仆从设备在该时序结束后释放总线,由上拉电阻将总线拉回至空闲状态(高电平)。仆从设备发出的数据在起始时序之后,报持有效时间15μs,因而,主机在读时序期间必须释放总线,并且在时序其实后的15μs之内采样总线状态。

在了解了单总线时序之后,以DS18B20的典型温度读取为例,读取过程为:复位→发SKIP ROM命令(0XCC)→发开始转换命令(0X44)→延时→复位→发送 SKIP ROM命令(0XCC)→发读存储器命令(0XBE)→连续读出两个字节数据(即温度)→结束。

OneWire库

你可以利用以上的单总线原理从头编写单总线通信的代码。我们可以发现,单总线的利用遵循严格的步骤,因此,这样的单总线代码被集成成了库函数,只需要调用OneWire.h文件中的函数,可以节省大量繁琐操作。

OneWire myWire(pin)

利用特定的引脚,创建OneWire类型的对象。你可以把许多单总线设备都连接在同一个引脚上,但是数量太大的化,建议你把他们分好组,每一组利用同一个引脚(对应的你也要为每组创建OneWire对象),这样能够保证你的布线不过于太混乱。

myWire.search(addrArray)

搜索下一个设备。addrArray是一个8位地址。如果设备找到,那么addrAraay将由找到的设备地址填充,同时返回true。如果没有搜寻到设备,则会返回false

myWire.reset_search()

开始新的一次搜寻,并且从第一次搜寻到的设备地址开始。

myWire.reset()

重置单总线。与任何设备开始通信都需要进行该步操作。

myWire.select(addrArray)

利用addrArray选择该地址的设备。每一次重置后(reset)后,都需要选择我们将要使用的设备,之后所有的通信都将经由该地址,除非重新重置单总线(reset)。

myWire.skip()

跳过设备选择。只有只接入了一个设备的时候该方法才有效。这个方法的好处在于,我们不需要再重新搜索设备(search),从而能够直接访问这一设备。

myWire.write(num);

写一个字节,可以利用该方法来写入指令操作设备。

myWire.write(num, 1);

写一个字节,并保持电源接通单总线。

myWire.read()

读取一个字节。

myWire.crc8(dataArray, length)

在数据数组上进行CRC校验。

文档更新时间: 2020-07-24 14:58   作者:Astilbe