我目前的項目是ch582f根mpu6050通信。在通信成功幾十分鐘或幾個小時(老化測試一晚)過后會出現(xiàn)無法繼續(xù)讀取mpu6050的情況。提示i2c總線出于忙狀態(tài),但是我用示波器和邏輯分析儀測試沒有出現(xiàn)sda被拉低的情況,scl和sda線都是高電平狀態(tài)。
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標志?