STM32L432基于HAL库的I2C DMA传输SSD1306数据失败
问题根因与修复方案
核心问题定位
你遇到的传输出截断、仅能显示约254字节内容的现象,本质是手动改写中断逻辑打断了HAL库本身的I2C-DMA同步状态机,结合STM32L4系列I2C外设的硬件特性,具体存在三个叠加故障点:
- STM32L4的I2C外设在单次连续发送超过255字节时,硬件会自动触发
TCR(传输重载)中断,此时需要重新配置后续传输长度才能继续发送。你在中断里遇到TCR就直接手动发STOP、关DMA通道,相当于第一次触发重载时就把整个传输硬掐断,刚好卡在250余字节的位置。 - 你在DMA传输完成中断里提前手动关闭DMA通道,没有等I2C外设把TXDR寄存器里剩余的移位数据完全发送出去,导致总线状态错位,后续传输无法正常推进。
- 你把CubeMX默认生成的
HAL_I2C_EV_IRQHandler注释掉了,相当于失去了HAL层对I2C传输状态的维护,所有外设状态判断都失去了可靠依据。
具体修复步骤
1. 恢复标准中断处理逻辑
把你手动添加的寄存器操作全部从中断函数里移除,还原CubeMX生成的标准处理流程:
I2C1事件中断
删除所有手动操作寄存器的代码,取消HAL中断处理函数的注释:
void I2C1_EV_IRQHandler(void) { HAL_I2C_EV_IRQHandler(&hi2c1); }
DMA1通道6中断
删除手动关DMA、清标志位的冗余代码,只保留标准DMA回调:
void DMA1_Channel6_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_tx); }
2. 核对DMA配置参数
在CubeMX的I2C TX DMA配置里确认以下参数无偏差,避免传输错位:
- 传输方向:内存指向外设
- 内存数据宽度:字节
- 外设数据宽度:字节
- 内存地址增量:使能
- 外设地址增量:关闭
- 传输模式:普通(非循环)
- 通道优先级:高
3. 保留原有发送逻辑即可
HAL_I2C_Mem_Write_DMA本身原生支持超过255字节的长传输:
- HAL库已经内置了对STM32L4 I2C硬件TCR中断的处理逻辑,会自动拆分长传输块、衔接重载流程,直到1024字节全部发送完成后,才会自动触发STOP条件、释放I2C总线
- 你原有的发送缓冲区判断逻辑
while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)完全可以正常使用,不需要额外加延时或手动做时序同步
常见踩坑提醒
- 不要自行手动操作I2C的CR2寄存器发送STOP,HAL会根据传输进度自动发送,提前发STOP会直接截断未发送完成的缓冲区内容
- 不要在DMA中断里手动关闭DMA通道,HAL的DMA回调流程会和I2C状态机严格同步完成通道关闭,提前关通道会导致I2C外设等待DMA送数、总线挂死
- 不需要为I2C和DMA的中断做特殊优先级配置,只要两者的中断优先级不高于系统滴答定时器、不产生异常嵌套即可正常运行
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

