We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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.
Incorrect!
LPC_I2C->CONSET |= 0x14; LPC_I2C->CONSET |= 0x20;
LPC_I2C->CONSET = 0x??;
You also need to wait for an SI (I2C interrupt flag), which means the change of I2C Bus status.
You also need to wait for an SI (I2C interrupt flag), which means the change of I2C Bus status. ----------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------
I did not understand properly, what you are saying, which line is incorrect and of which function.
and what is this LPC_I2C->CONSET = 0x??; Its showing question marks on the right hand side.
Apart from this only a single I2C device is connected with the LPC1343, and i am going to use interrupt and SI Flag if this method don't work for me.
Actually i had adapted this code from LPC2148 I2C Code used for interfacing EEPROM sites.google.com/.../eeprom24c02
I checked all registers and configured them according to Cortex-M3 based LPC1343.
www.lpcware.com/.../code.bundle.lpc13xx.keil__3.zip
Use the above example code as your code base.
I think LPC_I2C->CONSET = 0x14; is better than LPC_I2C->CONSET |= 0x14;
Sorry for that I did not reply well.
void I2C_Start(void) { LPC_I2C->CONSET = 0x20; //Set the Start Bit while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); UART_Write(LPC_I2C->STAT); } void I2C_Restart(void) { LPC_I2C->CONSET = 0x20; //Set the Start Bit while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); UART_Write(LPC_I2C->STAT); } 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->CONSET & I2C_I2CONSET_SI)); UART_Write(LPC_I2C->STAT); } unsigned char I2C_Read(void) { LPC_I2C->CONCLR = 0X28; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); return(LPC_I2C->DAT); UART_Write(LPC_I2C->STAT); }
Replace your functions with the above, and test it.
unsigned char I2C_Read(void) { LPC_I2C->CONCLR = 0X28; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)); UART_Write(LPC_I2C->STAT); return(LPC_I2C->DAT); }
I made too many mistakes.
The mentioned code bundle uses interrupt, but polling would be better for you.
Thanks for your reply, i tried the above code as but it is giving the same result as given previously without any change. For Start Condition i am getting Status = 0x08 For Write Address Condition i am getting Status = 0x18 For Writing to Address i am getting Status = 0x28 For Repeated Start condition i am getting Status = 0x28 (which is incorrect it must be 0x10 here)
I don't know what to do now.
I will give a try to the Interrupt method but dont think it will work because Interrupt in the second polling based code i had use the SI interrupt.
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); }