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.

[参考译文] TM4C1294NCPDT:TM4C129重复启动条件和 TI-RTOS 驱动程序

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/975137/tm4c1294ncpdt-tm4c129-repeated-start-condition-and-ti-rtos-driver

器件型号:TM4C1294NCPDT

有人知道 TI-RTOS 中的 I2C 驱动程序库是否与需要重复启动条件的芯片配合使用? 我尝试与一个 RTC 芯片通信、但它需要重复启动条件。  

此致、

Bob Starr

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

    我相信答案是肯定的。 Tiva TI-RTOS I2C 驱动程序源位于以下文件中:  C:\ti_tirtos_tivac_2_16_00_08\products\tidrivers_tivac_2_16_00_08\packages/ti\drivers\i2c\I2CTiva.c

     如果写入后需要读取、处理程序会调用函数 I2CTiva_hwiFxn()来发送停止条件或附加的启动条件。 查看210到321行:

    案例 I2CTiva_write_mode:
    /*减量写入计数器*/
    object->writeCountIdx-;
    
    /*检查是否需要发送更多数据*/
    if (object->writeCountIdx){
    Log_print3 (Diags_User2、
    "I2C:(%p) ISR I2CTiva_write_mode:要写入的数据:"
    "0x%x;到从器件:0x%x"、
    hwAttrs->baseAddr,
    *(object->writeBufIdx)、
    object->currentTransaction->slaveAddress);
    
    /*将数据内容写入数据寄存器*/
    I2CMasterDataPuthwAttrs->baseAddr、*(object->writeBufIdx);
    object->writeBufIdx++;
    
    if ((object->writeCountIdx < 2)&&!(object->readCountIdx)){
    //所有内容都已发送,没有要接收的内容*/
    /*下一状态:空闲模式*/
    object->mode = I2CTiva_idle_mode;
    
    /*发送带停止位的最后一个字节*/
    I2CMasterControlhwAttrs->baseAddr、
    I2C_MASTER_CMD_BURST_SEND_FINISH);
    
    Log_Print1 (Diags_User2、
    "I2C:(%p) ISR I2CTiva_write_mode:ACK received;"
    "写入带停止位"、
    hwAttrs->baseAddr);
    }
    否则{
    /*
    *有更多的发送日期或某些日期
    *接下来需要接收数据
    *
    I2CMasterControlhwAttrs->baseAddr、
    I2C_MASTER_CMD_BURST_SEND_CONT);
    
    Log_Print1 (Diags_User2、
    "I2C:(%p) ISR I2CTiva_write_mode:ACK received;"
    "写入"、
    hwAttrs->baseAddr);
    }
    }
    
    /*此时,我们知道我们需要接收数据*/
    否则{
    /*
    *我们需要在传输完数据后进行检查,如果
    *我们需要接收任何数据。
    *在临界情况下、当我们仅传输一个字节时
    *且没有要接收的数据、I2C 将自动发送
    *停止位。 换言之、我们只需要检查一下
    *是否需要接收数据。 如果是、则为多少。
    *
    if (object->readCountIdx){
    /*下一状态:接收模式*/
    object->mode = I2CTiva_read_mode;
    
    /*切换到接收模式*/
    I2CMasterSlaveAddrSet (hwAttrs->baseAddr、
    object->currentTransaction ->slaveAddress、
    true);
    
    if (object->readCountIdx >1){
    /*发送重复开始*/
    I2CMasterControlhwAttrs->baseAddr、
    I2C_MASTER_CMD_BURST_Receive_start);
    
    Log_Print1 (Diags_User2、
    "I2C:(%p) ISR I2CTiva_write_mode:->"
    "I2CTIVA_READ_MODE;通过重新启动和 ACK 进行读取"、
    hwAttrs->baseAddr);
    }
    否则{
    /*
    *发送带有 NACK 的重复起始值、因为它是
    *要接收的最后一个字节。
    * I2C_MASTER_CMD_BURST_Receive_START_NACK 为
    *是局部定义的、因为没有宏
    *在发送后接收数据并发送 NACK
    *起始位(0x00000003)
    *
    I2CMasterControlhwAttrs->baseAddr、
    I2C_MASTER_CMD_BURST_Receive_START_NACK);
    
    Log_Print1 (Diags_User2、
    "I2C:(%p) ISR I2CTiva_write_mode:->"
    "I2CTIVA_READ_MODE;通过重新启动和 NACK 读取数据"、
    hwAttrs->baseAddr);
    }
    }
    否则{
    /*完成所有传输*/
    object->mode = I2CTiva_idle_mode;
    /*
    *无需再接收数据、因此请继续执行
    *停止位
    *同样、没有等效宏(0x00000004)
    *使用 I2C_MASTER_CMD_BURST_Receive_stop。
    *
    I2CMasterControlhwAttrs->baseAddr、
    I2C_MASTER_CMD_BURST_Receive_STOP);
    
    Log_Print1 (Diags_User2、
    "I2C:(%p) ISR I2CTiva_write_mode:->"
    "I2CTIVA_IDLE_MODE;发送停止位"、
    hwAttrs->baseAddr);
    }
    }
    中断;
    

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

    非常感谢您的回复、我不是 I2C 专家、使用此总线的经验有限。 是的、它看起来应该支持重复启动条件。 我很难理解如何从 RTC 时钟芯片和 RTC 器件的新功能中进行简单的寄存器读取。 我正在尝试从 MCP79410器件读取单个寄存器以检查运行状态。

    我正在尝试写入命令字节并读回一个字节。 我不知道在写入读取寄存器命令和回读结果字节之间是否存在停止/启动条件。 似乎部件希望在写入/读取操作之间重复启动。 驱动程序中断在下面的部分给出了一个错误。

    /*发生了某种错误! *
    object->mode = I2CTiva_error;
    
    if (errStatus &(I2C_MASTER_ERR_ARB_Lost | I2C_MASTER_ERR_ADDR_ACK){
    I2CTiva_completeTransfer ((I2C_Handle)参数);
    }
    

    #define RTCC 写入 0xDE // RTCC MCHP 的设备 ADDR (写入)
    #define RTCC 读取 0xDF // RTCC MCHP 的设备 ADDR (读取)
    
    uint8_t MCP79410_read (MCP79410_Handle handle、uint8_t RCCD_reg)
    {
    //IArg 键;
    I2C_Transaction i2cTransaction;
    uint8_t txBuffer[2];
    uint8_t rxBuffer[2];
    
    txBuffer[0]= RTCC_reg;
    
    /*用地址*/写入虚拟字节
    i2cTransaction.slaveAddress = RTCC 写入;
    i2cTransaction.writeBuf =&txBuffer;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf =&rxBuffer;
    i2cTransaction.ReadCount = 0;
    
    if (!I2C_transfer (handle->i2cHandle、&i2cTransaction))
    {
    system_printf ("unsuccessful I2C transfer\n");
    system_flush();
    }
    
    txBuffer[0]= RTCC_reg;
    
    /*初始化主 SPI 事务结构*/
    i2cTransaction.slaveAddress = RTCC 读取;
    i2cTransaction.writeBuf =&txBuffer;
    i2cTransaction.writeCount = 0;
    i2cTransaction.readBuf =&rxBuffer;
    i2cTransaction.ReadCount = 1;
    
    if (!I2C_transfer (handle->i2cHandle、&i2cTransaction))
    {
    system_printf ("unsuccessful I2C transfer\n");
    system_flush();
    }
    
    返回 rxBuffer[0];
    } 

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

    这是 RTC 芯片希望在重复启动条件下看到的内容。  

    我不确定如何使用 I2C 驱动程序 I2C_Transaction API 实现这一点。 这甚至可以通过 I2C 驱动器接口实现吗? 在写入控制字节和地址后、似乎需要在某个位置设置一个特殊的标志来告诉它不要发送停止条件。 在我看来、这甚至无法通过 TI-RTOS I2C API 实现?

    此致、

    Bob Starr

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

    还使用"链接读取"运行了另一个示例、但迄今为止也不能成功执行此操作。

    bool transferDone = false;
    
    void I2C3writeCallback (I2C_Handle handle、I2C_Transaction *事务、bool 结果)
    {
    //设置长度字节
    if (结果){
    transferDone =真;
    } 否则{
    //事务失败,相应地执行...
    system_printf ("unsuccessful I2C transfer\n");
    system_flush();
    }
    }
    
    uint8_t MCP79410_read (MCP79410_handle、uint8_t regadd)
    {
    I2C_Transaction i2cTrans1;
    I2C_Transaction i2cTrans2;
    uint8_t txBuffer1[2];
    uint8_t rxBuffer1[2];
    uint8_t txBuffer2[2];
    uint8_t rxBuffer2[2];
    
    txBuffer1[0]= regadd;
    
    //初始化第一个主 I2C 事务结构
    i2cTrans1.slaveAddress = RTCC 写入; // 0xDE
    i2cTrans1.writeCount = 1;
    i2cTrans1.writeBuf = txBuffer1;
    i2cTrans1.ReadCount = 0;
    i2cTrans1.readBuf = rxBuffer1;
    
    txBuffer2[0]= regadd;
    
    //第二次交易
    i2cTrans2.slaveAddress = RTCC 读取; // 0xDF
    i2cTrans2.writeCount = 0;
    i2cTrans2.writeBuf = txBuffer2;
    i2cTrans2.ReadCount = 1;
    i2cTrans2.readBuf = rxBuffer2;
    
    //执行链接 I2C 传输(在回调模式下)。
    i2C_transfer (handle->i2cHandle、&i2cTrans1);
    i2C_transfer (handle->i2cHandle、&i2cTrans2);
    
    //在 I2C 处理传输时执行其他操作
    
    //如果 I2C 传输完成,请执行一些操作
    
    Task_sleep (1000);
    
    if (转让人){
    
    }
    //继续...
    
    返回 rxBuffer2[0];
    }
    

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

    您需要对 I2C_transfer 进行一次调用、写入计数为1、读取计数为1。 您只需要使用7位来设置从器件地址。 最后一个读/写位由驱动程序添加。 例如、RTCC 地址为0x6f、而不是0xDE 和0xDF。

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

    尊敬的 Bob:

    非常感谢!! 最后、让这个烦人的部件正常工作! 我的 GOof、我按照以下内容更改了地址宏。

    #define RTCC 写入(0xDE >> 1)// RTCC MCHP 的设备 ADDR (写入)
    #define RTCC 读取(0xDF >> 1)// RTCC MCHP 的设备 ADDR (读取)

    最初、我编写和读取了一个字节的代码、但无法理解为什么它不起作用。

    由于我自己的监督、我忘记了解决位移问题的所有事情。 非常感谢您的帮助!

    此致、