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.
您好!
对于使用 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; }
您好、 Anthony
否。
其 HW i2c 只能支持8个 FIFO。对于 FIFO 的使用、您可以参考相同的 SDK 演示。 另一个需要确认的是在 syscfg 中配置 Tx FIFO 触发电平、如下所示:
对于数据长度超过8个字节的情况、您可以调用此 API 来等待 TX FIFO 清空并使用新数据来填充:
Fullscreen1DL_I2C_isControllerTXFIFOEmpty(I2C_INST);XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXDL_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长度的数据。
此致、
赫利克
您好、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.
您好、 Anthony
您需要在这里卡住 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 ) { ; }
尝试执行以下代码:
但第二次,它是永远轮询,这意味着 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个字节的数据。 我认为这就是显示图像损坏的原因。 我该如何解决此问题?
您好、 Anthony
尝试在硬件上观察这个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.
您好、 Anthony
以下是使用 DMA 的 I2C 控制器 Tx、Rx 的演示代码:
此致、
赫利克
您好、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; }