Arduino作为具有多个i2c地址的从机
我想使用Arduino作为i2c从机。但我要求Arduino通过使用多个i2c地址注册自身,充当多个设备 这可能不是人们通常会做的事情,但我这样做的原因如下: 我想使用Arduino作为Spektrum遥测的遥测传感器。遥测接收器有几个i2c插头,连接到多个传感器(电流0x02、电压0x03、空速0x11等),每个传感器都有遥测接收器期望的固定i2c地址 我想使用oneArduino作为所有这些设备,使用上述所有地址注册自身,并用读数进行适当响应 我可以在每个传感器上使用一个Arduino,这看起来很愚蠢,因为我可以用一个Arduino pro mini执行所有这些读数 我知道你可以使用Arduino作为具有多个i2c地址的从机,arduino,i2c,atmega,Arduino,I2c,Atmega,我想使用Arduino作为i2c从机。但我要求Arduino通过使用多个i2c地址注册自身,充当多个设备 这可能不是人们通常会做的事情,但我这样做的原因如下: 我想使用Arduino作为Spektrum遥测的遥测传感器。遥测接收器有几个i2c插头,连接到多个传感器(电流0x02、电压0x03、空速0x11等),每个传感器都有遥测接收器期望的固定i2c地址 我想使用oneArduino作为所有这些设备,使用上述所有地址注册自身,并用读数进行适当响应 我可以在每个传感器上使用一个Arduino,这看
Wire.begin(0x02);
但我需要类似的东西(伪代码)
当收到请求时,我需要知道询问Arduino的地址
例如(伪代码)
任何建议都将不胜感激。
使用Wire库无法使Arduino侦听多个从机地址,因为它只允许传递单个从机地址
即使是大多数Arduinos所基于的Atmel ATmega微控制器也只允许通过其双线地址寄存器TWAR将其硬件双线串行接口(TWI)设置为单个7位地址。然而,可以通过使用TWI地址屏蔽寄存器
TWAMR
屏蔽一个或多个地址位来解决此限制,如第22.9.6节所述(略为简要):
TWAMR可以加载7位Salve(原文如此!)地址掩码。TWAMR中的每个位都可以屏蔽(禁用)TWI地址寄存器(TWAR)中的相应地址位。如果掩码位设置为1,则地址匹配逻辑将忽略传入地址位与TWAR中相应位之间的比较
因此,我们首先必须根据我们想要响应的所有I2C地址设置掩码位,方法是对它们进行OR运算并向右移位以匹配TWAMR
寄存器布局(TWAMR
将掩码保持在位7:1,位0未使用):
TWAMR=(sensor1|addr | sensor2|addr | sensor3|addr)我真的很喜欢vega8的答案,但我还想提一点,如果你的I2C主机的时钟速度不快,那么使用基于软件的I2C实现也是可行的,可以给你想要的自由
如果粗略的计算表明在TWI ISR中花费的时间太高,中断可能会开始重叠,那么您可能需要考虑该方法。p> void setup()
void setup()
{
Wire.begin(0x11 | 0x12); // Adr 11 and 12 are used for Alt and Speed by Spectrum DX
Wire.onRequest(requestEvent); // register callback function
TWAMR = (0x11 | 0x12) << 1; // set filter for given adr
}
{
Wire.begin(0x11 | 0x12);//Adr 11和12通过频谱DX用于Alt和Speed
onRequest(requestEvent);//注册回调函数
TWAMR=(0x11 | 0x12)
这适用于带有遥测模块的频谱DX8。
频谱接口在Sectrum主页上公开。技术文档。I2C总线上可能有其他设备,TWAMR应设置为尽可能少的位。因此我认为计算掩码的更好方法是:
AddrOr = Addr1 | Addr2 | Addr3 | Addr4 ...
AddrAnd = Addr1 & Addr2 & Addr3 & Addr4 ...
TWAMR = (AddrOr ^ AddrAnd) << 1
AddrOr=Addr1 | Addr2 | Addr3 | Addr4。。。
AddrAnd=Addr1&Addr2&Addr3&Addr4。。。
TWAMR=(AddrOr^AddrAnd)好的评论,thx!这意味着实现硬件中已有的大部分功能(包括增加的程序大小+额外的测试)。当然更灵活,典型的折衷情况。如果使用除原始Arduino之外的平台是一种选择,ATXmega1设备配有4个I2C接口,github上有一个名为Xmegaduino的接口。谢谢@vega8,你的回答非常有描述性!如果可行,我会尝试更新。回答很好。有一个问题;有一些问题吗限制地址数量的因素(除了7位地址外)?是否可以专门处理6个地址?例如:(0x28 | 0x29 | 0x2A | 0x2B | 0x2C | 0x2D)这个想法确实有效!!这里有一个代码库:我唯一想添加的是,计算掩码的正确方法不是使用and和运算符。欢迎使用SO。请记住在代码中添加4个空格的缩进,以便正确显示。此外,我还建议添加一些注释。欢迎使用SO。请请记住在代码中添加4个空格的缩进,以便正确显示。
void setup()
{
Wire.begin(0x11 | 0x12); // Adr 11 and 12 are used for Alt and Speed by Spectrum DX
Wire.onRequest(requestEvent); // register callback function
TWAMR = (0x11 | 0x12) << 1; // set filter for given adr
}
void requestEvent() {
int adr = TWDR >> 1; // move 1 bit to align I2C adr
if (adr == 0x12) // check for altitude request at adr 12
Wire.write(tmpSpektrumDataAlt, 16); // send buffer
if (adr == 0x11) // check for speed request at adr 11
Wire.write(tmpSpektrumDataSpd, 16); // send buffer
}
AddrOr = Addr1 | Addr2 | Addr3 | Addr4 ...
AddrAnd = Addr1 & Addr2 & Addr3 & Addr4 ...
TWAMR = (AddrOr ^ AddrAnd) << 1