Hello!! Everyone i am working on LPC1343 Micro-controller and wants to interface RTCC PCF8523 with LPC1343.
I write code for I2C protocol but its not working. The problem is found when i send repeated start from master (LPC1343), the status for this must be 0x10 while i am getting 0x28 every time.
The full code can be downloaded from here:- www.edaboard.com/.../107170d1404924341-pcf8523_rtcc.zip (Its EDABOARD Link Sorry, i dont know how to attach files here.)
The functions used for I2C Protocol are as follow:-
#include "LPC13xx.h" #include "I2C.h" #include "UART.h" void I2C_Init(unsigned char Mode) { LPC_SYSCON->PRESETCTRL |= (1<<1); //De-Asserts Reset Signal to I2C LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); //Enable I2C Clock LPC_IOCON->PIO0_4 &= ~0x3F; LPC_IOCON->PIO0_4 |= 0x01; //SCL LPC_IOCON->PIO0_5 &= ~0x3F; LPC_IOCON->PIO0_5 |= 0x01; //SDA if(Mode == I2C_SPEED_400) { LPC_I2C->SCLH = 90; //I2PCLK is 72MHz LPC_I2C->SCLL = 90; //I2PCLK is 72MHz } else if(Mode == I2C_SPEED_100) { LPC_I2C->SCLH = 360; //I2PCLK is 72MHz LPC_I2C->SCLL = 360; //I2PCLK is 72MHz } LPC_I2C->CONCLR = 0xFF; //Clear All Flags LPC_I2C->CONSET = (1<<6); //I2C Interface Enable } void I2C_Start(void) { LPC_I2C->CONSET |= 0x20; //Set the Start Bit while(LPC_I2C->STAT!=0x08); //Wait for the Status Bit } void I2C_Restart(void) { LPC_I2C->CONSET |= 0x20; //Set the Start Bit while(LPC_I2C->STAT!=0x10); //Wait for the Status Bit } void I2C_Stop(void) { LPC_I2C->CONSET |= 0x14; //Stop I2C LPC_I2C->CONCLR = 0x08; } void I2C_Write(unsigned char data,unsigned char status) { LPC_I2C->DAT = data; LPC_I2C->CONCLR = 0X28; //Clear Start Flag and SI Interrupt while(LPC_I2C->STAT!=status); //Wait for the Status Byte } unsigned char I2C_Read(void) { LPC_I2C->CONCLR = 0X28; while (LPC_I2C->STAT!=0x50); //Wait for Status Set - 0x50 return(LPC_I2C->DAT); }
In function Read from RTCC (given below)
unsigned char PCF8523_Read(unsigned char Address) { unsigned char temp; I2C_Start(); UART_Write('1'); I2C_Write(PC8523_ADDRESS,0x18); UART_Write('2'); I2C_Write(Address,0x28); UART_Write('3'); I2C_Restart(); UART_Write('4'); I2C_Write(PC8523_ADDRESS+1,0x40); UART_Write('5'); temp = I2C_Read(); UART_Write('6'); I2C_Stop(); UART_Write('7'); return temp; }[/pre> As i dont have debugger i checked the content of Status Bytes on UART, i found that for I2c_Start, the status byte contains 0x08 when sending rtcc address i am getting status = 0x18 and then after sending the address from where i have to read i am getting status = 0x28 which is correct. Upto this point i am getting valid status responses, but after sending Repeated Start i am getting 0x28 each and every time continuously. Can anyone please help me to solve this issue.
The below code has been tested OK with my LPC1343 and DS3231 (My I2C-Slave, I don't have PCF8523). I assume your I2C_Init() is correct.
#include <LPC13xx.h> #define I2C_I2CONSET_AA ((0x04)) #define I2C_I2CONSET_SI ((0x08)) #define I2C_I2CONSET_STO ((0x10)) #define I2C_I2CONSET_STA ((0x20)) #define I2C_I2CONSET_I2EN ((0x40)) #define I2C_I2CONCLR_AAC ((1<<2)) #define I2C_I2CONCLR_SIC ((1<<3)) #define I2C_I2CONCLR_STOC ((1<<4)) #define I2C_I2CONCLR_STAC ((1<<5)) #define I2C_I2CONCLR_I2ENC ((1<<6)) #define I2C_STAT_CODE_BITMASK ((0xF8)) #define I2C_I2STAT_M_TX_START ((0x08)) #define I2C_I2STAT_M_TX_RESTART ((0x10)) #define I2C_I2STAT_M_TX_SLAW_ACK ((0x18)) #define I2C_I2STAT_M_TX_SLAW_NACK ((0x20)) #define I2C_I2STAT_M_TX_DAT_ACK ((0x28)) #define I2C_I2STAT_M_TX_DAT_NACK ((0x30)) #define I2C_I2STAT_M_TX_ARB_LOST ((0x38)) #define I2C_I2STAT_M_RX_START ((0x08)) #define I2C_I2STAT_M_RX_RESTART ((0x10)) #define I2C_I2STAT_M_RX_SLAR_ACK ((0x40)) #define I2C_I2STAT_M_RX_SLAR_NACK ((0x48)) #define I2C_I2STAT_M_RX_DAT_ACK ((0x50)) #define I2C_I2STAT_M_RX_DAT_NACK ((0x58)) #define I2C_I2DAT_BITMASK ((0xFF)) void I2C_Init( LPC_I2C_TypeDef *I2Cx, uint32_t clockrate ); uint32_t I2C_Start(void) { LPC_I2C->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; LPC_I2C->CONSET = I2C_I2CONSET_STA; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); return (LPC_I2C->STAT & I2C_STAT_CODE_BITMASK); } void I2C_Stop(void) { LPC_I2C->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; LPC_I2C->CONSET = I2C_I2CONSET_STO; while (LPC_I2C->CONSET & I2C_I2CONSET_STO); } uint32_t I2C_Write(unsigned char data) { LPC_I2C->DAT = data; LPC_I2C->CONCLR = I2C_I2CONCLR_SIC; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); return (LPC_I2C->STAT & I2C_STAT_CODE_BITMASK); } unsigned char Slave_Read(unsigned char Address) { uint8_t result; if ( I2C_Start() == I2C_I2STAT_M_TX_START ) { LPC_I2C->CONCLR = I2C_I2CONCLR_STAC; if ( I2C_Write(Address) == I2C_I2STAT_M_TX_SLAW_ACK ) { if ( I2C_Start() == I2C_I2STAT_M_TX_RESTART ) { if ( I2C_Write( Address | 0x1 ) == I2C_I2STAT_M_RX_SLAR_ACK ) { LPC_I2C->CONCLR = I2C_I2CONCLR_AAC; LPC_I2C->CONCLR = I2C_I2CONCLR_SIC; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); result = (uint8_t)(LPC_I2C->DAT & I2C_I2DAT_BITMASK); I2C_Stop(); return result; } } } } I2C_Stop(); return 0xE8; } int main(void) { volatile uint8_t result; I2C_Init( LPC_I2C, 100000 ); while(1) { result = Slave_Read(0xD0); /* Check result */ } }
Hello!! The code is working now, i had not cleared the SI Flag when using Repeated Restart Function.
Here is the Updated and Working I2C Functions for LPC1343
#include "LPC13xx.h" #include "I2C.h" void I2C_Init(unsigned char Mode) { LPC_SYSCON->PRESETCTRL |= (1<<1); //De-Asserts Reset Signal to I2C LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); //Enable I2C Clock LPC_IOCON->PIO0_4 &= ~0x3F; LPC_IOCON->PIO0_4 |= 0x01; //SCL LPC_IOCON->PIO0_5 &= ~0x3F; LPC_IOCON->PIO0_5 |= 0x01; //SDA if(Mode == I2C_SPEED_400) { LPC_I2C->SCLH = 90; //I2PCLK is 72MHz LPC_I2C->SCLL = 90; //I2PCLK is 72MHz } else if(Mode == I2C_SPEED_100) { LPC_I2C->SCLH = 360; //I2PCLK is 72MHz LPC_I2C->SCLL = 360; //I2PCLK is 72MHz } LPC_I2C->CONCLR = 0xFF; //Clear All Flags LPC_I2C->CONSET = (1<<6); //I2C Interface Enable } void I2C_Start(void) { LPC_I2C->CONCLR = 0X28; LPC_I2C->CONSET |= 0x20; //Set the Start Bit while(LPC_I2C->STAT!=0x08); //Wait for the Status Bit } void I2C_Restart(void) { LPC_I2C->CONCLR = 0X28; LPC_I2C->CONSET |= 0x20; //Set the Start Bit while(LPC_I2C->STAT!=0x10); //Wait for the Status Bit } void I2C_Stop(void) { LPC_I2C->CONSET |= 0x14; //Stop I2C LPC_I2C->CONCLR = 0x08; } void I2C_Write(unsigned char data,unsigned char status) { LPC_I2C->CONCLR = 0X28; LPC_I2C->DAT = data; LPC_I2C->CONCLR = 0X28; //Clear Start Flag and SI Interrupt while(LPC_I2C->STAT!=status); //Wait for the Status Byte } unsigned char I2C_Read(void) { LPC_I2C->CONCLR = 0X2C; //Cleat SI and Asset Acknowledgment Flag while(LPC_I2C->STAT!=0x58); return(LPC_I2C->DAT); }