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:I2C 传递函数

Guru**** 2391415 points
Other Parts Discussed in Thread: TCA9555

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1240759/tm4c1292ncpdt-i2c-transfer-function

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

您好!

我的 I2C 传输代码中有一个问题。

在我的参考运行代码中、用于 I2C 传输的函数如下:

   I2C_Handle      i2c;
    I2C_Params      i2cParams;
    I2C_Transaction i2cTransaction;

    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2c = I2C_open(stI2cConfig->vui8I2cBus, &i2cParams);
    /*if (i2c == NULL) {
        IOC_DRIVER_ERR("Error Initializing I2C\n");
    }
    else {
        IOC_DEBUG_DRIVER("I2C Initialized!\n");
    }*/

    i2cTransaction.slaveAddress = stI2cConfig->vui8slaveAddress;
    i2cTransaction.writeBuf = stI2cConfig->pui8txbuffer;
    i2cTransaction.writeCount = stI2cConfig->vui8writeCount;
    i2cTransaction.readBuf = stI2cConfig->pui8RxBuffer;
    i2cTransaction.readCount = stI2cConfig->vui8readCount;

    /* Print the Data send through the I2C */
    if(I2C_transfer(i2c, &i2cTransaction))  {
    }
    else {
        IOC_DRIVER_ERR("I2C Bus fault\n");
    }

    /* De-initialized I2C */
    I2C_close(i2c);
    /*IOC_DEBUG_DRIVER("I2C closed!\n");
    IOC_DEBUG_DRIVER_FLUSH();*/
    stI2cConfig->pui8RxBuffer = i2cTransaction.readBuf;
   
    

I2C_Handle、I2C_Params、I2C_Transaction 均在 I2C.h 文件(在 tirtos..\products\tidrivers..\packages\ti\drivers\i2c.h 中)中定义

但是、当我尝试从微控制器运行它到 TCA9555时、我得到的是 I2C 信号(SCK 和 SDA)、但没有输出。

相反、如果我使用以下函数进行 I2C 传输:

void i2cTivaLibTransfer(I2cStructType *pI2cData)
{
    uint32_t ui32Index, ui32Count;
    I2CMasterEnable(pI2cData->ui32I2cBus);

    /*if true - 400Khz, False - 100Khz */
    I2CMasterInitExpClk(pI2cData->ui32I2cBus, 120000000, true);

    I2CMasterSlaveAddrSet(pI2cData->ui32I2cBus, pI2cData->i2cSlaveAddress,
                                                        false);
    I2CMasterBurstLengthSet(pI2cData->ui32I2cBus, pI2cData->ui32TxCount);

    I2CMasterControl(pI2cData->ui32I2cBus,
                                I2C_MASTER_CMD_FIFO_BURST_SEND_START);
    for(ui32Index = 0; ui32Index < pI2cData->ui32TxCount; ui32Index++)
    {

        I2CFIFODataPut(pI2cData->ui32I2cBus,
                                       *(pI2cData->pui8DataTx+ui32Index));
    }

    while(I2CMasterBusy(pI2cData->ui32I2cBus))
    {

    }
    ui32Count = I2CMasterErr(pI2cData->ui32I2cBus);
    if(ui32Count != I2C_MASTER_ERR_NONE)
    {
    }
}

我在 TCA9555上的输出正在正常实现。

但第一个代码在参考板中工作正常。

请注意、我将在调试模式下运行上述2个代码片段、第一个代码片段可能与 RTOS 有关、还是仅在自由运行/编程模式下工作?

此致、

Kiran

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

    在我的参考运行代码中、用于 I2C 传输的函数如下:

    全屏
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    I2C_Handle I2C;
    I2C_Params i2cParams;
    I2C_Transaction i2cTransaction
    /*创建 I2C 以供使用*/
    I2C_Params_init (&i2cParams)
    i2cParams.bitrate = I2C_400kHz
    I2C = I2C_open (stI2cConfig->vui8I2cBus&i2cParams)
    /*if (i2c == NULL){
    IoC_DRIVER_ERR ("Error Initializing I2C\n");
    否则{
    IoC_debug_driver ("I2C 已初始化!\n");
    }*/
    i2cTransaction.slaveAddress = stI2cConfig->vui8slaveAddress
    i2cTransactionwriteBuf = stI2cConfig->pu8txbuffer
    i2cTransaction.writeCount = stI2cConfig->vui8writeCount
    i2cTransaction.readBuf = stI2cConfig->pui8RxBuffer
    i2cTransaction.ReadCount = stI2cConfig->vui8readCount
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    I2C_Handle、I2C_Params、I2C_Transaction 均在 I2C.h 文件(在 tirtos..\products\tidrivers..\packages\ti\drivers\i2c.h 中)中定义

    但是、当我尝试从微控制器运行它到 TCA9555时、我得到的是 I2C 信号(SCK 和 SDA)、但没有输出。

    [/报价]

    -请说明这是在您的定制电路板还是参考电路板上运行。 您稍后说、 第一个代码在参考板上运行正常。 我对哪一种方法有效和哪一种方法无效感到困惑。  

    -您的参考板是否连接到  TCA9555 ?

    -你的意思是什么,你得到 I2C 信号( SCK 和 SDA ),而不是输出。 如果你运行你的第一个代码、并且看到 SCK 和 SDA、那么主器件工作。 如果从器件未返回数据或确认、则需要调查 I2C 器件。  

    -使用逻辑分析仪布置您的 I2C 总线波形。  

    相反、如果我使用以下函数进行 I2C 传输:

    全屏
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    I2CMasterBurstLengthSet (pI2cData->ui32I2cBus、pI2cData->ui32TxCount)
    I2CMasterControl (pI2cData->ui32I2cBus
    I2C_MASTER_CMD_FIFO_BURST_SEND_START)
    for (ui32Index = 0ui32Index < pI2cData->ui32TxCount;ui32Index++)
    {
    I2CFIFODataPut (pI2cData->ui32I2cBus
    *(pI2cData->pui8DataTx+ui32Index)
    while (I2CMasterBusy (pI2cData->ui32I2cBus)
    {
    ui32Count = I2CMasterErr (pI2cData->ui32I2cBus)
    if (ui32Count!= I2C_MASTER_ERR_NONE)
    {
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    我在 TCA9555上的输出正在正常实现。

    但第一个代码在参考板中工作正常。

    [/报价]

    -再说一次,第一个代码生成的波形与第二个代码生成的波形之间的差异是什么。 也许您的第一个代码与第二个代码具有不同的命令序列。  

    Unknown 说:
    请注意、我将在调试模式下运行上述2个代码片段、是否第一个代码片段可以与 RTOS 有任何关系、或者它只能在自由运行/编程模式下工作?
    [/quote]

    -你不是也在 RTOS 中运行第二个代码吗?  只是您使用 TivaWare I2C 驱动程序、而不是 TI-RTOS I2C 驱动程序。  

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

    尊敬的 Charles:

    请澄清此软件是在您的定制电路板还是参考电路板上运行。 您稍后说、 第一个代码在参考板上运行正常。 我对哪一种方法有效和哪一种方法无效感到困惑。  [/报价]

    TI-RTOS 函数(第一个代码)在我们的参考板(使用 RTOS)上运行、但第二个函数(Tivaware I2C)在我们的自定义板上运行。   

    -您的参考板是否连接到 TCA9555 ?

    是的、参考板和定制板都连接到 TCA955。

    -你的意思是什么,你得到 I2C 信号( SCK 和 SDA ),而不是输出。 如果你运行你的第一个代码、并且看到 SCK 和 SDA、那么主器件工作。 如果从器件未返回数据或确认、则需要调查 I2C 器件。  

    -使用逻辑分析仪布置您的 I2C 总线波形。  

    -再说一次,第一个代码生成的波形与第二个代码生成的波形之间的差异是什么。 也许您的第一个代码与第二个代码具有不同的命令序列。

    请查看下面针对我们定制电路板上 TI-RTOS (第一个代码)和 Tivaware Functions (第二个代码)的示波器捕获。

    TI-RTOS 功能(I2C)

    Tivaware 函数(I2C)

    在逐步调试时、我发现代码不会从下面的行继续执行:


    /*打印通过 I2C 发送的数据*/
    if (I2C_transfer (i2c、&i2cTransaction))  

    SPI 事务中也会出现类似的问题。 一种是用于 SPI 传输的 TI-RTOS 代码。 请参阅下面的

        uint32_t  i;
        SPI_Handle stSpiHandle;
        SPI_Params stSpiParams;
        SPI_Transaction stSpiTransaction;
    
        bool boTransferOK;
    
       // Semaphore_pend(Sem_spi_Handle, BIOS_WAIT_FOREVER);
        IOC_DEBUG_DRIVER("spi write\n");
        SPI_Params_init(&stSpiParams);
        stSpiParams.bitRate = 1500000;
        stSpiParams.frameFormat = SPI_POL0_PHA1;//SPI_POL0_PHA0;//
        stSpiParams.dataSize = 16;
    
        /* Initialize SPI handle as default master */
        stSpiHandle = SPI_open(stSpiConfig->vui8SpiBus, &stSpiParams);
        if (stSpiHandle == NULL) {
            IOC_DRIVER_ERR("Error initializing SPI\n");
            //Event_post(Event_Fault_Handler, Event_Id_00);
        }
        else {
            IOC_DEBUG_DRIVER("SPI initialized\n");
        }
    
        /* Initialize master SPI transaction structure */
        stSpiTransaction.count = stSpiConfig->vui8DataCount;
        stSpiTransaction.txBuf = stSpiConfig->pui8STxbuffer;
        stSpiTransaction.rxBuf = stSpiConfig->pui8SRxBuffer;
    
        if(stSpiConfig->vui8ChipSelect == 1)
        {
            GPIO_write(BOARD_PORTP_PIN1, LOW);
        }
        else
        {
            GPIO_write(BOARD_PORTF_PIN4, LOW);
        }
    
        /* Initiate SPI transfer */
        boTransferOK = SPI_transfer(stSpiHandle, &stSpiTransaction);
    
        if(boTransferOK) {
            if(stSpiConfig->vui8ChipSelect == 1)
            {
                GPIO_write(BOARD_PORTP_PIN1, HIGH);
            }
            else
            {
                GPIO_write(BOARD_PORTF_PIN4, HIGH);
            }
            for (i = 0; i < stSpiConfig->vui8DataCount; i++){
            /* Print contents of master transfer buffer */
    
                IOC_DEBUG_DRIVER("Send Data %d : %x\n", i+1,
                                         ((uint16_t *)stSpiTransaction.txBuf)[i]);
            }
        }
        else {
            IOC_DEBUG_DRIVER("Unsuccessful master SPI transfer");
          //  Event_post(Event_Fault_Handler, Event_Id_00);
    
        }
        IOC_DEBUG_DRIVER_FLUSH();
    
        for (i = 0; i < stSpiConfig->vui8DataCount; i++){
        /* Print contents of master transfer buffer */
    
            IOC_DEBUG_DRIVER("Received Data %d : %x\n", i+1,
                                     ((uint16_t *)stSpiTransaction.rxBuf)[i]);
        }
    
        /* Deinitialize SPI */
        SPI_close(stSpiHandle);

    另一种是用于 SPI 传输的 Tivaware 代码。

    请参见下方的。

    uint32_t ui32Index;
    
        SSIConfigSetExpClk(pspiData->ui32SpiBus, 120000000, SSI_FRF_MOTO_MODE_1,
                           SSI_MODE_MASTER, DO_SPI_PERIPHERAL_CLOCK, SPI_DATA_LENGTH);//
    
        /* Checks the SPI Rx FIFO is empty */
        while(SSIDataGetNonBlocking(pspiData->ui32SpiBus,pspiData->pui8DataRx+0))
        {
    
        }
    
       if(pspiData->ui8ChipSelect == 1)
         {
             GPIO_write(BOARD_PORTP_PIN1, LOW);
         }
         else
         {
             GPIO_write(BOARD_PORTF_PIN4, LOW);
         }
    
       for(ui32Index = 0; ui32Index < pspiData->ui32TransferCount; ui32Index++)
       {
    
           SSIDataPut(pspiData->ui32SpiBus, *(pspiData->pui8DataTx+ui32Index));
       }
    
       GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0x00);
       SSIEnable(pspiData->ui32SpiBus);
    
       while(SSIBusy(pspiData->ui32SpiBus))
       {
    
       }
       if(pspiData->ui8ChipSelect == 1)
       {
           GPIO_write(BOARD_PORTP_PIN1, HIGH);
       }
       else
       {
           GPIO_write(BOARD_PORTF_PIN4, HIGH);
       }
       GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, GPIO_PIN_2);
    
       for(ui32Index = 0; ui32Index < pspiData->ui32TransferCount; ui32Index++)
       {
    
           SSIDataGet(pspiData->ui32SpiBus, (pspiData->pui8DataRx+ui32Index));
    
           *(pspiData->pui8DataRx+ui32Index) &= 0x00FF;
    

    第一个代码片段可以在我的参考板上运行、而不能在我的自定义板上运行。 但第二个代码片段在我的自定义板上可以正常运行。

    微控制器连接到半桥驱动器 NCV7723 IC 并使用第二个代码正确提供输出。

    同样、在调试期间、问题出现在下一行、例如第一个代码片段

    /*启动 SPI 传输*/
    boTransferOK = SPI_TRANSMIT (stSpiHandle、&stSpiTransaction);

    -您是否也在 RTOS 中运行了第二个代码?  只是您使用 TivaWare I2C 驱动程序、而不是 TI-RTOS I2C 驱动程序。  [/报价]

    第二个代码在调试模式下运行、而不是在编程或自由运行模式下运行、因此这些代码不是实时代码。

    此致、

    Kiran

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    TI-RTOS 函数(第一个代码)在我们的参考板上运行(使用 RTOS)、但第二个函数(Tivaware I2C)在我们的定制板上工作。   [/报价]

    下表是否正确理解? 您可以填写问号吗?

      参考板 定制板
    TI-RTOS 功能(I2C) 工作 不工作
    TivaWare 函数(I2C) 工作

    请查看下面定制电路板上 TI-RTOS (第一个代码)和 Tivaware 函数(第二个代码)的示波器捕获。

    由于 TI-RTOS 代码在参考板上工作、因此应在同时运行 TI-RTOS 的情况下附加参考板与定制板的示波器捕获。  

    我还假设 TivaWare 函数可以在参考板上工作、对吗?

    我看到、在下面的代码中、您会注释掉第9-14行。 在调用 I2C_OPEN()时如何保证已经获取了句柄。 如果 i2c 为 NULL、则表示您尚未获取句柄。 如果没有句柄,如何保证 I2C_TRANSMIT()能够正常工作?  

    TI-RTOS 功能(I2C)

    [/报价]

    观察波形可以看到、它看起来是发送一个用于写入方向的地址字节和一个数据字节、然后停止。 如果要写入/读取寄存器、需要确保命令遵守从器件数据表中描述的预期命令序列。  

    您的 vui8writeCount、vui8readCount 是什么? 如果您要读取一个寄存器 、我认为您需要将  vui8writeCount 设置为1、将 vui8readCount 设置为1。 请参阅上面的 i2c 命令序列、其中它是 slave_addr (W)->Register_addr->slave_addr (R)->Data。

    我建议您从100k 速度开始、而不是从400k 速度开始。 一旦一切正常工作、就可以改回400K。  

      有关更多详细信息、请参阅 software-dl.ti.com/.../_i2_c_8h.html。  

    说实话、我认为 TivaWare 在 I2C 控制方面提供更好的灵活性。 根据我的经验、每个 I2C 器件可能与另一个 I2C 器件大不相同。 TivaWare 将提供比 TI-RTOS 驱动程序更好的自定义控制。  

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

    尊敬的 Charles:

    我看到在下面的代码中,您注释出了第9-14行。 在调用 I2C_OPEN()时如何保证已经获取了句柄。 如果 i2c 为 NULL、则表示您尚未获取句柄。 如果没有句柄,如何保证 I2C_TRANSMIT()能够正常工作?  [/报价]

    --即使在取消对以上行的注释(检查 I2C 是否为 NULL ),传输也没有成功进行。 代码到达 I2C_transfer()函数,但不到达下一行。

    您的 vui8writeCount、vui8readCount 是什么? 如果您要读取一个寄存器 、我认为您需要将 vui8writeCount 设置为1、将 vui8readCount 设置为1。

    我写的是 TCA9555的配置寄存器0x06 ,写入0xFF(低8位)和0x0F(高8位),所以写入计数是'3'(字节),在这种情况下读取计数是'0'。 请参阅下面的

    i2cConfigbus stI2cConfig;
        uint8_t aui8txBuffer[DI_INPUTREG_WRITECOUNT];
        uint8_t aui8rxBuffer[DI_INPUTREG_READCOUNT];
    
        /* Configuring IO expander port as input for digital input and
        * output for Source sink selection
        */
        stI2cConfig.ui8regaddr = 0x06;
        stI2cConfig.vui8slaveAddress =  DI_SLAVEADDRESS;
        stI2cConfig.vui8I2cBus = Board_I2C9;
        aui8txBuffer[0] = 0x06;
        aui8txBuffer[1] = 0xFF;
        aui8txBuffer[2] = 0x0F;
        stI2cConfig.pui8txbuffer = aui8txBuffer;
        stI2cConfig.pui8RxBuffer = aui8rxBuffer;
        stI2cConfig.vui8writeCount = 3;
        stI2cConfig.vui8readCount = 0;
        ioc_DII2CTransfer(&stI2cConfig);

    这个代码在参考板上工作、Tivaware 函数也在参考板以及定制板上工作。 但用于 I2C 传输的 RTOS 功能在定制板上不起作用。

    您能否指导它为什么不起作用?

    此致、

    Kiran

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    此代码在参考板中可用,Tivaware 函数也在参考板和定制板中可用。 但用于 I2C 传输的 RTOS 功能在自定义板上不起作用。

    那么、结果如下、对吧?

      参考板 定制板
    TI-RTOS 功能(I2C) 工作 不工作
    TivaWare 函数(I2C) 工作 工作

    --我要向 TCA9555的配置寄存器0x06写入0xFF (用于低8位)和0x0F (用于高8位),因此写入计数为"3"(字节),在本例中,读取计数为"0"。 查看以下[/报价]

    我没有看到问题。  

    您能指导为什么它不起作用吗?

    如果同样的代码可在您的参考板上运行、那么我认为它也可在用户板上运行。   您为什么不展示此参考板的波形、因为它可以为您效劳。 参考电路板波形与您的定制电路板相比如何?  

    对于调试、我强烈建议您从100k 速度而不是400k 速度开始。 一旦您解析了100k、那么您可以更改为400k。  

    您使用的上拉电阻值是多少? 在您的定制板中有 ACK 位(见下文)、该位可能会被主器件误解为 NACK。 您能否查看 I2C 寄存器以及是否遇到任何错误?

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

    尊敬的 Charles:

    老实说、我认为 TivaWare 在 I2C 控制方面提供了更好的灵活性。 根据我的经验、每个 I2C 器件可能与另一个 I2C 器件大不相同。 TivaWare 将提供比 TI-RTOS 驱动程序更好的自定义控制。  [/报价]

    针对以上陈述的唯一一个疑问、即有可能将 TivaWare 中写入 TI-RTOS 驱动程序的代码转换成秘密代码? 在执行此操作之前、我需要注意的任何事项。

    请建议!!

    谢谢。

    Kiran

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

    请参考下图。 您可以看到、TI-RTOS 有一个 依赖于特定于器件的 driverlib 的驱动程序接口。 用于 Tiva 的 TI-RTOS 将使用 TivaWare driverlib。 对于 MSP430或 C2000等其它 MCU、将使用它们各自的 driverlib。 TI-RTOS 驱动程序在所有 TI 产品中提供同构接口、无论您使用的是哪种 MCU/MPU。 但是、硬件模块的实现会有所不同。 例如、TM4C129 I2C 模块与 C2000在功能上可能有很大不同。 在这种情况下、TI-RTOS I2C 驱动程序可能无法考虑每个 I2C 模块的所有独特功能。 TI-RTOS I2C 驱动程序很可能会为所有 MCU/MPU 提供通用的功能集。 另一点是可能的勘误表。 TI-RTOS 安装程序中使用的 TivaWare 版本比最新的 TivaWare 版本旧。 可能有 TivaWare driverlib 问题在最新版本中已修复、但在旧版本中未修复。 最后、在使用 TivaWare 时、可能存在勘误表、说明我们有软件权变措施。 但是、在 TI-RTOS 驱动程序中实现相同的权变措施将不会如此简单。 这就是我提到 TivaWare 会更灵活的原因。 话虽如此、如果您已根据您的应用要求实现了 TI-RTOS 驱动程序、并且它正在工作、那么我们没有理由放弃它。  

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

    尊敬的 Charles:

    感谢您的答复。

    检查后、我将在参考板上分享示波器捕获、并在定制板上分享10万个。

    您能否使用 TI-RTOS 驱动程序库共享 I2C 通信的示例代码?

    谢谢。

    Kiran