/* ****************************************************************************** * @file apt32f102_i2c.c * @author APT AE Team * @version V1.08 * @date 2021/06/21 ****************************************************************************** *THIS SOFTWARE WHICH IS FOR ILLUSTRATIVE PURPOSES ONLY WHICH PROVIDES *CUSTOMER WITH CODING INFORMATION REGARDING THEIR PRODUCTS. *APT CHIP SHALL NOT BE HELD RESPONSIBILITY ADN LIABILITY FOR ANY DIRECT, *INDIRECT DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF *SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION *CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.AND APT CHIP RESERVES *THE RIGHT TO MAKE CHANGES IN THE SOFTWARE WITHOUT NOTIFICATION ****************************************************************************** */ #include "apt32f102_i2c.h" volatile uint8_t I2CWrBuffer[BUFSIZE]; volatile uint8_t I2CRdBuffer[BUFSIZE]; volatile uint8_t RdIndex = 0; volatile uint8_t WrIndex = 0; volatile uint8_t I2C_Data_Adress; volatile uint8_t I2C_St_Adress; volatile U8_T f_ERROR=0; volatile U32_T R_IIC_ERROR_CONT; extern void delay_nms(unsigned int t); /*************************************************************/ //I2C RESET,CLEAR ALL REGISTER //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_DeInit(void) { I2C0->ENABLE = 0; I2C0->IMSCR = 0; I2C0->ICR = 0X7FFF; } /*************************************************************/ //I2C MASTER Initial //EntryParameter:SPEEDMODE,MASTERBITS, //SPEEDMODE:FAST_MODE(>100K),STANDARD_MODE(<100K) //MASTERBITS:I2C_MASTRER_7BIT/I2C_MASTRER_10BIT //ReturnValue:NONE /*************************************************************/ void I2C_Master_CONFIG(I2C_SDA_TypeDef I2C_SDA_IO,I2C_SCL_TypeDef I2C_SCL_IO,I2C_SPEEDMODE_TypeDef SPEEDMODE, I2C_MASTRERBITS_TypeDef MASTERBITS,U16_T I2C_MASTER_ADDS,U16_T SS_SCLHX,U16_T SS_SCLLX) { //SDA IO Initial if(I2C_SDA_IO==I2C_SDA_PA00) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFFFFFF0) | 0x00000005; //PA0.0->SDA } else if(I2C_SDA_IO==I2C_SDA_PA03) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFFF0FFF) | 0x00006000; //PA0.3->SDA } else if (I2C_SDA_IO==I2C_SDA_PA07) { GPIOA0->CONLR = (GPIOA0->CONLR&0X0FFFFFFF) | 0x40000000; //PA0.7->SDA } else if(I2C_SDA_IO==I2C_SDA_PA013) { GPIOA0->CONHR = (GPIOA0->CONHR&0XFF0FFFFF) | 0x00600000; //PA0.13->SDA } else if(I2C_SDA_IO==I2C_SDA_PA014) { GPIOA0->CONHR = (GPIOA0->CONHR&0XF0FFFFFF) | 0x06000000; //PA0.14->SDA } //SCL IO Initial if (I2C_SCL_IO==I2C_SCL_PB00) { GPIOB0->CONLR = (GPIOB0->CONLR&0XFFFFFFF0) | 0x00000006; //PB0.0->SCL } else if (I2C_SCL_IO==I2C_SCL_PB02) { GPIOB0->CONLR = (GPIOB0->CONLR&0XFFFFF0FF) | 0x00000400; //PB0.2->SCL } else if(I2C_SCL_IO==I2C_SCL_PA01) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFFFFF0F) | 0x00000050; //PA0.1->SCL } else if(I2C_SCL_IO==I2C_SCL_PA04) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFF0FFFF) | 0x00060000; //PA0.4->SCL } else if(I2C_SCL_IO==I2C_SCL_PA06) { GPIOA0->CONLR = (GPIOA0->CONLR&0XF0FFFFFF) | 0x06000000; //PA0.6->SCL } else if(I2C_SCL_IO==I2C_SCL_PA015) { GPIOA0->CONHR = (GPIOA0->CONHR&0X0FFFFFFF) | 0x60000000; //PA0.15->SCL } I2C0->ENABLE = (I2C0->ENABLE&0XFFFFFFFE)|I2C_DISABLE; I2C0->CR =(I2C0->CR&0XFFFFF000)|I2C_MASTER_EN |I2C_SLAVE_DIS| SPEEDMODE | MASTERBITS | I2C_RESTART_EN; //Repeat start bit enable I2C0->TADDR =I2C_MASTER_ADDS; if(SPEEDMODE==FAST_MODE) { I2C0->FS_SCLH = SS_SCLHX; //SCL high time I2C0->FS_SCLL = SS_SCLLX; //SCL low time } else if(SPEEDMODE==STANDARD_MODE) { I2C0->SS_SCLH = SS_SCLHX; //SCL high time I2C0->SS_SCLL = SS_SCLLX; //SCL low time } } /*************************************************************/ //I2C SLAVE Initial //EntryParameter:SPEEDMODE,SLAVEBITS,I2C_SALVE_ADD //SPEEDMODE:FAST_MODE(>100K),STANDARD_MODE(<100K) //SLAVEBITS:I2C_SLAVE_7BIT/I2C_SLAVE_10BIT //I2C_SALVE_ADD:I2C SLAVE ADDRESS //ReturnValue:NONE /*************************************************************/ void I2C_Slave_CONFIG(I2C_SDA_TypeDef I2C_SDA_IO,I2C_SCL_TypeDef I2C_SCL_IO,I2C_SPEEDMODE_TypeDef SPEEDMODE, I2C_SLAVEBITS_TypeDef SLAVEBITS,U16_T I2C_SALVE_ADDS,U16_T SS_SCLHX,U16_T SS_SCLLX) { //SDA IO Initial if(I2C_SDA_IO==I2C_SDA_PA00) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFFFFFF0) | 0x00000005; //PA0.0->SDA } else if(I2C_SDA_IO==I2C_SDA_PA03) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFFF0FFF) | 0x00006000; //PA0.3->SDA /// } else if (I2C_SDA_IO==I2C_SDA_PA07) { GPIOA0->CONLR = (GPIOA0->CONLR&0X0FFFFFFF) | 0x40000000; //PA0.7->SDA } else if(I2C_SDA_IO==I2C_SDA_PA013) { GPIOA0->CONHR = (GPIOA0->CONHR&0XFF0FFFFF) | 0x00600000; //PA0.13->SDA } else if(I2C_SDA_IO==I2C_SDA_PA014) { GPIOA0->CONHR = (GPIOA0->CONHR&0XF0FFFFFF) | 0x06000000; //PA0.14->SDA } //SCL IO Initial if (I2C_SCL_IO==I2C_SCL_PB00) { GPIOB0->CONLR = (GPIOB0->CONLR&0XFFFFFFF0) | 0x00000006; //PB0.0->SCL } else if (I2C_SCL_IO==I2C_SCL_PB02) { GPIOB0->CONLR = (GPIOB0->CONLR&0XFFFFF0FF) | 0x00000400; //PB0.2->SCL } else if(I2C_SCL_IO==I2C_SCL_PA01) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFFFFF0F) | 0x00000050; //PA0.1->SCL } else if(I2C_SCL_IO==I2C_SCL_PA04) { GPIOA0->CONLR = (GPIOA0->CONLR&0XFFF0FFFF) | 0x00060000; //PA0.4->SCL // } else if(I2C_SCL_IO==I2C_SCL_PA06) { GPIOA0->CONLR = (GPIOA0->CONLR&0XF0FFFFFF) | 0x06000000; //PA0.6->SCL } else if(I2C_SCL_IO==I2C_SCL_PA015) { GPIOA0->CONHR = (GPIOA0->CONHR&0X0FFFFFFF) | 0x60000000; //PA0.15->SCL } I2C0->ENABLE = (I2C0->ENABLE&0XFFFFFFFE)|I2C_DISABLE; I2C0->CR =(I2C0->CR&0XFFFFF000)| I2C_MASTER_DIS |I2C_SLAVE_EN | SPEEDMODE | SLAVEBITS; I2C0->SADDR = I2C_SALVE_ADDS; if(SPEEDMODE==FAST_MODE) { I2C0->FS_SCLH = SS_SCLHX; //SCL high time I2C0->FS_SCLL = SS_SCLLX; //SCL low time } else if(SPEEDMODE==STANDARD_MODE) { I2C0->SS_SCLH = SS_SCLHX; //SCL high time I2C0->SS_SCLL = SS_SCLLX; //SCL low time } INTC_IPR4_WRITE(0X40400040); //setting highest INT Priority when using i2c as salve } /*************************************************************/ //I2C SDA TSETUP THOLD CONFIG //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_SDA_TSETUP_THOLD_CONFIG(U8_T SDA_TSETUP , U8_T SDA_RX_THOLD , U16_T SDA_TX_THOLD) { I2C0->SDA_TSETUP=SDA_TSETUP; I2C0->SDA_THOLD=(SDA_RX_THOLD<<16)|SDA_TX_THOLD; } /*************************************************************/ //I2C INT CONFIG //EntryParameter:I2C_RX_UNDER,I2C_RX_OVER,I2C_RX_FULL,I2C_TX_OVER // I2C_TX_EMPTY,I2C_RD_REQ,I2C_TX_ABRT,I2C_RX_DONE // I2C_INT_BUSY,I2C_STOP_DET,I2C_START_DET,I2C_GEN_CALL // I2C_RESTART_DET,I2C_MST_ON_HOLD,I2C_SCL_SLOW //NewState:ENABLE/DISABLE //ReturnValue:NONE /*************************************************************/ void I2C_ConfigInterrupt_CMD(FunctionalStatus NewState,U32_T INT_TYPE) { if(NewState != DISABLE) { I2C0->IMSCR |= INT_TYPE; } else { I2C0->IMSCR &= (~INT_TYPE); } } /*************************************************************/ //I2C FIFO trigger data //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_FIFO_TriggerData(U16_T RX_FLSEL,U16_T TX_FLSEL) { I2C0->RX_FLSEL = RX_FLSEL; I2C0->TX_FLSEL = TX_FLSEL; } /*************************************************************/ //I2C Stop //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Stop(void) { I2C0->DATA_CMD = (I2C0->DATA_CMD&0XFFFFFDFF)|I2C_CMD_STOP; //Enable I2C } /*************************************************************/ //I2C enable //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Enable(void) { I2C0->ENABLE = (I2C0->ENABLE&0XFFFFFFFE)|I2C_ENABLE; //Enable I2C while((I2C0->STATUS&0x1000)!=0x1000); } /*************************************************************/ //I2C disable //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Disable(void) { I2C0->ENABLE =(I2C0->ENABLE&0XFFFFFFFE)|I2C_DISABLE; //Disable I2C while((I2C0->STATUS&0x1000)==0x1000); } /*************************************************************/ //I2C Abort enable in master mode //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Abort_EN(void) { I2C0->ENABLE = (I2C0->ENABLE&0XFFFFFFFD)|I2C_ABORT; //Enable Abort } /*************************************************************/ //I2C Abort status //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ U8_T I2C_Abort_Status(void) { uint8_t value = 0; uint32_t dat = 0; dat=(I2C0->ENABLE)&0x02; if (dat == 0x02) { value = 1; //aborting } return value; //no abort or abort over } /*************************************************************/ //I2C RECOVER enable //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_SDA_Recover_EN(void) { I2C0->ENABLE = (I2C0->ENABLE&0XFFFFFFF7)|I2C_SDA_REC_EN; //Enable Recover Enable } /*************************************************************/ //I2C RECOVER enable //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_SDA_Recover_DIS(void) { I2C0->ENABLE = (I2C0->ENABLE&0XFFFFFFF7)|I2C_SDA_REC_DIS; //Enable Recover Disable } /*************************************************************/ //I2C Interrupt enable //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Int_Enable(void) { INTC_ISER_WRITE(I2C_INT); //Enable I2C interrupt } /*************************************************************/ //I2C Interrupt disable //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Int_Disable(void) { INTC_ICER_WRITE(I2C_INT); //Disable I2C interrupt } /*************************************************************/ //I2C WRITE OneByte //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_WRITE_Byte(U8_T write_adds,U8_T i2c_data) { U16_T R_EEROR_CONT=0; I2C0->DATA_CMD = I2C_CMD_WRITE|write_adds ; I2C0->DATA_CMD = i2c_data |I2C_CMD_STOP; do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; I2C_Disable(); I2C_Enable(); break; } } while( (I2C0->STATUS & I2C_BUSY) != I2C_BUSY ); //Wait for FSM working do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; I2C_Disable(); I2C_Enable(); break; } } while(((I2C0->STATUS) & I2C_TFE) != I2C_TFE); } /*************************************************************/ //I2C WRITE nByte //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_WRITE_nByte(U8_T write_adds,volatile U8_T *i2c_data,U8_T NumByteToWrite) { U16_T R_EEROR_CONT=0; U8_T i; I2C0->DATA_CMD = I2C_CMD_WRITE|write_adds ; for(i=0;i=NumByteToWrite-1) { I2C0->DATA_CMD = *(i2c_data+i) |I2C_CMD_STOP; } else { I2C0->DATA_CMD = *(i2c_data+i); } do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; I2C_Disable(); I2C_Enable(); break; } } while( (I2C0->STATUS & I2C_BUSY) != I2C_BUSY ); //Wait for FSM working do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; I2C_Disable(); I2C_Enable(); break; } } while(((I2C0->STATUS) & I2C_TFNF) != I2C_TFNF); } } /*************************************************************/ //I2C READ OneByte //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ U8_T I2C_READ_Byte(U8_T read_adds) { U8_T value; U16_T R_EEROR_CONT=0; I2C0->DATA_CMD = I2C_CMD_WRITE|read_adds|I2C_CMD_RESTART1; I2C0->DATA_CMD = I2C_CMD_READ |I2C_CMD_STOP; do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; break; } } while( (I2C0->STATUS & I2C_BUSY) != I2C_BUSY ); //Wait for FSM working do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; break; } } while( (I2C0->STATUS & I2C_RFNE) != I2C_RFNE ); //Wait for RX done value=I2C0->DATA_CMD &0XFF; return value; } /*************************************************************/ //I2C READ nByte //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_READ_nByte(U8_T read_adds,volatile U8_T *i2c_data,U8_T NumByteToWrite) { U16_T R_EEROR_CONT=0; U8_T i; I2C0->DATA_CMD = I2C_CMD_WRITE|read_adds|I2C_CMD_RESTART1; for(i=0;i=NumByteToWrite-1) { I2C0->DATA_CMD = I2C_CMD_READ |I2C_CMD_STOP; } else { I2C0->DATA_CMD = I2C_CMD_READ; } do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; break; } } while( (I2C0->STATUS & I2C_BUSY) != I2C_BUSY ); //Wait for FSM working do { if(R_EEROR_CONT++>=10000) { R_EEROR_CONT=0; f_ERROR=1; break; } } while( (I2C0->STATUS & I2C_RFNE) != I2C_RFNE ); //Wait for RX done *(i2c_data+i)=I2C0->DATA_CMD &0XFF; } } U16_T R_READ_BUF=0; /*************************************************************/ //I2C slave Receive //EntryParameter:NONE //ReturnValue:NONE /*************************************************************/ void I2C_Slave_Receive(void) { if(!(((I2C0->MISR&I2C_SCL_SLOW)==I2C_SCL_SLOW) ||((I2C0->MISR&I2C_TX_ABRT)==I2C_TX_ABRT))) //IIC is aborted when sclk locked)) { if((I2C0->MISR&I2C_RX_FULL)==I2C_RX_FULL) //Data received? { if(RdIndex==0) { RdIndex=1; I2C_Data_Adress=I2C0->DATA_CMD&0XFF; I2C_St_Adress=I2C_Data_Adress; } else { if(I2C_Data_AdressDATA_CMD&0XFF; } I2C_Data_Adress++; } I2C0->ICR = I2C_RX_FULL; R_IIC_ERROR_CONT=0; } if((I2C0->MISR&I2C_RD_REQ)==I2C_RD_REQ) //Read request generated { if(RdIndex==1) { RdIndex=2; WrIndex = I2C_St_Adress; //I2C_ConfigInterrupt_CMD(ENABLE,I2C_TX_EMPTY); if(WrIndexDATA_CMD= (I2C0->DATA_CMD&0XFFFFFF00) |I2CWrBuffer[WrIndex]; } } I2C0->ICR = I2C_RD_REQ; R_IIC_ERROR_CONT=0; } if((I2C0->MISR&I2C_TX_EMPTY)==I2C_TX_EMPTY) //IIC send empty { if(RdIndex==2) { if(WrIndex+1DATA_CMD= (I2C0->DATA_CMD&0XFFFFFF00) |I2CWrBuffer[WrIndex+1]; } WrIndex++; } else { if(R_IIC_ERROR_CONT>10000) { I2C_Disable(); I2C0->DATA_CMD= (I2C0->DATA_CMD&0XFFFFFF00); I2C_SLAVE_CONFIG(); R_IIC_ERROR_CONT=0; } else { R_IIC_ERROR_CONT++; } } I2C0->CR = I2C_TX_EMPTY; } else if((I2C0->MISR&I2C_STOP_DET)==I2C_STOP_DET) { I2C0->ICR =I2C_STOP_DET; if(RdIndex!=0) { RdIndex=0; //I2C_ConfigInterrupt_CMD(DISABLE,I2C_TX_EMPTY); } R_READ_BUF=I2C0->DATA_CMD&0XFF; R_IIC_ERROR_CONT=0; } } else { I2C_Disable(); I2C0->DATA_CMD= (I2C0->DATA_CMD&0XFFFFFF00); I2C_SLAVE_CONFIG(); RdIndex=0; //I2C_ConfigInterrupt_CMD(ENABLE,I2C_TX_EMPTY); I2C0->ICR = I2C_SCL_SLOW|I2C_TX_ABRT; R_IIC_ERROR_CONT=0; } } /******************* (C) COPYRIGHT 2020 APT Chip *****END OF FILE****/