STM32 I2C鉗住SCL強行拉低的解決方法

重力弹力支持力發表於2024-06-02

問題伊始

在多機的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
}

相關文章