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.

[参考译文] TMS320F28377S:Driverlib:使用 I2C 发送和接收数据

Guru**** 2482225 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/692922/tms320f28377s-driverlib-sending-and-receiving-data-with-i2c

器件型号:TMS320F28377S

您好!

我正在尝试弄清楚如何使用 I2C 发送数据序列。

 我正在使用 Driverlib 库、但"示例"和数据表对如何发送和接收数据包没有任何帮助。

如果我发送此信息;

空 PCA9555D_Config (uint32_t Base、uint16_t id、uint16_t inout)


   I2C_setSlaveAddress (基址、id);
   I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
   I2C_setDataCount (Base、5);
   I2C_sendStartCondition (Base);
   I2C_putData (Base、INV_P0);
   I2C_putData (Base、0);
   I2C_putData (Base、0);
   I2C_putData (Base、INOUT 和& 0x0F);
   I2C_putData (Base、(INOUT >> 8)&& 0x0F);
   I2C_sendStopCondition (基);
 }

这会发出数据。 但会在几次之后停止。 1每秒重新发送一次。

但经过几次后、总线会锁定。 TX 和 RX Fito 已满。

有人能否解释 FIFO 中存储的内容及其填充原因?

谢谢

EV

编辑:

总线锁定时的寄存器设置:

GRP( I2caRegs )    
   I2COAR   无符号/可读、可写   0x0000    
   I2CIER   无符号/可读、可写   0x0000    
   I2CSTR   无符号/可读、可写   0x1E28    
   I2CCLKL   无符号/可读、可写   0x0008    
   I2CCLKH   无符号/可读、可写   0x0007    
   I2CCNT   无符号/可读、可写   0x0005    
   I2CDRR   无符号/可读、可写   0x0004    
   I2CSAR   无符号/可读、可写   0x0080    
   I2CDXR   无符号/可读、可写   0x0000    
   I2CMDR   无符号/可读、可写   0x6E20    
   I2CISRC   无符号/可读、可写   0x0000    
   I2CEMDR   无符号/可读、可写   0x0001    
   I2CPSC   无符号/可读、可写   0x0013    
   I2CFFTX   无符号/可读、可写   0x7080    
   I2CFFRx   无符号/可读、可写   0x3080    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    EV、

    当 TXFFST = 16时、它会告诉您发送 FIFO 中有16个(8位数据)

    当 RXFFST = 16时、它会告知您已在接收 FIFO 中接收到16 (8位数据)

    查看 I2CSTR、可以发现您的 I2C 被其他一些 I2C 主设备作为从设备进行寻址。 您是否希望从其他 I2C 主设备接收一些数据? 这很可能是接收 FIFO 满的原因。 您是否在 FIFO 中断上读取 I2CDRR 寄存器16次? 这将清除 RX FIFO 缓冲区、以便接收下一个数据序列。

    此致、
    曼诺伊
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Manoj、

    感谢您的回复。

    我确信没有其他 i2c 主器件、数据来自 I2C 硬件内部。

    如果我将代码修改为:

    空 PCA9555D_Config (uint32_t Base、uint16_t id、uint16_t inout)


       I2C_setSlaveAddress (基址、id);
       I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
       I2C_setDataCount (Base、5);
       I2C_putData (Base、INV_P0);
       I2C_putData (Base、0);
       I2C_putData (Base、0);
       I2C_putData (Base、INOUT 和& 0x0F);
       I2C_putData (Base、(INOUT >> 8)&& 0x0F);
       I2C_sendStartCondition (Base);
       I2C_sendStopCondition (基);
       while (I2C_getRxFIFOStatus (Base)!= I2C_FIFO_RXEMPTY) I2C_getData (Base);
     }

    此 代码生成可重复的 i2c 消息。

    认为我在文档或示例中找不到:

    -我需要按什么顺序放置数据、启动、停止条件?

    -我假设 RX FIFO 数据是从发送数据中读回的信息。 我应该如何管理它? 我认为同步可能会有问题。

    如何按顺序发送多条 I2C 消息?  我是否必须等待先前的按摩完成(要检查哪一点?)  或者、我能否将其添加到 FIFO 中。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    EV、

    1) 1)我查看了您的 PCA9555D_Config 函数。 您使用的顺序正确。 此外、您无需单独设置开始位和停止位。 您可以将它们组合在一起。

    2) 2) RXFIFO 缓冲区正在填满、因为您正在从 I2C 总线接收数据。 如果您不希望出现这种情况。 检查是否已选择数字回路(您的 DLB 位是否已设置、I2CMDR.DLB = 1?)

    3) 3)如果要发送多条 I2C 消息、可以使用重复模式(I2CMDR.RM)和 FIFO。 当 TXFIFO 状态(TXFFST <= TXFFIL)时、您可以生成中断来重新填充 TXFIFO 以进行下一组传输。 完成发送所有消息后、发送 STOP 信号。

    此致、
    曼诺伊
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Manoj、

    感谢详细的解释。

    1) 1)正常

    2) 2)我添加 了 I2C_DisableLoopback (Base);在该处解决了问题。

    3) 3)这是否也适用于多个 I2C IC? 如何在 FIFO 中添加 I2C_setSlaveAddress 和 I2C_setDataCount?

    4) 4)我在读取 I2C 消息时仍然遇到问题:

    int16_t I2C_Read (uint32_t HWBase、uint16_t Slave_address、uint16_t ReG_address、uint16_t No_for_databytes、uint16_t Read_Array[])
    {uint16_t cnt;
       //检查是否仍有一条正在处理的 I2C 消息,表明另一个主设备处于活动状态
       如果((I2C_getStopConditionStatus (HWBase)!= 0)&&(I2C_isBusBusy (HWBase)!= 0))返回 I2C_STP_NOT _READY_ERROR;
       //发送请求
       I2C_setConfig          (HWBase、I2C_MASTER_SEND_MODE);
       I2C_setSlaveAddress    (HWBase、Slave_address);
       I2C_setDataCount       (HWBase、1);
       I2C_putData            (HWBase、ReG_address);
       I2C_setConfig          (HWBase、I2C_MDR_RM);
       I2C_sendStartCondition (HWBase);
       //读取响应
       I2C_setConfig          (HWBase、I2C_MASTER_Receive_MODE);
       I2C_setDataCount       (HWBase、NO_Of _databases);
       I2C_setSlaveAddress    (HWBase、Slave_address);
       I2C_sendStartCondition (HWBase);
       I2C_sendStopCondition  (HWBase);
       对于(cnnt=0;<No_of_databytes;cnt++)
       {
           while (I2C_getRxFIFOStatus (HWBase)=I2C_FIFO_RXEMPTY);
           Read_Array[cnt]= I2C_getData (HWBase);
       }
       返回 I2C_Success;

    编辑:新版本:问题是预期的响应不正确。 我看不到响应地址发出。


    但它不能按预期工作。 建议问题是什么?

    我是否首先使用 I2C_setConfig ( HWBase、I2C_MASTER_SEND_MODE)发送 Reg_address;并使用以下命令接收数据:   I2C_setConfig   (HWBase、I2C_MASTER_Receive_mode);?

    4) 4)处理 NACK。 是这样的

       if ((I2C_getStatus (HWBAse)&& I2C_STS_NO_ACK)!= 0)
               {
                   I2C_sendStopCondition  (HWBase);
                   I2C_clearStatus (HWBase、I2C_STS_NO_ACK);
                   
               }

    这会释放总线吗?

    感谢您的帮助!

    EV

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    EV、

    3)是的、F28377S I2C 支持总线中的多主 I2C。

       当 TX FIFO 被使能时、写入 I2CDXR 寄存器中的任何内容都会填充 FIFO。 I2C 从器件地址和 I2C 计数寄存器不 会填充到 FIFO 中。

    4) 4)这是我认为您应该做的事情

    //below 函数将执行以下操作:-

    1) 1)发送开始位

    2) 2)在 I2C 总线中发送从器件地址+写入位+从器件接收 ACK 位

    3) 3)在 I2C 总线中发送数据+从从器件接收 ACK 位+停止位(当 I2CCNT 递减至0时)

    I2C_setSlaveAddress  (HWBase、Slave_address);

    I2C_putData       (HWBase、DATA);

    I2C_setDataCount    (HWBase、1);

    I2C_setConfig      (HWBase、I2C_MASTER_SEND_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    //below 函数将执行以下操作:-

    1) 1)发送开始位

    2) 2)在 I2C 总线中发送从器件地址+读取位+从器件接收 ACK 位

    3) 3)在 I2C 总线中接收数据+从主器件接收 ACK 位+......... +停止位(当 I2CCNT 递减至0时)

    //您不能重新定义从地址,因为它已在上面配置

    I2C_setDataCount    (HWBase、NO_Of _databases);

    I2C_setConfig      (HWBase、I2C_MASTER_Receive_mode | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    5) 5)看起来正确。

    此致、

    曼诺伊

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Manoj、

    感谢详细的解释。

    我按照建议修改了我的代码:

    int16_t I2C_Read (uint32_t HWBase、uint16_t Slave_address、uint16_t ReG_address、uint16_t No_for_databytes、uint16_t Read_Array[])

    {uint16_t cnt;

      //检查是否仍有一条正在处理的 I2C 消息,表明另一个主设备处于活动状态

      如果((I2C_getStopConditionStatus (HWBase)!= 0)&&(I2C_isBusBusy (HWBase)!= 0))返回 I2C_STP_NOT _READY_ERROR;

      //发送请求

      I2C_setSlaveAddress  (HWBase、Slave_address);

      I2C_setDataCount    (HWBase、1);

      I2C_putData       (HWBase、Reg_address);

      I2C_setConfig      (HWBase、I2C_MASTER_SEND_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

      //读取响应

      I2C_setDataCount    (HWBase、NO_Of _databases);

      I2C_setConfig      (HWBase、I2C_MASTER_Receive_mode | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

      对于(cnnt=0;<No_of_databytes;cnt++)

      {

        while (I2C_getRxFIFOStatus (HWBase)=I2C_FIFO_RXEMPTY);

        Read_Array[cnt]= I2C_getData (HWBase);

      }

      返回 I2C_Success;

    但它仍然不起作用:

    我想,我需要发送:

    发送请求:

    I2C 地址 =>0x21 + R

    寄存器 ID  => 0

    响应:

    I2C 地址 => Ox2 + W

    数据字节1 =>从器件响应

    数据字节2 =>从器件响应

    这不是我得到的响应:

    我不能得到读操作在消息中看到响应 I2C 地址。 那么、这种情况在哪里消失了?

    谢谢、

     EV

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    EV、

    您的回复中不清楚哪些不起作用。 请清楚描述您的问题。 很难从波形中猜测问题。

    1) 1)主发送器传输是否正确放置了从地址、EEPROM 地址?

    2) 2)您是否完全遵循 PCA9555D 的读取命令格式?

    3)从图中、在从地址0x21之后、我会看到读取位(高位)和一些数据(0x0F)。 那么、确切地说、什么是不起作用的。

    4) 4)此外、您是否还在使用 RXFIFO?

    此致、

    曼诺伊

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Manoj、

    如果您对时钟脉冲进行计数、则数据计数不正确。 因此 F28377SS 不会发送所有 I2C 数据。
    因此、我在第一条消息和第二条消息之间等待来解决它。


    这是工作代码:
    int16_t I2C_Read (uint32_t HWBase、uint16_t Slave_address、uint16_t ReG_address、uint16_t No_for_databytes、uint16_t Read_Array[])
    {uint16_t cnt;
    //检查是否仍有一条正在处理的 I2C 消息,表明另一个主设备处于活动状态
    如果((I2C_getStopConditionStatus (HWBase)!= 0)&&(I2C_isBusBusy (HWBase)!= 0))返回 I2C_STP_NOT _READY_ERROR;
    //发送请求
    I2C_setSlaveAddress (HWBase、Slave_address);
    I2C_setDataCount (HWBase、1);
    I2C_putData (HWBase、Reg_address);
    I2C_setConfig (HWBase、I2C_MASTER_SEND_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    while (I2C_getStopConditionStatus (HWBase)!= 0);

    //读取响应
    I2C_setDataCount (HWBase、NO_NO_O_DATABytes);
    I2C_setConfig (HWBase、I2C_MASTER_Receive_mode | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    对于(cnnt=0;<No_of_databytes;cnt++)

    while (I2C_getRxFIFOStatus (HWBase)=I2C_FIFO_RXEMPTY);
    Read_Array[cnt]= I2C_getData (HWBase);

    返回 I2C_Success;


    等待任何其他控制位做好准备都不起作用。 下一条消息在上一条消息的基础上发送。 如上一篇文章中的示波器图片所示。 因此、在发送下一条消息之前、您必须等待前一条消息完成。
    如果您看到文档 SLVA704第7页、则会出现重复起始。 但我无法让它正常工作。 我甚至开始怀疑硬件是否可能实现。

    EV
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    EV、

    最好知道问题已解决。

    是的、您需要等待所有位传输、然后才能读回。 F28377D 的工作频率为200MHz、I2C 的工作频率以 KHz 为单位、要慢得多。 因此、要么等待您获得停止位(或)延迟、直到所有位在您读取前首先传输。

    根据论坛帖子、很明显我们可以在 I2C 示例中做得更好、我们在 TRM 中提供了一些说明。 感谢您的参与。 我们将在未来尝试解决这一问题。 我没有时间线、但我将在将来提交一个 TT 来解决此问题。

    我想我可以关闭这个帖子。 但是、请标记可解决您的问题的线程、以便其他存在类似问题的工程师受益。

    此致、
    曼诺伊