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永远处于忙状态
image
image

解决过程

翻找参考手册发现I2C可以软复位,在I2C2->CR1[15]
image
但是在代码加入了I2C2->CR1 |= 1 << 15;后确实释放了SCL,但是好像整个I2C都复位后是没办法通信了,反正主机是找不到这个从机设备的存在,我相信肯定还有解决方法,但是我想偷懒一会

解决方法

继续翻手册可以发现I2C2->CR1寄存器下还有一个很重要的位,I2C2->CR1[8]

image
代码中加入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
}
posted @   重力弹力支持力  阅读(187)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示