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.

[参考译文] MSPM0G3507:u8g2库的 I2C 移植

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1351902/mspm0g3507-i2c-porting-for-u8g2-library

器件型号:MSPM0G3507

您好!  

对于使用 i2c 硬件连接的 MSPM0G 系列 MCU、是否有 u8g2库的移植示例?  

我想知道 I2C 字节发送 回调的 HAL 是什么样子、因为其 HW i2c 只能支持8个 FIFO。 如何拆分并实现到该回调函数中?

仅供参考、下面是为 Arduino I2C 提供的样片。

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
uint8_t u8x8_byte_arduino_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
Wire.write((uint8_t *)arg_ptr, (int)arg_int);
break;
case U8X8_MSG_BYTE_INIT:
Wire.begin();
break;
case U8X8_MSG_BYTE_SET_DC:
break;
case U8X8_MSG_BYTE_START_TRANSFER:
if ( u8x8->display_info->i2c_bus_clock_100kHz >= 4 )
{
Wire.setClock(400000L);
}
Wire.beginTransmission(u8x8_GetI2CAddress(u8x8)>>1);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
Wire.endTransmission();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

    您好、 

    否。

    其 HW i2c 只能支持8个 FIFO。

    对于 FIFO 的使用、您可以参考相同的 SDK 演示。 另一个需要确认的是在 syscfg 中配置 Tx FIFO 触发电平、如下所示:

    对于数据长度超过8个字节的情况、您可以调用此 API 来等待 TX FIFO 清空并使用新数据来填充:

    Fullscreen
    1
    DL_I2C_isControllerTXFIFOEmpty(I2C_INST);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    此致、

    赫利克

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

    您好、Helic、

    非常感谢您的回复、  

    再说明几点、如果使用电感器

    Fullscreen
    1
    DL_I2C_isControllerTXFIFOEmpty(I2C_INST);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    我无法使用此功能:

    Fullscreen
    1
    2
    3
    4
    5
    /* Send the packet to the controller.
    * This function will send Start + Stop automatically.
    */
    DL_I2C_startControllerTransfer(I2C_INST, Addr,
    DL_I2C_CONTROLLER_DIRECTION_TX, 2);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    因为这会自动发送"Start+Stop"、对吧?
    我需要使用其他 API 吗?

    谢谢。此致、

    安东尼。

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

    您好!  

    我不能使用此文件:

    如果 DL_I2C_startControllerTransfer 可以大于8、您可以在参数中设置实际大小。

    传输开始后、  通过 JAM CPU 使用 以下标志读取等待 TxFIFO 为空:

    Fullscreen
    1
    DL_I2C_isControllerTXFIFOEmpty(I2C_INST);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    或者你可以 参考这个线程,因为你两个都需要传输>8长度的数据。

    https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1352378/mspm0g3507-i2c-master-controller-multiple-data-more-the-8-bytes-transfer-polling-example

    此致、

    赫利克

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

    您好、Helic、

    再次感谢您的答复。 因此、基本而言、  

    我应该直接使用  

    具有(假设) 16字节长度的"DL_I2C_startControllerTransfer"并等待 TXFIFO 变为空、再填充8个字节、但我不需要再次调用该 startControllerTransfer 函数、因为这将自动传输下一批 FIFO 数据。 是这样吗?  

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

    您好、Anthony

    是这样吗?  [/报价]

    可以!

    您可以查看  i2c 控制器 RW 多字节 fifo 中断、这是一个>8字节发送示例。

    此致、

    赫利克

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

    您好、Helic、

    非常感谢您的回复。 我使用您的代码片段对其进行了测试、发现了一个问题。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /*
    * Fill FIFO with data.
    */
    g_u8TxCount = DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[0], buf_idx);
    /* Wait for I2C to be Idle */
    while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
    /* Send the packet to the controller.
    * This function will send Start + Stop automatically.
    */
    DL_I2C_startControllerTransfer(I2C_INST, OLED_I2C_ADDR,
    DL_I2C_CONTROLLER_DIRECTION_TX, buf_idx);
    /* Poll until the Controller writes all bytes */
    while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
    while (g_u8TxCount < buf_idx) {
    interrupt = DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    //Waiting for txfifo empty
    while (interrupt != DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY )
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    我能够进行轮询、直到控制器写入所有字节并且代码首次通过此阶段。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /*
    * Fill FIFO with data.
    */
    g_u8TxCount = DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[0], buf_idx);
    /* Wait for I2C to be Idle */
    while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
    /* Send the packet to the controller.
    * This function will send Start + Stop automatically.
    */
    DL_I2C_startControllerTransfer(I2C_INST, OLED_I2C_ADDR,
    DL_I2C_CONTROLLER_DIRECTION_TX, buf_idx);
    /* Poll until the Controller writes all bytes */
    while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    但第二次、它会永远进行轮询、这意味着 I2C 无法完成所有其他字节的写入。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    while (g_u8TxCount < buf_idx) {
    interrupt = DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    //Waiting for txfifo empty
    while (interrupt != DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY )
    {
    ;
    }
    //clear interrupt
    DL_I2C_clearInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    DL_I2C_flushControllerTXFIFO(I2C0);
    //Write more data to I2C FIFO
    g_u8TxCount += DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[g_u8TxCount], buf_idx - g_u8TxCount);
    /* Poll until the Controller writes all bytes */
    while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    您能帮助我了解一下这个问题吗?

    在轮询此阶段之前、我是否需要调用任何其他 API?

    谢谢。此致、

    Anthony Thet.

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

    您好、 

    您需要在这里卡住 CPU、并在每个 while 循环中检查状态。

    这是不可行的,如果你这样做↓:还有一些逻辑问题。

    Fullscreen
    1
    2
    3
    4
    5
    6
    interrupt = DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    //Waiting for txfifo empty
    while (interrupt != DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY )
    {
    ;
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    尝试执行以下代码:

    https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1352378/mspm0g3507-i2c-master-controller-multiple-data-more-the-8-bytes-transfer-polling-example

    但第二次,它是永远轮询,这意味着 I2C 无法完成所有其他字节的写入。

    可以、因为在中、您不会更新中断值。

    此致、

    赫利克

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

    您好、Helic、

    谢谢。 现在、我已尝试使用您提到的代码并能够驱动 OLED、但图像已损坏、有时会闪烁。 因此,当我调试时,我发现了这个问题。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /*
    * Fill FIFO with data.
    */
    g_u8TxCount = DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[0], buf_idx);
    /* Wait for I2C to be Idle */
    while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
    /* Send the packet to the controller.
    * This function will send Start + Stop automatically.
    */
    DL_I2C_startControllerTransfer(I2C_INST, OLED_I2C_ADDR,
    DL_I2C_CONTROLLER_DIRECTION_TX, buf_idx);
    while( g_u8TxCount < buf_idx)
    { /* Wait Till TXFIFO Empty*/
    // while(!DL_I2C_isControllerTXFIFOEmpty(I2C_INST))
    // ;
    Waiting for txfifo empty
    while (!(DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY)))
    ;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    在第一个"DL_I2C_fillControllerTXFIFO"函数中、"g_u8TxCount"接收到了返回值8。

    Fullscreen
    1
    2
    3
    4
    /*
    * Fill FIFO with data.
    */
    g_u8TxCount = DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[0], buf_idx);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    但在第二个"DL_I2C_fillControllerTXFIFO"函数中、  

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    while( g_u8TxCount < buf_idx)
    { /* Wait Till TXFIFO Empty*/
    // while(!DL_I2C_isControllerTXFIFOEmpty(I2C_INST))
    // ;
    Waiting for txfifo empty
    while (!(DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY)))
    ;
    //clear interrupt
    DL_I2C_clearInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    g_u8TxCount += DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[g_u8TxCount], buf_idx - g_u8TxCount);
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    g_u8TxCount 收到17个字节的数据、这意味着 fillControllerTXFIFO 写入9个字节的数据。 我认为这就是显示图像损坏的原因。 我该如何解决此问题?

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

    您好、 

    尝试在硬件上观察这个9个字节。 确保硬件信号正确。

    g_u8TxCount received 17 meaning fillControllerTXFIFO writes 9字节数据。

    此致、

    赫利克

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

    您好、Helic、

    我已经尝试使用相同的 EVK 与移植 Arduino 库(只需要两个字节来写入)、它运行良好。
    我不知道为什么,我只是尝试这只是能够确保每次只写入8字节和 OLED 显示器仍然闪烁。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    while( g_u8TxCount < buf_idx)
    { /* Wait Till TXFIFO Empty*/
    // while(!DL_I2C_isControllerTXFIFOEmpty(I2C_INST))
    // ;
    //Waiting for txfifo empty
    while (!(DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY)))
    ;
    //clear interrupt
    DL_I2C_clearInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    if(buf_idx - g_u8TxCount > 8)
    {
    g_u8TxCount += DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[g_u8TxCount], 8);
    }
    else {
    g_u8TxCount += DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[g_u8TxCount], buf_idx - g_u8TxCount);
    }
    // g_u8TxCount += DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[g_u8TxCount], buf_idx - g_u8TxCount);
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    有没有采用 DMA 传输的主控制器发送 I2C 的示例? 我想尝试一下、因为当前轮询方法似乎太慢。

    谢谢。此致、

    Anthony Thet.

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

    您好、 

    以下是使用 DMA 的 I2C 控制器 Tx、Rx 的演示代码:

    e2e.ti.com/.../4527.i2c_5F00_controller_5F00_rw_5F00_dma_5F00_fifo_5F00_interrupts_5F00_LP_5F00_MSPM0G3507_5F00_nortos_5F00_ticlang.zip

    此致、

    赫利克

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

    您好、Helic、  

    非常感谢您一直以来提供的帮助和帮助。

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

    您好、Helic、

    在应用代码发生一些更改后、我只需使用 u8g2库通过 I2C 来驱动 SSD1316 OLED 显示屏。

    只想为 MSPM0G3507共享我的 HAL 驱动程序代码。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    uint8_t u8x8_gpio_and_delay_mspm0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
    {
    switch (msg)
    {
    case U8X8_MSG_GPIO_AND_DELAY_INIT:
    delay_cycles(32000);//1ms
    break;
    case U8X8_MSG_DELAY_MILLI:
    for(uint8_t i=0; i < arg_int; i++)
    {
    delay_cycles(32000);
    }
    break;
    case U8X8_MSG_GPIO_DC:
    break;
    case U8X8_MSG_GPIO_RESET:
    if (arg_int)
    {
    DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_RST_OLED_PIN);
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX