STM32 I2C钳住SCL强行拉低的解决方法
问题伊始
在多机的I2C通信过程中,STM32单片机做为从机I2C设备与主机通信,以下是代码中的一部分
HAL_I2C_Slave_Receive(&hi2c2, inquire, 2, 500);
if(inquire[0] == 0xaa && inquire[1] == 0x55){ //查询到主机发送的查询码?
inquire[0] = 0; inquire[1] = 0; //清除查询码
for(int i=0; i<1; i++){ //循环一次
if(HAL_I2C_Slave_Transmit(&hi2c2, verify, 2, 3000) != HAL_OK){ //从机发送确认码
break;
}
if(HAL_I2C_Slave_Receive(&hi2c2, u8_angle, 24, 3000) != HAL_OK){
break;
}
for(int i=0; i<24; i+=2){ //高位在前
angle[i / 2] = ((unsigned int)u8_angle[i] << 8) | u8_angle[i+1];
set_Pulse(i/2, angle[i/2]);
}
} //for
}
在执行完if(HAL_I2C_Slave_Receive(&hi2c2, u8_angle, 24, 3000) != HAL_OK)
这句代码,STM32单片机莫名钳住的SCL引脚强制拉低,导致I2C永远处于忙状态
解决过程
翻找参考手册发现I2C可以软复位,在I2C2->CR1[15]
但是在代码加入了I2C2->CR1 |= 1 << 15;
后确实释放了SCL,但是好像整个I2C都复位后是没办法通信了,反正主机是找不到这个从机设备的存在,我相信肯定还有解决方法,但是我想偷懒一会
解决方法
继续翻手册可以发现I2C2->CR1
寄存器下还有一个很重要的位,I2C2->CR1[8]
代码中加入I2C2->CR1 |= 1 << 9;
发现可以正常运行了,可能也是碰巧
HAL_I2C_Slave_Receive(&hi2c2, inquire, 2, 500);
if(inquire[0] == 0xaa && inquire[1] == 0x55){ //查询到主机发送的查询码?
inquire[0] = 0; inquire[1] = 0; //清除查询码
for(int i=0; i<1; i++){ //循环一次
if(HAL_I2C_Slave_Transmit(&hi2c2, verify, 2, 3000) != HAL_OK){ //从机发送确认码
break;
}
if(HAL_I2C_Slave_Receive(&hi2c2, u8_angle, 24, 3000) != HAL_OK){
break;
}
I2C2->CR1 |= 1 << 9; ////////////新增加的代码
for(int i=0; i<24; i+=2){ //高位在前
angle[i / 2] = ((unsigned int)u8_angle[i] << 8) | u8_angle[i+1];
set_Pulse(i/2, angle[i/2]);
}
} //for
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步