【发布时间】:2023-03-15 13:30:03
【问题描述】:
这似乎是一个比较常见的问题,但我在网上找到的任何解决方案都没有成功。具体来说,我正在尝试通过 I2C/DMA 和在 cubeIDE 中生成的 HAL 将 1024 字节缓冲区(完整的 128x64 像素图像)传输到 SSD1306 显示器。我使用的是STML432核板。使用 HAL_I2C_Mem_Write 在没有 DMA 的情况下传输缓冲区没有问题
根据我看到的其他问题,问题在于 DMA 在 I2C 总线仍在传输时完成。我只是不知道如何解决这个问题,并且给出的示例通常不使用 HAL(不幸的是,尽管我很努力,但我猜我自己并不完全有能力将它们正确应用到 HAL)。我尝试过使用 I2c 和 DMA 的中断,但没有成功,只传输了大约前 254 个字节(屏幕上显示的只有两行)。
这是我发送缓冲区的代码:
static void ssd1306_WriteMData_DMA(const uint8_t *data, uint16_t size)
{
while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);
HAL_I2C_Mem_Write_DMA(&hi2c1, I2C_ADDR, SSD1306_REG_MDAT, 1, (uint8_t*)data, size);
}
以及每个中断处理程序的代码:
void I2C1_EV_IRQHandler(void)
{
/* USER CODE BEGIN I2C1_EV_IRQn 0 */
if(I2C1->ISR & I2C_ISR_TCR){
I2C1->CR2 |= (I2C_CR2_STOP);// stop i2c
I2C1->ICR |= (I2C_ICR_STOPCF);// Reset the ICR flag.
// stop DMA
DMA1->IFCR |= DMA_IFCR_CTCIF6;
// clear flag
DMA1_Channel6->CCR &= ~DMA_CCR_EN;
}
/* USER CODE END I2C1_EV_IRQn 0 */
//HAL_I2C_EV_IRQHandler(&hi2c1);
/* USER CODE BEGIN I2C1_EV_IRQn 1 */
/* USER CODE END I2C1_EV_IRQn 1 */
}
void DMA1_Channel6_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
// stop DMA
DMA1->IFCR |= DMA_IFCR_CTCIF6;
// clear flag
DMA1_Channel6->CCR &= ~DMA_CCR_EN;
/* USER CODE END DMA1_Channel6_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_i2c1_tx);
/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
/* USER CODE END DMA1_Channel6_IRQn 1 */
}
我认为这就是所有相关的代码,如果我还缺少其他内容,请告诉我。外围设备的所有初始化代码都是通过 cubeMX 完成的,但如果需要,我可以发布它或设置。我觉得我错过了一些非常简单的事情,但老实说这有点过头了,所以我不太了解发生了什么......
感谢您的帮助!
【问题讨论】: