wenwen446 2023-10-16 07:20 采纳率: 25%
浏览 126
已结题

I2C通讯时,SCL波形异常

I2C通讯,发现SCL的波形出现掉坑现象,求原因及解决方法,我是采用轮询方式通讯读的时候出现这个现象。

img

img

uint8_t I2C_EE_ReadBuffer(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead)
{
    
    uint8_t state = I2C_START;
    uint32_t timeout = 0;
    uint8_t i2c_timeout_flag = 0;
    uint8_t Return_Stat=0;
    
    while(!(i2c_timeout_flag)) {
        switch(state) {
                    
        case I2C_START:    
/* CASE     I2C_START:*/

//            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    

            while(I2C_GetFlag(I2C1, I2C_FLAG_BUSY) && (timeout < I2C_TIME_OUT_8815)) {
                timeout++;
                }
                if(timeout < I2C_TIME_OUT_8815) {
                    
//                    GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    
                    
                    I2C_ConfigPecLocation(I2C1, I2C_PEC_POS_CURRENT);
                    I2C_ConfigAck(I2C1, ENABLE);
                                            
                    /** Send START condition */
                    I2C_GenerateStart(I2C1, ENABLE);
                    timeout = 0;
                    state = I2C_SEND_ADDRESS;
                                    
                                    
                } else {
                    timeout = 0;
                    IIC_SWReset_8815();                    
                                    
                    state = I2C_TIMEOUT_END;
                }
            break;

                
        
        
        case I2C_SEND_ADDRESS:        
/* CASE     I2C_SEND_ADDRESS:*/        
        
//            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    

            while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_MODE_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                timeout++;
            }
            if(timeout < I2C_TIME_OUT_8815) {
                
//                 GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    
               
                I2C_SendAddr7bit(I2C1, SC8815_ADDRESS_R, I2C_DIRECTION_SEND);
                state = I2C_CLEAR_ADDRESS_FLAG;
                timeout = 0;
            } else {
                timeout = 0;
                IIC_SWReset_8815();                    
                            
                state = I2C_TIMEOUT_END;//state = I2C_START;

            }
            break;


        
        case I2C_CLEAR_ADDRESS_FLAG:        
/* CASE     I2C_CLEAR_ADDRESS_FLAG:*/    
        
//            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    
        
            while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_TXMODE_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                timeout++;
            }
            if(timeout < I2C_TIME_OUT_8815) {
//                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                /** Clear EV6 by setting again the PE bit */
                I2C_Enable(I2C1, ENABLE);
                /** Send the EEPROM's internal address to write to */
                I2C_SendData(I2C1, ReadAddr);                            
                timeout = 0;
                state = I2C_TRANSMIT_DATA;
            } else {
                timeout = 0;
                IIC_SWReset_8815();                    
                
                state = I2C_TIMEOUT_END;//state = I2C_START;
                            
            }
            break;

        
        
        
        case I2C_TRANSMIT_DATA:        
/* CASE     I2C_TRANSMIT_DATA:*/        
        
//                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    

                while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_DATA_SENDED) && (timeout < I2C_TIME_OUT_8815)) {
                    timeout++;
                }
                if(timeout < I2C_TIME_OUT_8815) {
                    /* send the EEPROM's internal address to write to : only one byte address */
//                    GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                    I2C_GenerateStart(I2C1, ENABLE);
                    timeout = 0;
                } else {
                    timeout = 0;
                    IIC_SWReset_8815();                    
                                    
                    state = I2C_TIMEOUT_END;//state = I2C_START;
                                    
                }

//                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    

                while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_MODE_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                    timeout++;
                }
                if(timeout < I2C_TIME_OUT_8815) {
//                    GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                    I2C_SendAddr7bit(I2C1, SC8815_ADDRESS_R, I2C_DIRECTION_RECV);
                    timeout = 0;
                } else {
                    timeout = 0;
                    IIC_SWReset_8815();                    
                                    
                    state = I2C_TIMEOUT_END;//state = I2C_START;
                                    
                }

//                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    

                while(!I2C_GetFlag(I2C1, I2C_FLAG_ADDRF) && (timeout < I2C_TIME_OUT_8815)) {
                    timeout++;
                }
                if(timeout < I2C_TIME_OUT_8815) {

//                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                /** While there is data to be read */
                if (NumByteToRead == 1)
                {
                    /** Disable Acknowledgement */
                    I2C_ConfigAck(I2C1, DISABLE);
                    /** clear ADDR */
                    (void)(I2C1->STS1); 
                    (void)(I2C1->STS2);
                    /** Generates START condition to close communication */
                    I2C_GenerateStart(I2C1, ENABLE);
                }
                else
                {
                    /** clear ADDR */
                    (void)(I2C1->STS1); 
                    (void)(I2C1->STS2);
                }
                    
                timeout = 0;
                state = I2C_NUM_mine;                
                
                } else {
                    timeout = 0;
                    IIC_SWReset_8815();                    
                                    
                    state = I2C_TIMEOUT_END;//state = I2C_START;
                }



    
            break;

        case I2C_NUM_mine:

                if(NumByteToRead!=0)
                {
                    if (NumByteToRead <= 2)
                    {
                        /** One byte */
                        if (NumByteToRead == 1)
                        {
//                            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    
                                        
                            while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                                timeout++;
                            }
                            if(timeout < I2C_TIME_OUT_8815) {
//                                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                                timeout = 0;
                                /** Read data from DAT */
                                *pBuffer = I2C_RecvData(I2C1);
                                /** Point to the next location where the byte read will be saved */
                                pBuffer++;
                                /** Decrement the read bytes counter */
                                NumByteToRead--;
                                 /** Generates STOP condition to release SCL/SDA line */
                                I2C_GenerateStop(I2C1, ENABLE);   
                                
                                
                            } else {
                                timeout = 0;
                                IIC_SWReset_8815();                    
                                                
                                state = I2C_TIMEOUT_END;//state = I2C_START;
                                                
                            }

                                            
                         
                        }
                        /** 2 Last bytes */
                        else
                        {
//                            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    
                            
                            while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                                timeout++;
                            }
                            if(timeout < I2C_TIME_OUT_8815) {
//                                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                                timeout = 0;
                                /** Disable Acknowledgement */ 
//                                I2C_ConfigAck(I2C1, DISABLE);
                                               
                                /** Read data from DAT */
                                *pBuffer = I2C_RecvData(I2C1);
                                /** Point to the next location where the byte read will be saved */
                                pBuffer++;
                                /** Decrement the read bytes counter */
                                NumByteToRead--;
                                
//                                I2C_ConfigAck(I2C1, DISABLE);
//                                
//                                I2C_GenerateStop(I2C1, ENABLE);                                
                                
                                
                            } else {
                                timeout = 0;
                                IIC_SWReset_8815();                    
                                                
                                state = I2C_TIMEOUT_END;//state = I2C_START;
                                                
                            }
                            
                            I2C_ConfigAck(I2C1, DISABLE);
                            /** clear ADDR */
                            (void)(I2C1->STS1); 
                            (void)(I2C1->STS2);
                            /** Generates START condition to close communication */
                            I2C_GenerateStart(I2C1, ENABLE);
                            
                            
                            
//                            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    

                            while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                                timeout++;
                            }
                            if(timeout < I2C_TIME_OUT_8815) {
                                timeout = 0;
//                                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                                /** Read data from DAT */
                                *pBuffer = I2C_RecvData(I2C1);              
                                /** Point to the next location where the byte read will be saved */
                                pBuffer++;
                                /** Decrement the read bytes counter */
                                NumByteToRead--;
                                
                                /** Generates STOP condition to release SCL/SDA line */
                                I2C_GenerateStop(I2C1, ENABLE);                                
                                
                                
                            } else {
                                timeout = 0;
                                IIC_SWReset_8815();                    
                                                
                                state = I2C_TIMEOUT_END;//state = I2C_START;
                                                
                            }                                
                        }
                    }
                    else
                    {
//                            GPIO_WriteBit(GPIOB, GPO_Debug, Bit_SET);    
                        
                            while(!I2C_CheckEvent(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG) && (timeout < I2C_TIME_OUT_8815)) {
                                timeout++;
                            }
                            if(timeout < I2C_TIME_OUT_8815) {
//                                GPIO_WriteBit(GPIOB, GPO_Debug, Bit_RESET);    

                                timeout = 0;
                                /** Read a byte from the EEPROM */
                                *pBuffer = I2C_RecvData(I2C1);
                                /** Point to the next location where the byte read will be saved */
                                pBuffer++;
                                /** Decrement the read bytes counter */
                                NumByteToRead--;
//                                if (I2C_GetFlag(I2C1, I2C_FLAG_BYTEF))
//                                {
//                                    /** Read a byte from the EEPROM */
//                                    *pBuffer = I2C_RecvData(I2C1);
//                                    /** Point to the next location where the byte read will be saved */
//                                    pBuffer++;
//                                    /** Decrement the read bytes counter */
//                                    NumByteToRead--;
//                                }                                
                                
                                
                            } else {
                                timeout = 0;
                                IIC_SWReset_8815();                    
                                                
                                state = I2C_TIMEOUT_END;//state = I2C_START;
                                                
                            }
                    }
                }
                else
                {
                    state = I2C_STOP;
                }
        
            break;        

        case I2C_STOP:

            timeout = 0;
            state = I2C_END;
            i2c_timeout_flag = I2C_OK;

            break;        

        case I2C_TIMEOUT_END:
            i2c_timeout_flag = 1; 
            Return_Stat = 1;
            break;        
        
        default:
            state = I2C_START;
            i2c_timeout_flag = I2C_OK;
            timeout = 0;
            break;        
    }

}
        
 return Return_Stat; 
 
}

```c
void IIC_SWReset_8815(void)
{
    GPIO_InitType i2cx_gpio;
//    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
//    GPIO_AFIOInitDefault();
//    GPIO_DeInit(GPIOA);
    
    i2cx_gpio.Pin        = I2C1_SCL_PIN | I2C1_SDA_PIN;
    i2cx_gpio.GPIO_Speed = GPIO_SPEED_HIGH;
    i2cx_gpio.GPIO_Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitPeripheral(GPIOA, &i2cx_gpio);
    
    GPIO_ResetBits(I2C1_GPIO_PORT, I2C1_SCL_PIN | I2C1_SDA_PIN);
    

//    GPIO_InitStruct(&i2cx_gpio);
//    i2cx_gpio.Pin        = I2C1_SCL_PIN | I2C1_SDA_PIN;
////    i2cx_gpio.GPIO_Speed = GPIO_SPEED_HIGH;
//    i2cx_gpio.GPIO_Mode  = GPIO_MODE_INPUT;
//    i2cx_gpio.GPIO_Pull  = GPIO_PULL_UP;
//    GPIO_InitPeripheral(GPIOA, &i2cx_gpio);

        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();

    GPIO_SetBits(I2C1_GPIO_PORT, I2C1_SCL_PIN);
    
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();

    GPIO_SetBits(I2C1_GPIO_PORT, I2C1_SDA_PIN);

    I2C_8815_Config();
    
}

```

  • 写回答

11条回答 默认 最新

  • qllaoda 2023-10-16 09:47
    关注

    硬件I2C还是IO模拟I2C时序?如果是硬件,应该是外部干扰或者总线上其他设备异常导致。
    如果是软件模拟,除了以上原因,还可能和I2C时钟信号的延迟处理代码有关。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月20日
  • 修改了问题 10月16日
  • 修改了问题 10月16日
  • 创建了问题 10月16日