This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
您好!
我们将 TMS320F28069与 I2C IO 扩展器结合使用。
有时 I2C 接口有问题。 似乎 FIFO 溢出。
应发送值0x09和值(通常为0x1C)。 在代码中、始终首先发送值0x09 (IO 扩展器的寄存器)。
通过 LogicAnalyzer、我们可以看到值按错误的顺序发送(请参阅屏幕截图)。
Config: void InitI2C ( void ) { I2caRegs.I2CSAR = I2C_SLAVE_ADDR; // (0x20) I2caRegs.I2CPSC.all = 8; // Prescaler - 10MHz I2caRegs.I2CMDR.bit.IRS = 1; // The prescaled frequency takes effect only when IRS is changed to 1. I2caRegs.I2CCLKL = 7; // NOTE: must be non zero I2caRegs.I2CCLKH = 7; // NOTE: must be non zero // --> 100.44 kHz I2C Speed I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT } Function: int16 write_I2c_data ( unsigned int slave_addr, unsigned int length, unsigned char I2CRegister, unsigned char Value ) { int16 retval = 1; retval = check_BB_bit (I2C_TIMEOUT); if (retval < 0) { I2caRegs.I2CMDR.bit.IRS = 0; // Timed out. Reset module. I2C_ Errorhandling (); return retval; // Abbrechen } /***************Write******************/ I2caRegs.I2CSAR = slave_addr; // Setup slave address I2caRegs.I2CCNT = length; // Setup number of bytes to send MsgBuffer + Address I2caRegs.I2CDXR = I2CRegister; I2caRegs.I2CDXR = Value; // Send start as master transmitter I2caRegs.I2CMDR.all = 0x6E20; //gesetzt werden FREE, STT, STP, MST, TRX, IRS // -->> -- I2CMaster_Wait retval |= check_STP_and_BB_bit ( I2C_TIMEOUT); if (retval < 0) { I2caRegs.I2CMDR.bit.IRS = 0; // Timed out. Reset module. I2C_Errorhandling(); return retval; // Abbrechen } //--<<--- return retval; }
致电:
WRITE_I2C_DATA (I2C_SLAVE_ADDR,2,MCP23008_GPIO,GPIO_exp.all);
可以非常快速地调用该函数。
发送 FIFO 的溢出是否已知?
我该如何进行准确的调试?
谢谢你。
马库斯
您好、Markus:
我不知道 I2C 上有任何溢出问题。 为了进行仔细检查、您是否可以在 WRITE_I2C_DATA 函数前后使用 print 语句、以确保发送正确的参数? 如果在写入之间添加延迟、是否有任何变化? 您能否分享这两种未首先发送0x09的情况的屏幕截图?
此致、
阿米尔·奥马尔
您好、Omer:
感谢您提供快速反馈。 在上面的屏幕截图中、可以看到这一点(黄线)。 您可以看到首先发送0x0C、这是错误的。
第一个数据库代码中的调用是一个定义、因此实际上不能首先发送其他值(如0x09)。
#define I2C_SLAVE_ADDR 0x20 #define MCP23008_GPIO 0x09 write_I2c_data ( I2C_SLAVE_ADDR, 2, MCP23008_GPIO, GPIO_exp.all );
在经过延迟后、我无法看到误差。 因此、我们假设 FIFO 溢出。
此致、
马库斯
您好、Markus:
我看了一些用于带有 EEPROM 的 I2C 的示例、看起来通过 FIFO 进行传输时确实有延迟; 有一个 while 循环以最长的时间等待10微秒(它会检查是否接收到 NACK 或发生超时、如果出现这种情况、则会中断循环)。 您是使用轮询来确定何时写入还是中断、还是您只是尽快写入?
此致、
阿米尔·奥马尔
您好 Omar:
我们尽快写信。 我检查 Stopbit 和 Busybit、然后下一个周期开始。
此致、
马库斯
尊敬的 Markus:
我将检查轮询停止位和繁忙位是否足以等待使用 I2C 进行写入、我将在明天尝试与您联系。
此致、
阿米尔·奥马尔
您好、Markus:
您的方法似乎没有问题、您能否在初始帖子第73行提供该函数的函数代码? (RetVal |= CHECK_STP_AND_BB_BIT (I2C_TIMEOUT);)。 此外、由于您使用 FIFO 模式、您 是否可以尝试轮询 I2caRegs.I2CFFTX.bit.TXFFST 位来查看 FIFO 何时为空?
此致、
阿米尔·奥马尔
您好、Omer:
谢谢你。 这是第73行的代码。
int16 check_STP_and_BB_bit( Uint16 timeout ) { int16 retval = 1; retval = check_STP_bit (timeout); retval |= check_BB_bit (timeout); return retval; } int16 check_BB_bit( Uint16 timeout ) { int16 retval = 1; while ( I2caRegs.I2CSTR.bit.BB == 1 ) { DELAY_US( 1 ); timeout--; if ( timeout < 1 ) { retval = -1; // I2C is locked up - fatal Error! break; } } return retval; } int16 check_STP_bit( Uint16 timeout ) { int16 retval = 1; while ( I2caRegs.I2CMDR.bit.STP == 1 ) { DELAY_US( 1 ); timeout--; if ( timeout < 1 ) { retval = -1; // I2C is locked up - fatal Error! break; } } return retval; }
好主意。 我是否也可以为此使用 I2caRegs.I2CFFTX.bit.TXFFINT?
哪一种是更好的解决方案、即对位 TXFFST 或位 TXFFINT 进行极化?
此致、
马库斯
您好、Markus:
由于您正在对代码使用轮询、因此最好保持轮询位的状态、所以我建议尝试 TXFFST、因为它是状态。 TXFFINT 的工作方式应相同、因为您还使能 TXFFIENA 位。
此致、
阿米尔·奥马尔
您好、Omer:
感谢您的答复。 关于 TXFFINT:我之所以读这个、是因为如果我还想产生一个中断、我只需要设置 TXFFIENA。 但根据我的解释、我也可以在不使用中断的情况下使用位 TXFFINT。
TXFFST 包含5位。 对于小于1的情况、我必须进行查询。 借助 TXFFINT、我可以查询等式。 这应该会更快、更高效、对吧?
此致、
马库斯
您好、Markus:
TXFFST 包含5位。 对于小于1的情况、我必须进行查询。 借助 TXFFINT、我可以查询等式。 这应该会更快、更高效、对吗?
这不完全正确、逻辑检查是等效的。 这与所说的0xf 和0x0比0b1和0b0慢相同;只是因为位更多并不一定意味着它需要更长的时间(如果您比较的位数大于与汇编操作等效的位数、则可能需要更长的时间)。 我 在下面创建了一些基本伪代码:
while(I2caRegs.I2CFFTX.TXFFST & 0xF);
这是 类似于您以前检查其他状态位的方式的简单检查。 您只需检查发送 FIFO 何时为空、就可以进行按位与运算、没有太大的开销。
此致、
阿米尔·奥马尔
您好、Omer:
我修改了我的代码。 到目前为止、该测试未显示任何错误。 然而,它也只是偶尔出现以前。
int16 check_TXFFST_FIFO_status( Uint16 timeout ) { int16 retval = 1; while ( I2caRegs.I2CFFTX.bit.TXFFST == 0 ) { DELAY_US( 1 ); timeout--; if ( timeout < 1 ) { i2c_timeout_counter++; retval = -1; break; } } return retval; }
/***************Write******************/ I2caRegs.I2CSAR = slave_addr; I2caRegs.I2CCNT = length; I2caRegs.I2CDXR = I2CRegister; I2caRegs.I2CDXR = Value; retval |= check_TXFFST_FIFO_status ( I2C_TIMEOUT); if (retval < 0) { I2caRegs.I2CMDR.bit.IRS = 0; // Timed out. Reset module. I2C_Errorrhandling(); return retval; } // Send start as master transmitter I2caRegs.I2CMDR.all = 0x6E20;
---
除了使用 int16 check_TXFFST_FIFO_STATUS ( uint16超时),我还使用 int16 check_TXFFINT_bit( uint16超时)对其进行了测试。 到目前为止、这里也没有出现任何错误。
int16 check_TXFFINT_bit( Uint16 timeout ) { int16 retval = 1; while ( I2caRegs.I2CFFTX.bit.TXFFINT == 0 ) { DELAY_US( 1 ); timeout--; break; } } I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1; return retval;
您看到某个函数或另一个函数的优点了吗?
您好、Markus:
在性能方面、它们看起来与我相当。 如果您对此非常谨慎、则可以使用 CCS 周期计数器 来查看函数的运行速度是否有任何差异。
此致、
阿米尔·奥马尔
您好、Omer:
感谢您的评估。 我想通过此函数修复了误差。 感谢您的支持。
此致、
马库斯