問題伊始
在多機的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
}