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


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();
}
```