我目前的项目是ch582f根mpu6050通信。在通信成功几十分钟或几个小时(老化测试一晚)过后会出现无法继续读取mpu6050的情况。提示i2c总线出于忙状态,但是我用示波器和逻辑分析仪测试没有出现sda被拉低的情况,scl和sda线都是高电平状态。
uint8_t i2c_timeout(uint32_t *p_times) //Timeout processing
{
(*p_times)++;
//x5_delay_us(1);
i2c_ch58xx_delay_us(1);
if(*p_times > I2C_TIMEOUT) {
return 1;
}
return 0;
}
void x5_i2c_init_bsp(uint8_t no, x5_i2c_config_t *config)
{
if (no > 0 || !config){
printf("ch58xx x5_i2c_init_bsp error:no > 0 or config == NULL\r\n");
}
//
// static uint8_t init_flag = 0;
// if (init_flag == 0) {
// GPIOB_ModeCfg(GPIO_Pin_13 | GPIO_Pin_12, GPIO_ModeIN_PU);
// I2C_Init(I2C_Mode_I2C, 400000, I2C_DutyCycle_16_9, I2C_Ack_Enable,
// I2C_AckAddr_7bit, HOST_NO_ADDR);
if (i2c_info[no].port_clk == CH58xx_GPIOB) {
GPIOB_ModeCfg(i2c_info[no].pin_clk, GPIO_ModeIN_PU);
}else{
GPIOA_ModeCfg(i2c_info[no].pin_clk, GPIO_ModeIN_PU);
}
if (i2c_info[no].port_sda == CH58xx_GPIOB) {
GPIOB_ModeCfg(i2c_info[no].pin_sda, GPIO_ModeIN_PU);
}else{
GPIOA_ModeCfg(i2c_info[no].pin_sda, GPIO_ModeIN_PU);
}
printf("ch58xx x5_i2c_init_bsp: mode:%d,speed:%d,duty_cycle:%d,ack_add:%d,host_NO_ADDR:%d, \r\n",
i2c_mode[config->mode], i2c_speed[config->speed],i2c_duty_cycle[config->dc],
I2C_AckAddr_7bit, HOST_ADDR);
I2C_Init(i2c_mode[config->mode], i2c_speed[config->speed], i2c_duty_cycle[config->dc],
I2C_Ack_Enable, I2C_AckAddr_7bit, HOST_ADDR);
// init_flag = 1;
// }
}
/***************************************
* read n bytes of data continuously
* param:
* addr-Slave address
* mem-Register addr
* men_16-Enbale 16 bit register
* p_des-Destination pointer
* len-Read length
* return:
* 0:succeed
* 1~7:error in 1~7 step.
* 0x01:error in read continuously
*/
static uint8_t i2c_read_nBytes(uint8_t addr, uint16_t mem, uint8_t mem_16, uint8_t *p_des, uint8_t len)
{
uint32_t i_timeout = 0;
/*send register addr*/
//I2C_GenerateSTOP(DISABLE);
while(I2C_GetFlagStatus(I2C_FLAG_BUSY)) { //IIC whether host busy
if(i2c_timeout(&i_timeout))
return 1;
}
I2C_GenerateSTART(ENABLE); //start signal
i_timeout = 0;
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)) { //wait BUSY, MSL and SB flags
if(i2c_timeout(&i_timeout))
return 2;
}
I2C_Send7bitAddress(addr<<1, I2C_Direction_Transmitter); //send component addr , bit0 = 0 indicate "write"
i_timeout = 0;
while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { //wait BUSY, MSL, ADDR, TXE and TRA flags
if(i2c_timeout(&i_timeout))
return 3;
}
if(mem_16) {
I2C_SendData((uint8_t)(mem>>8)); //If mem addr is 16bit, Send the upper 8 bits of the memory address
i_timeout = 0;
while(!I2C_GetFlagStatus(I2C_FLAG_TXE)){ //wait send finished.
if(i2c_timeout(&i_timeout))
return 4;
}
i_timeout = 0;
}
I2C_SendData((uint8_t)mem); //Send the lower 8 bits of the memory address
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { //wait TRA, BUSY, MSL, TXE and BTF flags, send register addr finished.
if(i2c_timeout(&i_timeout))
return 5;
}
/*Generate a re-start signal to start the reading process*/
I2C_GenerateSTART(ENABLE); //re-start signal
i_timeout = 0;
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)) { //wait BUSY, MSL and SB flags
if(i2c_timeout(&i_timeout))
return 6;
}
I2C_AcknowledgeConfig(ENABLE); //After the transmission is completed, turn on ACK enable again
I2C_Send7bitAddress(addr<<1, I2C_Direction_Receiver); //send component addr , bit0 = 1 indicate "read"
i_timeout = 0;
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){ //wait BUSY, MSL and ADDR flags
if(i2c_timeout(&i_timeout))
return 7;
}
for(uint8_t i=0; i<len; i++){
if(i == len-1)
//I2C_NACKPositionConfig(I2C_NACKPosition_Next);
I2C_AcknowledgeConfig(DISABLE);
//Clear the ACK bit (PE may be cleared here in some cases, this line can be removed, but the logic analyzer will receive one more byte of data if it captures the timing)
//In order for the master device to generate a NACK signal after receiving the last byte, it must clear the ACK bit (ACK=0) after reading the penultimate byte (after the penultimate RxNE event)
i_timeout = 0;
while(!I2C_GetFlagStatus(I2C_FLAG_RXNE)) { //wait receive data
if(i2c_timeout(&i_timeout)){
printf("[-->%d]I2C_ReceiveData: i =%d\r\n",__LINE__,i);
return 0xff;
}
}
*(p_des+i) = I2C_ReceiveData(); //read data from Rx register
}
I2C_GenerateSTOP(ENABLE); //Turn on the stop signal
return 0;
}
情况能怎么防止或者清除这个busy标志?