You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32L053 I2C主从模式切换:如何中止从机接收并恢复传输?

解决STM32L053 I2C主从切换传输问题

嘿,这个问题我之前调试STM32 I2C外设的时候也碰到过——同一个I2C外设同时做主从时,从机的监听状态会干扰主机传输,确实没有直接的“中止从机接收”API,但咱们可以通过操作寄存器或者HAL库的间接方法来实现模式切换,具体如下:

核心思路

STM32的I2C外设一旦配置为从机模式,会持续监听总线上的地址匹配请求,这时候发起主机传输会触发总线冲突。解决的关键是临时关闭从机的地址响应功能,待主机传输完成后再重新开启从机模式。

方法一:直接操作寄存器(推荐,开销小)

不需要复杂的API,直接修改I2C的地址寄存器和中断配置就能快速切换:

// 1. 先关闭从机相关中断,避免干扰
__HAL_I2C_DISABLE_IT(&hi2c1, I2C_IT_ADDR | I2C_IT_RXNE | I2C_IT_TXE);

// 2. 等待总线空闲,防止强制切换导致总线挂死
while (__HAL_I2C_GET_FLAG(&hi2c1, I2C_FLAG_BUSY));

// 3. 临时禁用从机地址匹配(关闭从机模式)
I2C1->OAR1 &= ~I2C_OAR1_OA1EN;
// 如果配置了双地址,也要关闭第二个地址
I2C1->OAR2 &= ~I2C_OAR2_OA2EN;

// 4. 执行主机传输逻辑
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, SLAVE_DEVICE_ADDR, tx_buffer, BUFFER_LEN, HAL_MAX_DELAY);

// 5. 传输完成后,重新启用从机模式
I2C1->OAR1 |= I2C_OAR1_OA1EN;
if (USE_DUAL_ADDRESS) {
    I2C1->OAR2 |= I2C_OAR2_OA2EN;
}

// 6. 重新开启从机相关中断
__HAL_I2C_ENABLE_IT(&hi2c1, I2C_IT_ADDR | I2C_IT_RXNE);

注意:操作寄存器时要确保使用的是对应I2C外设的寄存器(比如I2C1/I2C2),根据你的硬件配置调整。

方法二:使用HAL库初始化函数(适合调试阶段)

如果不想直接碰寄存器,可以通过先反初始化再重新初始化的方式切换模式:

// 提前准备好主、从两种模式的初始化结构体
I2C_HandleTypeDef hi2c_master;
I2C_HandleTypeDef hi2c_slave;
// (这里省略两种模式的结构体配置代码,比如地址、速率、中断等)

// 1. 等待总线空闲
while (__HAL_I2C_GET_FLAG(&hi2c_slave, I2C_FLAG_BUSY));

// 2. 反初始化从机配置
HAL_I2C_DeInit(&hi2c_slave);

// 3. 初始化主机模式并执行传输
HAL_I2C_Init(&hi2c_master);
HAL_I2C_Master_Transmit(&hi2c_master, SLAVE_DEVICE_ADDR, tx_buffer, BUFFER_LEN, HAL_MAX_DELAY);

// 4. 反初始化主机配置,重新恢复从机模式
HAL_I2C_DeInit(&hi2c_master);
HAL_I2C_Init(&hi2c_slave);

这种方法的缺点是初始化过程开销较大,但胜在逻辑清晰,适合调试阶段验证功能。

为什么加从机逻辑后传输失败?

当I2C外设处于从机模式时,会持续监听总线上的起始信号和地址帧,此时你尝试以主机身份发起START条件,外设会同时触发从机地址匹配检测和主机传输请求,导致总线状态混乱,最终传输超时或失败。

额外小提示

如果只是学习用,也可以考虑用STM32上的两个独立I2C外设(比如I2C1做主,I2C2做从),这样就不需要频繁切换模式,能避免很多总线冲突问题~

内容的提问来源于stack exchange,提问作者Cris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:02:46