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.

[参考译文] RM46L852:使用 HalCoGen 构建一个非阻塞 i2c API 的建议。

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1335929/rm46l852-advice-for-building-a-non-blocking-i2c-api-using-halcogen

器件型号:RM46L852
主题中讨论的其他器件:HALCOGEN

我想以非阻塞的方式使用 I2C 主机外设(不是无限的 while 循环)。

为此、我需要学习如何使用具有中断的 TI HalCoGen I2C API。

遗憾的是、我没有找到任何示例:

- TI e2e 搜索功能未显示任何讨论此主题的结果

-正式文件不包含使用 HalCoGen 生成代码的示例

- HalCoGen 示例文件夹 有0提到 i2cNotification

所以我现在转到这个论坛:^)

——

我主要寻找有关如何处理待机问题的

- 如何在 i2cNotification 中正确处理 STOP ?

- 如何正确处理 i2cNotification 中的错误?

- 如何适当地等待总线做好准备,然后再做其他事情?

下面是我的代码:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static volatile bool g_rx_done = false;
static volatile bool g_tx_done = false;
int i2c_transmit(i2cBASE_t *base, //
uint8_t slave_address,
size_t data_size,
uint8_t const data[data_size])
{
if (i2cIsMasterReady(base) != true)
{
return -1; //< Busy
}
g_tx_done = false;
i2cSetSlaveAdd(base, slave_address);
i2cSetDirection(base, I2C_TRANSMITTER);
i2cSetMode(base, I2C_MASTER);
i2cSetCount(base, data_size);
i2cSetStop(base);
i2cSetStart(base);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

欢迎提供任何建议。

此致、
加布里埃尔

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

    尊敬的 Gabriel:

    我同意您的看法、即在 i2c 中没有经过良好测试的中断示例。

    我建议您参考以下两个可能在某种程度上对您有帮助的主题。

    (+) TMS570LC4357:I2C 总线示例代码-基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛

    (+) CCS/TMS570LS1227:I2C -与中断通信-基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛

    - 如何在 i2cNotification 中正确处理 stop?

    这取决于您的要求。

    例如、如果我想向从机发送一些 n 个字节、并想发送 STOP 条件、那么我们可以在设置 count 个字节后、在调用 i2csend 函数之前、按照您所做的那样设置 STOP 条件。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    i2cSetSlaveAdd(base, slave_address);
    i2cSetDirection(base, I2C_TRANSMITTER);
    i2cSetMode(base, I2C_MASTER);
    i2cSetCount(base, data_size);
    i2cSetStop(base);
    i2cSetStart(base);
    i2cSend(base, data_size, data);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    这种情况下发生的情况是、它将在中断模式下发送配置的字节数(如果我们启用)、然后它将自动发送停止条件。

    同样的收货程序。

    但是、在某些情况下、我们可能需要在不发送停止条件的情况下重新启动 i2c。

    例如、请参阅上文中的温度传感器读取方法、在这里、我们在两个传感器之间没有停止条件的情况下进行发送和读取。 在这些情况下、我们不应在配置字节数后发送停止条件。 而不是在完成发送字节后、我们应该再次设置起始条件并执行接收操作、然后我们可以发送停止条件。

    我想以非阻塞的方式使用 I2C 主设备外设(while 循环不是无限的)。

    尽管我们不想像轮询方法中的无限循环那样等待、但还是需要在 while (1)上构建状态机、以检查状态并执行下一个操作。

    例如、我为上述温度读数程序提供代码。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    int state =0;
    unsigned char Command_Byte = 0xAA;
    bool prev_cmd = false;
    unsigned char Temperature[2];
    int main(void)
    {
    i2cInit();
    while(1)
    {
    I2c_Temperature_Reading();
    /*Other Tasks*/
    }
    return 0;
    }
    void I2c_Temperature_Reading(void)
    {
    switch(state)
    {
    case 0:
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    如上面的示例所示、我们没有等到发送字节、而只是验证前一条命令是否成功执行。 那么我们要进行下一步操作。

    我希望这有助于您了解和实现中断模式下的 i2c。

    - 如何正确处理 i2cNotification 中的错误?

    这同样取决于您的应用要求。 例如、如您在我的共享代码中所见、如果有任何仲裁、我只是将重新启动温度读取程序。  

    --
    谢谢。此致、
    Jagadish。

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

     Jagadish、您好!

    感谢您的回答。

    如果我想向从机发送 n 个字节并想发送 STOP 条件,那么我们可以在设置 count 字节后和调用 i2csend 函数之前设置 stop 条件,就像您所做的那样。

    感谢您解释如何使用 i2cSetStop()函数。
    我仍然不确定如何处理 停止条件检测标志。


    在您的示例中、我看到您还在中断中清除了 SCD。 这总是一个好主意吗?
    如果通信中断、并且我们从未接收到 I2C_SCD_INT 中断、该怎么办? 我们如何从这种情况中恢复?

    Fullscreen
    1
    2
    3
    4
    if (flags & I2C_SCD_INT) //< Stop condition detect
    {
    i2cClearSCD(base);
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    例如、我为上述温度读数程序提供代码。

    [/报价]

    感谢您分享此代码。


    我看到、当您收到仲裁丢失(AL)时、您重置了状态机。
    为什么你不做同样的 NACK ?

      那么 ARDY 和 AAS 呢?
    我们应该如何处理它们?


    BTW、在您的状态机中、  

    Fullscreen
    1
    state =2;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    应该在 IF 条件内?

    此致、
    加布里埃尔

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

    我还有另一个问题要问  Jagadish。

    我不明白这些 API 之间的区别:

    Fullscreen
    1
    2
    3
    4
    bool i2cIsMasterReady(i2cBASE_t *i2c);
    bool i2cIsBusBusy(i2cBASE_t *i2c);
    uint32 i2cIsTxReady(i2cBASE_t *i2c);
    uint32 i2cIsRxReady(i2cBASE_t *i2c);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    它们之间有什么细微差别?

    这些轮询 API 与接收 I2C_TX_INT 或 I2C_RX_INT 中断之间有什么区别?

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

    尊敬的 Gabriel:

    这些轮询 API 与接收 I2C_TX_INT 或 I2C_RX_INT 中断之间有何区别?

    它们之间没有区别。 唯一需要注意的是、如果您正在以轮询方式开发代码、则必须使用这些 API。  

    例如、如下所示、突出显示的代码:

    在该轮询代码中、要向数据寄存器写入一个新字节、我们只是等待前一个字节通过轮询 I2C_TX_INT 标志来移位。 如果设置该标志、则意味着先前写入数据寄存器的数据值已移到移位寄存器中、我们可以向其中写入一个新值。 在此驱动程序直接验证 I2C_TX_INT 位、但我们也可以使用"i2cIsTxReady" API、而不是在此处。

    但如果是中断模式、我们无需轮询该位、而只需 在 IMR 寄存器中启用 I2C_TX_INT 中断标志。 如果我们这样做、如果数据寄存器值移动到移位寄存器、则我们会立即获得中断和控制权将转移到处理程序代码、因此我们可以向数据寄存器写入新值。

     I2C_RX_INT 和 i2cIsRxReady API 也具有类似的行为。

    i2cIsBusBusy -此 API 在轮询模式下也有助于识别已发送的所有字节或已接收的所有字节。 我的意思是、在发送起始条件后、该忙标志将被设置、在接收到停止条件后、它将被清除。

    因此、它可按以下方式使用:

    如您所见、在设置要传输的字节数并调用 i2cSend API 后、我们只需轮询 i2cby 标志以识别传输是否已完成。

    i2cIsMasterReady-每当生成停止条件时、这意味着一个事务完成、则第一个 BB (总线忙)标志将被清除、然后 MST 位也被清除。

    在开始新事务之前、必须清除该位、如果不清除该位、则我们不应开始新事务。

    每当我们开始新事务时、都需要添加此检查。 例如您可以看到上面的代码、对于第一次交易、我们没有使用此检查、但在开始第二次交易之前、我们将使用此检查来确保第一次交易是否完成。 也可以在代码的中断模式下使用此检查、在开始第二个事务之前的第一个事务之后、最好检查此条件。

    --
    谢谢。此致、
    Jagadish。

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

    Jagadish、您好!

    感谢您的回答。

    它使  i2cIsMasterReady 更清晰。

    您共享的这个 HalCoGen 代码具有一个有趣的含义。
    如果我发送的消息只有1个字节、则永远不会接收 I2C_TX_INT、这意味着 prev_cmd 将永远不会设置为 True。

    在不使用轮询的情况下、如何判断传输是否已完成、是否从未产生任何中断?

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

    此外、对于错误管理:

    当我发送格式错误的消息时、我收到一个 NACK。
    接收到 NACK 后、似乎无法从它中恢复:i2cIsMasterReady 函数始终返回 False。

    我们如何从这类错误中恢复总线?

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

    尊敬的 Gabriel:

    您共享的这个 HalCoGen 代码有一个有趣的含义。

    是的、回答正确。 存在错误、请参阅 QJ 的以下权变措施。

    (+) TMS570LS1115:I2C 中断不工作-基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛

    --
    谢谢。此致、
    Jagadish。

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

    尊敬的 Gabriel:

    当我发送格式错误的消息时,我收到一个 NACK。
    接收到 NACK 后、似乎无法从它中恢复:i2cIsMasterReady 函数始终返回 False。

    我们如何从这类错误中恢复总线?

    为什么不启用 NACK 中断、如果生成了该中断、则尝试重新启动通信。

    重启通信方式、首先发送一个停止条件、然后再发送启动和数据等。

    --

    谢谢。此致、
    Jagadish。

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

    是的、回答正确。 存在错误、请参阅 QJ 的以下权变措施。

    [/报价]

    这是非常有帮助的,谢谢!


    @我有与 μ suser5967417相同的问题:RX 中断可以工作、但 TX 中断不工作 。
    当我在函数库中放置一个断点时、  i2c 中断 函数 I 没有接收到任何 TXRDY 中断。

    以下是我的 HalCoGen I2C 配置:

    引脚多路复用器

    外设

    ISR

    你知道为什么我不会收到 TXRDY 吗?

    为什么不启用 NACK 中断、如果生成了该中断、则尝试重新启动通信。

    [/报价]

    有趣。 我今天将对此进行测试。

    感谢你的帮助。

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

    尊敬的 Gabriel:

    您有什么想法为什么我不会收到 TXRDY 吗?

    您连接到主 i2c 的从器件是什么?

    用于 i2c 线路的上拉电阻器值是什么?

    我能拿到您的整个项目进行验证吗?

    --

    谢谢。此致、
    Jagadish。

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

    Jagadish、您好!  

    您连接到主 i2c 的从器件是什么?

    [/报价]

    我已使用 SHT3x-DIS 和 PT7C4563进行了测试。

    用于 i2c 线路的上拉电阻器值是什么?

    [/报价]

    硬件已使用阻塞 i2c 代码进行验证。 这会是一个硬件问题、这对我来说是一个惊喜。

    我能拿到您的整个项目进行验证吗?

    [/报价]

    这是 halcogen 文件 https://pastebin.com/VCtxvySA

    此致、

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

    尊敬的 Gabriel:

    确保从器件向主器件发送 ACK。

    如果从器件不向主器件发送 ACK、则主器件不会向从器件发送任何数据。

    例如、如上文中所示 pic、主器件向从器件发送了0x08地址、但从器件不会向主器件发送任何 ACK、因此主器件不会向从器件发送任何其他数据。

    如果您在上面看到、pic 主器件会将0x4C 地址发送给从器件、而从器件提供 ACK 和主器件会进一步移动数据字节。 为了确保主从设备之间的通信正确无误、请从设备端确保完成以下操作。

    1.确保主器件 SDA 和 SCL 线路与从器件 SDA 和 SCL 线路正确连接。

    2.确保在 SDA 和 SCL 线上连接外部上拉电阻。 上拉不应过高或过小、最好在2.2K 到4.7K 之间。  

    (+) TMS570LS3137:I2C 无法正常工作-基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛

    3.确保从主设备发送正确的从设备地址。

    --
    谢谢。此致、
    Jagadish。

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

    Jagadish、您好!

    感谢您的反馈。  
    由于 i2c 传输运行良好、因此我认为它与硬件无关。

    我没有 验证从器件的 ACK、但由于我正确地从从从器件接收到多个字节、我似乎不太可能不会接收 NACK。

    您确定不可能是另外一个 HalCoGen 错误吗?  
    这个线程中、看起来即使对于经修改的代码、用户也无法接收 TX ISR。

    此致、

    加布里埃尔   

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

     如果你想,我可以创建一个单独的线程,因为我们正在输入一个新的主题: HalCodeGen TX ISR 问题。

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

    请创建新主题。 将所有内容合并到一个问题中可能并不好。

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

    好的、下面是新主题: e2e.ti.com/.../rm46l852-i2c-txrdy-interrupts-never-fire-while-the-rxrdy-works-fine