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.

[参考译文] TM4C1292NCPDT:无法向 TCA9555PWR 发送多个 I2C 数据

Guru**** 2387830 points
Other Parts Discussed in Thread: TM4C1292NCPDT, TCA6416, TCA9555
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1193423/tm4c1292ncpdt-unable-to-send-multiple-i2c-data-to-tca9555pwr

器件型号:TM4C1292NCPDT
主题中讨论的其他器件: TM4C123TCA6416TCA9555

您好!

在原理图中、我通过 I2C 时钟和数据线、SCL 和 SDA 将 TM4C1292NCPDT 连接到 IO 扩展器 IC TCA9555PWR。  

我正在尝试运行以下代码、所有3个地址行均为高电平、这意味着地址为0x27:

#include

#include

#include

#include "inc/hw_i2c.h"

#include "inc/hw_memmap.h"

#include "inc/hw_types.h"

#include "inc/hw_gpio.h"

#include "driverlib/i2c.h"

#include "driverlib/sysctl.h"

#include "driverlib/gpio.h"

#include "driverlib/pin_map.h"

#include "XDC/std.h"

#include

uint32_t g_ui32SysClock;

bool bDiInitialized = false;

 

#define DI_SLAVEADDRESS         0x27

 

//初始化 I2C 模块0

InitI2C0 ()

  //启用 I2C 模块0

   SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);

   //复位模块

   SysCtlPeripheralReset (SYSCTL_Periph_I2C0);

 

   //启用包含 I2C 0的 GPIO 外设

   SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);

 

   //为端口 B2和 B3上的 I2C0功能配置引脚复用。

   GPIOPinConfigure (GPIO_PB2_I2C0SCL);

   GPIOPinConfigure (GPIO_PB3_I2C0SDA);

 

   //为这些引脚选择 I2C 功能。

   GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);

   GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);

 

   //启用和初始化 I2C0主机模块。  使用 I2C0模块的系统时钟。  最后一个参数设置 I2C 数据传输速率。

   //如果为 false,则数据速率设置为100kbps,如果为 true,则数据速率 将设置为400kbps。

   //I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、TRUE);//对于400kbps tm4c123

   I2CMasterInitExpClk (I2C0_BASE、 SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、120000000)、true);//对于400kbps tm4c129

 

   //清除 I2C FIFO

   //HWREG (I2C0_BASE + I2C_O_FIFOCTL)= 80008000;

 

//I2C 发送功能

//向指定的从设备发送 I2C 命令

void I2CSend (uint8_t slave_addr、uint8_t num_for_args、...)

   uint8_t i;

   //告诉主模块何时将在总线上放置什么地址

   //与从设备通信。

   I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、false);

 

   //存储变量数量的参数列表

   va_list vargs;

 

   //将 va_list 指定为"open"和最后一个固定参数 ,以便 vargs 知道从何处开始查找

   va_start (vargs、num_of _args);

 

   //将要发送的数据放入 FIFO 中

   I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));

   //如果只有一个参数,我们只需要使用 单个发送 I2C 函数

   if (num_of _args == 1)

   {

       //从 MCU 发起数据发送

       I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);

       //等待 MCU 完成传输。

       while (!(I2CMasterBusy (I2C0_BASE)));

       while (I2CMasterBusy (I2C0_BASE));

       //"close"变量参数列表

       va_end (vargs);

   }

   //否则,我们开始在  I2C 总线上传输多个字节

   其他

   {

       //从 MCU 发起数据发送

       I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);

       //等待 MCU 完成传输。

       while (!(I2CMasterBusy (I2C0_BASE)));

       while (I2CMasterBusy (I2C0_BASE));

       //send num_of _args-2数据片段、使用

       ///burse_send_contt 命令的 I2C 模块

       for (i = 1;i <(num_of _args - 1);i++)

       {   //将下一段数据放入 I2C FIFO 中

           I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));

           //发送刚刚放置到 FIFO 中的下一个数据

           I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);

           //等待 MCU 完成传输。

           while (!(I2CMasterBusy (I2C0_BASE)));

           while (I2CMasterBusy (I2C0_BASE));

       }

       //将最后一段数据放入 I2C FIFO 中

       I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));

       //发送刚刚放置到 FIFO 中的下一个数据

       I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);

       //等待 MCU 完成传输。

       while (!(I2CMasterBusy (I2C0_BASE)));

       while (I2CMasterBusy (I2C0_BASE));

       //"Close"变量 args 列表

       va_end (vargs);

   }  

//通过 I2C 向指定的从设备发送一组数据

I2CSendString (uint32_t slave_addr、char array [])

{    //告诉主模块 在与从器件通信时它将在总线上放置什么地址。

   I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、false);

    //将要发送的数据放入 FIFO 中

   I2CMasterDataPut (I2C0_BASE、array[0]);

    //如果只有一个参数,我们只需要使用

   //单发送 I2C 函数

   if (array[1]='\0')

   {

       //从 MCU 发起数据发送

       I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);

 

       //等待 MCU 完成传输。

       while (!(I2CMasterBusy (I2C0_BASE)));

       while (I2CMasterBusy (I2C0_BASE));

   }

    //否则,我们开始在  I2C 总线上传输多个字节

   其他

   {        //启动从 MCU 发送数据

       I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);

        //等待 MCU 完成传输。

       while (!(I2CMasterBusy (I2C0_BASE)));

       while (I2CMasterBusy (I2C0_BASE));

        //将索引初始化为数组

       uint8_t i = 1;

        //send num_of _args-2数据片段、使用

       ///burse_send_contt 命令的 I2C 模块

       while (array[i + 1]!='\0')

       {        //将下一段数据放入 I2C FIFO 中

           I2CMasterDataPut (I2C0_BASE、array[i++]);

            //发送刚刚放置到 FIFO 中的下一个数据

           I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);

            //等待 MCU 完成传输。

           while (!(I2CMasterBusy (I2C0_BASE)));

           while (I2CMasterBusy (I2C0_BASE));

       }

        //将最后一段数据放入 I2C FIFO 中

       I2CMasterDataPut (I2C0_BASE、array[i]);

        //发送刚刚放置到 FIFO 中的下一个数据

       I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);

        //等待 MCU 完成传输。

       while (!(I2CMasterBusy (I2C0_BASE)));

       while (I2CMasterBusy (I2C0_BASE));

   }   

 //I2C 接收功能

//读取从器件上的指定寄存器

uint32_t I2CReceive (uint32_t SLAVE_addr、uint8_t reg)

   //specify that we are writing (a register address) to the (指定我们正在写入(寄存器地址))

   //从器件

   I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、false);

   //指定要读取的寄存器

   I2CMasterDataPut (I2C0_BASE、reg);

   //将控制字节和寄存器地址字节发送到从器件

   I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);

   //等待 MCU 完成事务

   while (I2CMasterBusy (I2C0_BASE));

   //指定我们将从从从器件读取

   I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、TRUE);

   //发送控制字节并从我们 指定的寄存器中读取

   I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_Receive);

   //等待 MCU 完成事务

   while (!(I2CMasterBusy (I2C0_BASE)));

   while (I2CMasterBusy (I2C0_BASE));

   //返回从指定寄存器提取的数据

   返回 I2CMasterDataGet (I2C0_BASE);

}  

void main (void)

{    //将时钟设置为直接从外部晶振/振荡器运行。

  G_ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |

                                      SYSCTL_OSC_MAIN |

                                      SYSCTL_USE_PLL |

                                      SYSCTL_CFG_VCO_480)、120000000);

  //初始化 I2C 模块0

 InitI2C0();

 I2CSend (DI_SLAVEADDRESS、3、0、0、0x01);

 I2CSend (DI_SLAVEADDRESS、3、0x06、0x01、0);//配置端口0

   while (1){};

 但是从示波器捕获中可以看到、只有一个 I2C 发送命令看起来工作正常、而不是多个。

 

 请提供相同的指南。

此致、

Kiranjit

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

    您好!

     请查看您的示波器、在这里我圈出 ACK/NACK 位。 SCL 显示将0x27作为从器件地址输出、后跟等于0的 R/W 位、这是写入从器件的命令。 但是、像从器件这样的 lLooks 不会向主器件返回 ACK、因此 SCL 在 ACK/NACK 阶段被拉高。 当从器件接收到主器件发出的命令时、您需要调查从器件为什么不驱动 ACK。 当主器件没有从从器件获取 ACK 时、它无法继续。 您可以检查 I2CMCS 寄存器中的 DATACK 和 ERROR 位、我认为它们设置为高电平。  

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

    您好、Charles、

    我在 CCS 的调试模式中检查了状态寄存器 I2C0MCS。 DATACK 和 ERROR 位设置为低电平。

    示波器捕获有时会显示以下图像:

    谢谢、

    Kiran

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

    您好 Kiran、

     ACK 位为半高。 您有什么上拉电阻器? 当从器件尝试将其驱动为低电平时、似乎几乎无法克服上拉。 您是否有任何示波器电容器表明 ACK 处于低电平?

     您可以调用  I2CEND (DI_SLAVEADDRESS、0、0、0、0x01)、以便只 向从器件写入一个字吗? 我想看看 示波器上是如何显示一个简单的单字写入的。  

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

    您好、Charles、

    所使用的上拉电阻器各为2K。 没有示波器捕获显示 ACK 为低电平。

    因此、我这次只使用了一个 I2C 写入到从器件、正如您所建议的那样、即  I2CEND (DI_SLAVEADDRESS、 0、0、0、0x01) 、但范围捕获保持不变。

    原因可能是什么?

    请提供指导。

    此致、

    Kiran

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

    您好!

    此外、我尝试了函数 I2CEND (DI_SLAVEADDRESS、 1、0、0、0x01) 来发送一个位、示波器捕获如下所示

    此致、

    Kiran

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

    您好!

     很抱歉、我真的不知道问题是什么。   

     您可以在 LaunchPad 上尝试一下吗? 请显示将 LaunchPad 连接到 IO 扩展器时的波形。  

     -您是否有其他可尝试的定制板? 您可以在不同的电路板上复制吗?

     您能否尽量简化您的示例? 也许、首先参考 C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl-bootstxl-senshub\humid_sht21_simple 的简单示例。  

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

    您好!

    要在中运行示例代码、我需要首先了解此示例、我不知道应该在哪里提供 IO 扩展器 IC 的地址?

    此外、我将使用 ADUM3151隔离器和 IO 扩展器 EVM 的 Launchpad 和 EV 电路板进行测试(设置如下所示)。 我将 通过隔离器提供从 Launchpad 到 IO 扩展器 EVM 的 I2C SCL、SDA 信号。

    对于 IO 扩展器、我将从器件地址用作0x27 (原理图的屏幕截图、如下所示)、因为 电动汽车电路板中的所有三条地址线(引脚2、3、21)都被上拉(我们已更换 IC TCA6416并将评估板中的 TCA9555PWR 焊接)。

    如果您有任何建议、请 告诉我。

    此致、

    Kiran

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

    您好!

     我看一下您之前的示波器电容器之一、您会看到。 请参见下面的。 在该上限中、从器件不回复 ACK。 如您所见、在没有 ACK 的情况下、主器件终止。 我不熟悉 TCA9555器件。 您需要咨询  TCA9555 论坛支持、以便他们能够帮助您更好地进行调试。 不知怎么说 、TCA9555 不会将0x27识别为地址。  

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

    您好、Charles、

    感谢你的帮助。 我将在 TCA9555论坛上发帖。

    此致、

    Kiran

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

    您好、Charles、

    为了处理 SDA 和 SCL 之间的同步、我需要在代码中做什么修改、即设置时间、保持时间和启动/停止条件?

    谢谢、

    Kiran

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

    接口论坛中的主题: 无法向 TCA9555PWR 发送多个 I2C 数据 、但据我所见、问题不是由 TCA9555引起的。

    捕获的 SDA 波形在上升沿显示过冲、这表示 SDA 引脚未配置为开漏、而是配置为推挽。 这意味着对 GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3)的调用不起作用、或在以后被覆盖。

    (我对 TM4C 一无所知;如何回读并检查 GPIO 配置?)

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

    您好!

     您无需在代码中注意 SDA 和 SCL 之间的同步。 它应该由硬件处理。 您能否以100kHz 的频率运行 I2C? 我想看看位时序与400kHz 相比是如何运行的。

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

    您好、Charles、

    我在代码中进行了以下更改。

    在2k 和4k7上拉的情况下、请参阅100kHz 和400kHz 的示波器捕获。

    100kHz (2K 上拉)

    400kHz (2k 上拉)

    100kHz (4k7上拉)

    400kHz (4k7上拉)

    请提供您的建议。

    此致、

    Kiranjit

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

    您好!

     我不知道如何自行解决这个问题。 通常情况下、我将期望较低的上拉电阻用于较高的 I2C 波特率。 但是、在示波器上、400kHz 时的4k7波形比2k 更好。 无论使用哪种电阻器、在100kHz 和400kHz 下、NACK 似乎仍然存在问题。 您是否有其他 LaunchPad 可供尝试? 您能重复同样的操作吗?

       还会给您一个抬头显示。 我将在下周三休假、我的回复将延迟。