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**** 2343770 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 提供的样片。

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();
      break;
    default:
      return 0;
  }
  return 1;
}

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

    您好、 

    Unknown 说:

    否。

    Unknown 说:
    其 HW i2c 只能支持8个 FIFO。

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

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

    DL_I2C_isControllerTXFIFOEmpty(I2C_INST);

    此致、

    赫利克

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

    您好、Helic、

    非常感谢您的回复、  

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

    DL_I2C_isControllerTXFIFOEmpty(I2C_INST);

    我无法使用此功能:

        /* 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);

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

    谢谢。此致、

    安东尼。

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

    您好!  

    我不能使用此文件:

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

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

    DL_I2C_isControllerTXFIFOEmpty(I2C_INST);

    或者你可以 参考这个线程,因为你两个都需要传输>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、

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

                /*
                * 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 )
                    {
                        ;
                    }
                    //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);
                }        
    
    
    
                /* Trap if there was an error */
                if (DL_I2C_getControllerStatus(I2C_INST) &
                    DL_I2C_CONTROLLER_STATUS_ERROR) {
                    /* LED will remain high if there is an error */
                    __BKPT(0);
                }
    
                /* Wait for I2C to be Idle */
                while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE))
                ;
    
                DL_I2C_flushControllerTXFIFO(I2C0);

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

                /*
                * 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);

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

                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);
                }  

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

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

    谢谢。此致、

    Anthony Thet.

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

    您好、 

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

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

    interrupt = DL_I2C_getRawInterruptStatus(I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY);
    //Waiting for txfifo empty
    while (interrupt != DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY )
    {
        ;
    }

    尝试执行以下代码:

    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、但图像已损坏、有时会闪烁。 因此,当我调试时,我发现了这个问题。

                /*
                * 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)))
                    ;
                    //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);
                }

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

                /*
                * Fill FIFO with data.
                */
                g_u8TxCount = DL_I2C_fillControllerTXFIFO(I2C_INST, &buffer[0], buf_idx);

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

                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);
                }

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

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

    您好、 

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

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

    此致、

    赫利克

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

    您好、Helic、

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

                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);
                }

    有没有采用 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 驱动程序代码。

    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);
    		}
            else
            {
                DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_RST_OLED_PIN);
    		}
    	    break;
    	  }
    	  return 1;
    }
    
    
    uint8_t u8x8_byte_mspm0_hw_i2c (u8x8_t *u8g2, uint8_t msg, uint8_t arg_int, void *arg_ptr)
    {
      /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
      /* add extra byte for the i2c address */
      static uint8_t buffer[34];
      static volatile uint8_t buf_idx, g_u8TxCount;
      uint8_t *data;  
      switch(msg)
      {
        case U8X8_MSG_BYTE_SEND:
            data = (uint8_t *)arg_ptr;
            while( arg_int > 0 )
            {
                buffer[buf_idx++] = *data;
                data++;
                arg_int--;
            }
                break;
    
        case U8X8_MSG_BYTE_INIT:
                /* add your custom code to init i2c subsystem */
    
                break;
        case U8X8_MSG_BYTE_SET_DC:
                /* ignored for i2c */
                break;
        case U8X8_MSG_BYTE_START_TRANSFER:
                buf_idx = 0;       
                break;
        case U8X8_MSG_BYTE_END_TRANSFER:
                /*
                * 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)
                {
                    while(DL_I2C_isControllerTXFIFOFull(I2C_INST)==true)
                    ;
                    DL_I2C_transmitControllerData(I2C_INST, buffer[g_u8TxCount]);
                    g_u8TxCount++;
                }
    
                /* Poll until the Controller writes all bytes */
                while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
    
                /* Trap if there was an error */
                if (DL_I2C_getControllerStatus(I2C_INST) &
                    DL_I2C_CONTROLLER_STATUS_ERROR) {
                        while(1);
                }
    
                /* Wait for I2C to be Idle */
                while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
    
                DL_I2C_flushControllerTXFIFO(I2C_INST);
    
                break;
    
        default:
                return 0;    
      }
      return 1;
    }