Arduino Language Reference-Functions-wire-Functions
begin()
Description
该函数初始化Wire库并以控制器或外围设备的身份加入I2C总线。通常只需调用一次该函数。
Syntax
Wire.begin()
Wire.begin(address)Parameters
- address: 7位从机地址(可选);如果未指定,则以控制器设备的身份加入总线。
Returns
无。
end()
Description
禁用 Wire 库,撤消 Wire.begin() 的效果。要在此之后再次使用 Wire 库,请再次调用 Wire.begin()。
注意:此功能在 Wire 库的原始版本中不可用,可能在所有平台上仍不可用。需要跨平台和版本移植的代码可以使用 WIRE_HAS_END 宏,该宏仅在 Wire.end() 可用时定义。
Syntax
Wire.end()Parameters
无。
Returns
无。
requestFrom()
Description
该函数由控制器设备用于从外围设备请求字节。这些字节可以通过 available() 和 read() 函数进行检索。requestFrom() 方法接受一个布尔参数,用于与某些 I2C 设备进行兼容性更改。如果为真,requestFrom() 在请求后发送一个停止消息,释放 I2C 总线。如果为假,requestFrom() 在请求后发送一个重新启动消息。总线不会被释放,这样可以防止另一个主设备在消息之间发出请求。这允许一个主设备在控制时发送多个请求。默认值为真。
Syntax
Wire.requestFrom(address, quantity)
Wire.requestFrom(address, quantity, stop)Parameters
- address: 要请求字节的设备的 7 位从设备地址。
- quantity: 要请求的字节数。
- stop: 真或假。如果为真,将在请求后发送一个停止消息,释放总线。如果为假,将在请求后继续发送重新启动,保持连接活动。
Returns
- byte : 从外围设备返回的字节数。
beginTransmission()
Description
该函数开始与给定地址的 I2C 外设设备进行传输。随后,使用 write() 函数排队待传输的字节,并通过调用 endTransmission() 来传输它们。
Syntax
Wire.beginTransmission(address)Parameters
- address: 要传输到的设备的 7 位地址。
Returns
无。
endTransmission()
Description
此函数结束一个由 beginTransmission() 开始的对外围设备的传输,并且传输由 write() 排队的字节。endTransmission() 方法接受一个布尔型参数,通过改变其行为以兼容某些I2C设备。如果为真,endTransmission() 在传输后发送一个停止消息,释放I2C总线。如果为假,endTransmission() 在传输后发送一个重启消息。总线将不会被释放,这阻止了其他控制器设备在消息之间传输。这允许一个控制器设备在控制期间发送多个传输。默认值为真。
Syntax
Wire.endTransmission()
Wire.endTransmission(stop)Parameters
- stop:真或假。真将在传输后发送一个停止消息,释放总线。假将发送一个重启,保持连接活跃。
Returns
- 0:成功。
- 1:数据太长,无法放入传输缓冲区。
- 2:在地址传输时收到NACK。
- 3:在数据传输时收到NACK。
- 4:其他错误。
- 5:超时。
write()
Description
此函数在控制器设备的请求下,从一个外围设备写入数据,或者在beginTransmission()与endTransmission()调用之间,将字节排队以从控制器传输至外围设备。
Syntax
Wire.write(value)
Wire.write(string)
Wire.write(data, length)Parameters
- value:作为单个字节发送的值。
- string:作为一系列字节发送的字符串。
- data:作为字节发送的数据数组。
- length:要传输的字节数。
Returns
写入的字节数(读取此数字是可选的)。
Example
#include <Wire.h>
byte val = 0;
void setup() {
Wire.begin(); // 加入I2C总线
}
void loop() {
Wire.beginTransmission(44); // 向设备号44(0x2C)发送数据
Wire.write(val); // 发送值字节
Wire.endTransmission(); // 停止传输
val++; // 增加值
// 如果到达第64位(最大)
if(val == 64) {
val = 0; // 从最低值开始
}
delay(500);
}available()
Description
此函数返回可通过 read() 检索的字节数。应在调用 requestFrom() 后在控制器设备上调用此函数,或在 onReceive() 处理程序内的外围设备上调用。available() 继承自 Stream 实用工具类。
Syntax
Wire.available()Parameters
无。
Returns
可读取的字节数。
read()
Description
该函数会读取在调用 requestFrom() 后从外围设备传输到控制器设备的一个字节,或者从控制器设备传输到外围设备的一个字节。read() 继承自 Stream 工具类。
Syntax
Wire.read()Parameters
无。
Returns
接收到的下一个字节。
Example
#include <Wire.h>
void setup() {
Wire.begin(); // 加入 I2C 总线(控制器设备地址可选)
Serial.begin(9600); // 启动串行输出
}
void loop() {
Wire.requestFrom(2, 6); // 从设备编号 2 的从设备请求 6 个字节
// 从设备可能发送少于请求的字节
while(Wire.available()) {
char c = Wire.read(); // 以字符形式接收一个字节
Serial.print(c); // 打印该字符
}
delay(500);
}setClock()
Description
此函数修改用于 I2C 通信的时钟频率。I2C 外围设备没有最低工作时钟频率,但通常 100KHz 是基线。
Syntax
Wire.setClock(clockFrequency)Parameters
- clockFrequency: 所需通信时钟的值(以赫兹为单位)。可接受的值为 100000(标准模式)和 400000(快速模式)。某些处理器还支持 10000(低速模式)、1000000(快速模式加)和 3400000(高速模式)。请参阅特定处理器文档,以确保支持所需模式。
Returns
无。
onReceive()
Description
该函数用于注册一个函数,当外围设备从控制器设备接收到传输时调用该函数。
Syntax
Wire.onReceive(handler)Parameters
- handler: 当外围设备接收到数据时调用的函数;该函数应该接受一个 int 型参数(从控制器设备读取的字节数),且没有返回值。
Returns
无。
onRequest()
Description
该函数用于注册一个在控制器设备请求外围设备数据时将被调用的函数。
Syntax
Wire.onRequest(handler)Parameters
- handler: 将被调用的函数,不接受任何参数且无返回值。
Returns
无。
setWireTimeout()
Description
在主模式下设置 Wire 传输的超时时间。
注意: 这些超时几乎总是潜在问题的指示,例如设备故障、噪声、屏蔽不足或其他电气问题。这些超时将防止您的草图锁定,但不会解决这些问题。在这种情况下,通常还会出现数据损坏,但不会导致超时或其他错误,并且保持未被检测。因此,当发生超时时,之前读写的一些数据也可能已损坏。可能需要采取其他措施来更可靠地检测此类问题(例如校验和或读回写入的值)并从中恢复(例如完全系统重置)。此超时和此类其他措施应被视为最后一道防线,如果可能的话,应该修复根本原因。
Syntax
Wire.setWireTimeout(timeout, reset_on_timeout)
Wire.setWireTimeout()Parameters
timeout: 超时时间(微秒),如果为零则禁用超时检查reset_on_timeout: 如果为 true,则在超时时自动重置 Wire 硬件
当不带参数调用此函数时,将配置一个默认超时,该超时应足以防止典型的单主机配置锁定。
Returns
None。
Example Code
#include <Wire.h>
void setup() {
Wire.begin(); // 加入 i2c 总线(主机可选地址)
#if defined(WIRE_HAS_TIMEOUT)
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
#endif
}
byte x = 0;
void loop() {
/* 首先,向另一个设备发送命令 */
Wire.beginTransmission(8); // 传输到设备 #8
Wire.write(123); // 发送命令
byte error = Wire.endTransmission(); // 运行事务
if (error) {
Serial.println("写入时发生错误");
if (error == 5)
Serial.println("它是超时");
}
delay(100);
/* 然后,读取结果 */
#if defined(WIRE_HAS_TIMEOUT)
Wire.clearWireTimeoutFlag();
#endif
byte len = Wire.requestFrom(8, 1); // 从设备 #8 请求 1 字节
if (len == 0) {
Serial.println("读取时发生错误");
#if defined(WIRE_HAS_TIMEOUT)
if (Wire.getWireTimeoutFlag())
Serial.println("它是超时");
#endif
}
delay(100);
}Notes and Warnings
此超时在不同平台上的实现方式可能有所不同,但通常在等待(部分)事务完成时触发超时条件(例如等待总线再次可用、等待 ACK 位或者可能等待整个事务完成)。
当发生此类超时条件时,事务将被中止,endTransmission() 或 requestFrom() 将返回错误代码或零字节。虽然这本身不会解决总线问题(即它不会移除短路),但至少可以防止无限期阻塞,并允许您的软件检测并可能解决此条件。
如果 reset_on_timeout 被设置为 true 并且平台支持,Wire 硬件也会被重置,这有助于清除 Wire 硬件模块内部的任何不正确状态。例如,在 AVR 平台上,在噪声引起的超时后,可能需要重新启动通信。
当触发超时时,将设置一个标志,可以使用 getWireTimeoutFlag() 进行查询,并且必须使用 clearWireTimeoutFlag() 手动清除(在调用 setWireTimeout() 时也会被清除)。
请注意,在等待时钟伸展或等待第二个主机完成其事务时,也可能会触发此超时。因此,如果需要,请确保适当调整超时时间。典型的超时时间是 25 毫秒(这是 SMBus 协议允许的最大时钟伸展时间),但(较短的)值通常也可以工作。
Portability Notes
该函数在最初版本的 Wire 库中不可用,并且在某些平台上可能仍然不可用。需要跨平台和版本移植的代码可以使用 WIRE_HAS_TIMEOUT 宏,该宏仅在 Wire.setWireTimeout()、Wire.getWireTimeoutFlag() 和 Wire.clearWireTimeout() 都可用时定义。
当该超时功能在 AVR 平台上引入时,它最初默认保持禁用状态以保持兼容性,期望在以后的某个时候启用。这意味着超时的默认值可能因平台(版本)而异。可以从 WIRE_DEFAULT_TIMEOUT 和 WIRE_DEFAULT_RESET_WITH_TIMEOUT 宏获取默认超时设置。
如果您需要禁用超时,建议您使用 setWireTimeout(0) 默认禁用它,即使目前它是默认设置。
clearWireTimeoutFlag()
Description
清除超时标志。
默认情况下可能不会启用超时。有关如何配置超时及其工作方式的更多信息,请参见 Wire.setWireTimeout() 的文档。
Syntax
Wire.clearTimeout()Parameters
无。
Returns
无。
Portability Notes
原始版本的 Wire 库中没有此函数,在某些平台上可能仍然不可用。需要跨平台和版本移植的代码可以使用 WIRE_HAS_TIMEOUT 宏,只有在 Wire.setWireTimeout()、Wire.getWireTimeoutFlag() 和 Wire.clearWireTimeout() 都可用时才定义该宏。
getWireTimeoutFlag()
Description
检查自上次清除标志后是否发生了超时。
每当发生超时时,此标志都会被设置,并在调用 Wire.clearWireTimeoutFlag() 或使用 Wire.setWireTimeout() 更改超时时被清除。
Syntax
Wire.getWireTimeoutFlag()Parameters
无。
Returns
- bool: 标志的当前值
Portability Notes
此函数在原始版本的 Wire 库中不可用,并且在某些平台上可能仍然不可用。需要跨平台和版本移植的代码可以使用 WIRE_HAS_TIMEOUT 宏,只有当 Wire.setWireTimeout()、Wire.getWireTimeoutFlag() 和 Wire.clearWireTimeout() 全部可用时才定义该宏。