我正在为C2000 I2C总线编写文章,并且在主接收器操作模式中遇到一些问题。 我使用轮询而不是基于中断的方法。
从从属设备接收数据时,我的I2C通信每隔几分钟超时一次。 在下面代码的突出显示区域中超时,I2caRegs.I2CSTR.ALL == 0x2430 (NACKSNT, XSMT, SCD, XRDY)。 我不确定在从主发送器模式切换到主接收器模式时是否对寄存器进行了正确编程。 我从从属设备中看不到任何黑色。 仅在主传输模式下(未显示代码),我没有遇到任何问题。
计时器的时钟频率为150MHz,因此20万 周期为133毫秒超时,由于最大读取为6字节,超时时间非常长。
void I2C_read (UINT8 addr,UINT16 regPtr,UINT16 numBytes,UINT16 * data,enum I2C_DEF_error *错误, bool msbFirst,UINT32 timeoutMicroSecs)
{
*ERR = I2C_OK;
i2cMutex.Lock();
色调;
UINT32 lo = CtoMIpcRegs.MIPCCOUNTERL;
UINT32 HI = CtoMIPCRegs.MIPCOUNTERH;
EINT;
UINT32 timed_out = 0;
//主位将自动清除,因此等待以确保是一件好事
//总线是免费的,可以使用新的主中继器
while (I2caRegs.I2CMDR.bit.MST &&!(timed_out = I2C_timedout (lo,hi,2000万)){};
如果(超时)
{
DbgInfo("读取TX 1时超时。 状态:0x%x",I2caRegs.I2CSTR.ALL);
*ERR = I2C_ERROR_TIMEOUT;
i2cMutex.Unlock();
返回;
}
//I2caRegs.I2CMDR.bit.IRS = 0; //这有时是需要的,但我不想总是重置它
I2caRegs.I2CCNT = 1; //在非重复模式(RM =0)中,这表示要发送的字节数。 仅1个用于阅读(寄存器)
I2caRegs.I2CSAR =地址; //从设备的地址
I2caRegs.I2CDXR = regPtr; //要传输的第一个数据字节,即要寻址的远程寄存器
I2caRegs.I2CMDR.bit.TRX = 1; //向从属设备传输数据
I2caRegs.I2CMDR.Bit.MST = 1; //设置主位以启动SCL线。
I2caRegs.I2CMDR.bit.free = 1; //允许I2C在断点中运行
I2caRegs.I2CMDR.bit.stp = 0; //由于我们正在从从属设备接收数据,因此我们要执行重复启动,因此禁用停止位
I2caRegs.I2CMDR.bit.STT = 1; //开始新事务
I2caRegs.I2CMDR.bit.IRS = 1; //将I2C从复位中拉出
//等待寄存器空闲,然后开始事务的读取阶段
while (!I2caRegs.I2CSTR.bit.ARDY &&!(timed_out = I2C_timedout (lo,hi,2000万));
如果(超时)
{
DbgInfo("读取TX 2时超时。 状态:0x%x",I2caRegs.I2CSTR.ALL);
*ERR = I2C_ERROR_TIMEOUT;
i2cMutex.Unlock();
返回;
}
//检查我们是否收到"不确认"
IF (I2caRegs.I2CSTR.bit.nack)
{
DbgInfo("在READ TX. 状态:0x%x",I2caRegs.I2CSTR.ALL);
I2caRegs.I2CMDR.All = 0;
//I2caRegs.I2CMDR.bit.stp = 1;//在这种情况下,我们需要强制执行停止条件
I2caRegs.I2CSTR.bit.nack = 1;//清除nack位(通过向其写入1)
*err = I2C_nack;
i2cMutex.Unlock();
返回;
}
// I2caRegs.I2CMDR.All = 0;
I2caRegs.I2CCNT = numBytes; //在非重复模式(RM =0)中,这表示要读取的字节数。
I2caRegs.I2CMDR.bit.TRX = 0; //我们是主接收器,所以关闭传输位
I2caRegs.I2CMDR.Bit.MST = 1; //仍然是主服务器(可能不需要)
I2caRegs.I2CMDR.bit.free = 1; //允许I2C在断点中运行
I2caRegs.I2CMDR.bit.stp = 1; //停止位将在I2CCNT达到0后应用
I2caRegs.I2CMDR.bit.STT = 1; //对事务的接收部分重复开始
I2caRegs.I2CMDR.bit.IRS = 1; //将I2C从复位中拉出(可能不需要)
UINT16 I(0);
对于(i=0;i < numBytes;i++)
{
while (!(I2caRegs.I2CSTR.bit.RRDY || I2caRegs.I2CSTR.bit.ARDY)&&!(timed_out = I2C_TIMEDOUOUT (lo,hi,2000万)));
如果(超时)
{
DbgInfo("读取RX 1时超时。 状态:0x%x",I2caRegs.I2CSTR.ALL);
*ERR = I2C_ERROR_TIMEOUT;
i2cMutex.Unlock();
返回;
}
//检查我们是否收到"不确认"
IF (I2caRegs.I2CSTR.bit.nack)
{
DbgInfo("在读取Rx中获得了nack. 状态:0x%x",I2caRegs.I2CSTR.ALL);
I2caRegs.I2CMDR.All = 0;
//I2caRegs.I2CMDR.bit.stp = 1;//在这种情况下,我们需要强制执行停止条件
I2caRegs.I2CSTR.bit.nack = 1;//清除nack位(通过向其写入1)
*err = I2C_nack;
中断;
}
//确保已触发接收就绪信号
while (!I2caRegs.I2CSTR.bit.RRDY &&!(timed_out = I2C_timedout (lo,hi,2000万));
如果(超时)
{
DbgInfo("读取RX 2时超时。 状态:0x%x",I2caRegs.I2CSTR.ALL);
*ERR = I2C_ERROR_TIMEOUT;
i2cMutex.Unlock();
返回;
}
//首先根据MSB/LSB将下一个数据字节读入相应的索引中的缓冲区。
__byte((int*)数据,(msbFirst)? numBytes - I -1 :I)= I2caRegs.I2CDRRRr;
}
i2cMutex.Unlock();
}