博客专栏

EEPW首页 > 博客 > 什么是 1-Wire 协议?

什么是 1-Wire 协议?

发布人:电子资料库 时间:2023-01-16 来源:工程师 发布文章

1-Wire 协议是一种单线接口、半双工、双向、低速和功率、长距离串行数据通信协议。尽管该协议被归类为单线标准,但单线标准总线至少需要两根线——一根用于数据和/或电源,另一根用于接地回路。根据电源模式,可能需要额外的电线。

单线标准具有主从配置,其中只能有一个主设备、一台计算机或微控制器以及多个从设备。可以使用 1-wire 标准总线连接多达 100 个从属 1-wire 设备。但是,随着从设备添加到总线,主设备轮询它们可能需要更多时间。

该协议不使用时钟信号。相反,从属设备在内部计时并与来自主设备的信号同步。主设备单独负责从设备的读写操作,因此它们不能自行发起数据传输。他们能做的是在主机复位时通过总线指示他们的存在。 每个主设备都由一个 64 位地址标识,存储在每个单线从设备的 ROM 中。

这是一种低速串行通信标准,典型数据速度为 15.4 kbps。总线可以超速至 125 kbps 的最大数据速度。与其他标准串行数据通信协议(如 UART、I2C 和 SPI)相比,1-Wire 协议的数据速度较低,但 1-wire 总线在生产和运行中非常经济。它提供简单的硬件实现和极低的功耗占用空间。

虽然硬件简单,但微控制器端的软件实现却非常复杂。尽管功耗低,但它可以在相对较长的距离内传输数据。

1-Wire 协议用于温度传感器、实时时钟、定时器、EEPROM 和流行的 iButton。这些 1-wire 从器件中的大多数都是(现在的)Maxim Integrated 的产品。

让我们更详细地讨论一下。

什么是 1-Wire 协议?

1-Wire 协议是一种单线接口,用于微控制器和计算机中的低速数据通信。该协议在没有时钟信号的情况下在单条数据线上运行。它是一种主从串行通信协议,其中与多个从机的半双工双向数据通信由单个主机单独管理和控制。

1-wire 标准总线

1-wire 标准总线至少有两根线。一根是数据线,一根是地线返回。主机和从机都与数据线有开漏(集电极开路)连接。这就是 4.7K 电阻通常将数据线拉高的原因。1-wire 从设备有两种可能的供电模式:寄生和传统。

在寄生模式下,只有数据线和接地回路必须追踪到 1-wire 从器件。如果使用传统的电源模式,则必须为每个连接到总线的 1-wire 从设备追踪一条额外的正电源线。

因此,PCB 上的 1-wire 总线可能有两根或三根线。传统的1-wire总线三线供电更可靠。

寄生供电VS常规供电

如前所述,1-wire 从设备可以在寄生模式和常规模式下供电。所有 1-wire 从器件都有三个端子:VDD、GND 和数据。在寄生模式下,VDD 和 GND 引脚接地,因此信号和电源在同一根线(即数据线)上提供给从设备。

从属设备有一个 800 pF 的内部电容器,当数据线为高电平时,它会被充电。当数据线为低电平时,存储的电荷使从机保持活动状态。数据线通常由一个 4.7K 电阻上拉。

寄生供电需要严格的时序和准确规范的供电,以确保从属设备正常运行。这就是为什么这种模式不太可靠的原因。通常,使用额外的硬上拉来确定电源。

image.png


1-wire 器件的寄生供电。

image.png


带有额外硬上拉的 1-wire 器件的寄生供电。

在传统的供电模式下,1-wire 从设备由外部供电。每个 1-wire 从属设备都跟踪一根额外的线。从站的外部电源确保即使在恶劣的高温条件下也能安全运行。

image.png


1-wire 设备的常规供电。

典型的 1-wire 器件工作电压范围为 – 1.71~1.89V、1.71~3.63V、2.97~6.63V 和 2.97~5.25V。消耗的电流范围在 1.06~5mA 之间。上拉电阻设置电流电平,无论设备是提供寄生电源还是传统电源。

1-Wire 协议如何工作

该接口通常不用于微控制器或微型计算机。它通常由使用位拆分或通用异步接收器-发送器 (UART) 的软件来实现。

数据线上的通信由主机使用复位启动。它拉低数据线 480 us,然后释放它,允许典型的上拉电阻将数据线拉高。如果从设备连接到总线,它们通过将数据线拉低 60~240 us 来响应复位信号。如果线路被从设备拉低,则主设备通过总线确认它们的存在。60~240 us后,slave(s)释放数据线,master开始写入。

image.png


复位后,主设备可以与从设备写入和读取数据。最初,它发送 ROM 命令,如搜索 ROM 命令 (0xF0),以访问从属设备的 ROM 地址。在读取所有连接的 1-wire 从设备的 ROM 地址后,主设备可以通过发送匹配 ROM 命令(0x55)来访问一个。ROM 命令之后是功能命令。

例如,如果总线上连接了一个 1-wire 温度传感器,微控制器可以发送功能命令来启动温度转换、读取温度等。ROM 和功能命令都是 8 位长。

由于 1-Wire 标准不使用任何时钟信号,“0”和“1”位的通信通过为特定时隙设置数据线的逻辑电平来实现。通常,时隙为 60 us 长。每个时隙之间也有1us的间隔,使数据线再次被上拉电阻拉高。在每个 60 us 时隙中,主从之间通信 1 位。如果总线过载,时隙最多可缩短 10 倍。

当主机必须在数据线上写入位时,它会将数据线拉低。

  • 要写入“0”,主机在整个 60 us 时隙内拉低数据线,然后在时隙之间以 1us 间隔释放它。

  • 要写入“1”,主机在整个时隙内将数据线拉低 15 us 的较短时间,然后在时隙之间以 1 us 的间隔释放它。

从设备大约在中间时隙(即 60us 时隙中的 30us)发出脉冲。他们有一个基本的单稳态多谐振荡器来检测脉冲的持续时间。ROM 和功能命令为 8 位长。传送的数据也是以 8 位为一组。错误检测是通过 8 位循环冗余校验来执行的。

image.png


主设备在发送 ROM 搜索或功能命令后从从设备读取。读取操作由主设备控制。主机逐位读取从机,同时数据以 8 位为一组传送给主机。每个位在 60 us 时隙中读取(如果总线过载则更短)。

master拉低数据线1us后释放。然后,它在 15 us 后从总线采样数据。如果从机在总线上写入“0”,它会在整个 60 us 时隙内保持线路处于下拉状态,然后在时隙之间以 1us 间隔释放数据线。如果从机在总线上写入'1',它会保持线下拉15 us,然后释放上拉电阻将数据线拉高的数据线。

主机在 15 us 后对每个位进行采样。如果从设备发送的位为“0”,则该线在采样时被拉低。如果从设备发送的位为“1”,则该线在采样时被拉高。

image.png


主机可以在 1 线标准总线上与多达 100 个从机通信。然而,连接到总线的 1-wire 从机数量越多,主机从它们拉取数据所需的时间就越多。软件库通常使用 bit-banging 或 UART 来计时脉冲持续时间。在 1-Wire 协议中,LSB 总是最先发送。

协议实现

1-wire 通信中有五种总线信号,每一种都由主机发起和控制。这些信号是 Reset、Presence、Write 0、Write 1 和 Read。

该协议可以通过微控制器或计算机以两种方式实现:轮询和中断驱动实现。Polled 是一种纯软件实现。中断驱动的实现需要一个内置的定时器/计数器。

就 Arduino 而言,可以使用 delayMicroseconds() 函数完成轮询实现(仅软件)。这个函数有这个源代码:

void delayMicroseconds(unsigned int us)
{
// calling avrlib’s delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
// for the 16 MHz clock on most Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call yields a delay of approximately 1 1/8 us.
if (–us == 0)
return;
// the following loop takes a quarter of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2;
// account for the time taken in the preceeding commands.
us -= 2;
// busy wait
__asm__ __volatile__ (
“1: sbiw %0,1” “nt” // 2 cycles
“brne 1b” : “=w” (us) : “0” (us) // 2 cycles
);
}

对于 Arduino,1-wire 写操作可以用这个函数来执行:

void OWWrite(uint8_t bit){
if(bit){
//Write bit ‘1’
digitalWrite(PINNUMBER, 0x00);
delayMicroseconds(6);
digitalWrite(PINNUMBER, 0x01);
delayMicroseconds(64);
}
else{
//Write bit ‘0’
digitalWrite(PINNUMBER, 0x00);
delayMicroseconds(60);
digitalWrite(PINNUMBER, 0x01);
delayMicroseconds(10);
}
}

对于计算机来说,同样的功能可以用C++来写,如下:

void OWWrite(uint8_t bit){
if(bit==1){
//PF5 is port name
PORTF &= ~(1<<PF5);
delayMicroseconds(6);
PORTF |= (1<<PF5);
delayMicroseconds(64);
}
else{
PORTF &= ~(1<<PF5);
delayMicroseconds(60);
PORTF |= (1<<PF5);
delayMicroseconds(10);
}
}

对于Arduino,1-wire读取操作可以通过这个函数来执行:

uint8_t OWRead(void){
uint8_t result;
digitalWrite(PINNUMBER, 0x00);
delayMicroseconds(6);
digitalWrite(PINNUMBER, 0x01);
delayMicroseconds(9);
pinMode(PINNUMBER, INPUT);
result = digitalRead(PINNUMBER) & 0x01;
delayMicroseconds(55);
pinMode(PINNUMBER, OUTPUT);
return result;
}

对于计算机,相同的功能可以用 C++ 编写如下。

uint8_t OWReadBit(void){
uint8_t result = 0;
PORTF &= ~(1<<PF5);
delayMicroseconds(10);
PORTF |= (1<<PF5);
delayMicroseconds(20);
if(PINF & (1<<PF5)){
result = HIGH;
}
delayMicroseconds(30);
return result;
}

对于 Arduino,可以使用此函数执行重置和存在操作:

uint8_t OWResetPresence(void){
uint8_t result;
delayMicroseconds(0);
digitalWrite(PINNUMBER, 0x00);
delayMicroseconds(480);
digitalWrite(PINNUMBER, 0x01);
delayMicroseconds(70);
pinMode(PINNUMBER, INPUT);
result = digitalRead(PINNUMBER)^0x01;
delayMicroseconds(410);
pinMode(PINNUMBER, OUTPUT);
return result;
}

对于计算机,可以用 C++ 编写相同的函数:

uint8_t OWResetPresence(void){
uint8_t result = LOW;
PORTF &= ~(1<<PF5);
delayMicroseconds(480);
PORTF |= (1<<PF5);
delayMicroseconds(55);
if(PINF&(1<<PF5)){
result = HIGH;
}
return result;
}

微控制器和计算机可以使用 UART 来实现 1-Wire 协议的中断驱动。计算机可能需要一个外部 UART 芯片或分线板来与 1-wire 设备通信。

UART 的 Tx 和 Rx 必须连接到 1-wire 总线的数据线。UART 端口必须有一个集电极开路缓冲器,以便从设备可以下拉数据线。对于复位和存在信号,波特率必须设置为 9600,并且控制器/计算机需要传输 0xF0。

传输过程中:

  • 位 0~3 设置为'0'

  • 第 4 位设置为“1”

  • Bits 5~7 由从机写入。

  • 停止位设置为高

如果没有从设备连接到总线,则接收到的值为 0xF0。如果收到 0xF0 以外的任何值,则表示总线上存在 1-wire 从机。

对于单线写操作,UART 的波特率必须设置为 115200。起始位必须设置为“0”,停止位必须设置为“1”。

要写入“1”,UART 必须发送 0xFF 并接收 0xFF 作为回报。要写入“0”,UART 必须发送 0x00 并接收 0x00 作为回报。

对于单线读取操作,UART 的波特率必须设置为 115200。起始位必须设置为“0”,停止位必须设置为“1”。读取时,UART 传输一个值为 0xFF 的值,相当于释放拉高状态的线。其余位由从机写入。如果从设备写入“1”,则起始位之后的所有位都设置为“1”,因此 UART 接收到值 0xFF。如果从设备写入“0”,则起始位之后的所有位都设置为“0”,因此 UART 接收到除 0xFF 之外的任何值。

image.png


顺序检测

主设备可以搜索和检测总线上任意数量的 1-wire 从设备。还可以将多达 100 个从属设备连接到 1-wire 标准总线。然而,在标准的 1-wire 总线中,主机没有检测总线上从机物理顺序的机制。在一些 1-wire 器件中,提供了两个额外的引脚来支持序列检测。DS28EA00 就是这样一种器件。

image.png


1 线接口中的序列检测。

器件

1-Wire 协议是专有标准。所有 1-wire 器件均由 Maxim Integrated 制造。该表列出了一些著名的 1-wire 器件。

image.png


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。



关键词: wire 协议

相关推荐

技术专区

关闭