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
相关产品推荐
相关产品推荐

