I'm trying to write to an EEPROM and can't seem to be able to generate a STOP signal. I've checked the registers in debug mode and the RXAK bit does not reset, so I'm not able to correctly poll the ACK bit. All of this is without Processor Expert.
I'm using the Freedom Board with the KL25z128.
The pull-ups are 4.7k and are externally connected to the EEPROM on a separate circuit board.
This is the Code I'm using.
/*
* main implementation: use this 'C' sample to create your own application
*
*/
#include "derivative.h" /* include peripheral declarations */
int config(void);
int i2cinit(void);
void EEPROMWrite(uint8_t addr, uint8_t data);
int main(void)
{
int i;
uint8_t d;
config(); //Start Hardware configuration
i2cinit(); //Start I2C Configuration
EEPROMWrite(0x11, 0xAA);
}
int config(void)
{
//Configuration
SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK |
SIM_SCGC5_PORTD_MASK |
SIM_SCGC5_PORTC_MASK |
SIM_SCGC5_PORTB_MASK |
SIM_SCGC5_PORTA_MASK; /* Enable clock gate for ports to enable pin routing */
/* SIM_CLKDIV1: OUTDIV1=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,OUTDIV4=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
SIM_CLKDIV1 = 0x00U; /* Update system prescalers */
/* SIM_SOPT2: PLLFLLSEL=0 */
SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_PLLFLLSEL_MASK); /* Select FLL as a clock source for various peripherals */
/* SIM_SOPT1: OSC32KSEL=3 */
SIM_SOPT1 |= SIM_SOPT1_OSC32KSEL(0x03); /* LPO 1kHz oscillator drives 32 kHz clock for various peripherals */
/* SIM_SOPT2: TPMSRC=1 */
SIM_SOPT2 = (uint32_t)((SIM_SOPT2 & (uint32_t)~(uint32_t)(
SIM_SOPT2_TPMSRC(0x02)
)) | (uint32_t)(
SIM_SOPT2_TPMSRC(0x01)
)); /* Set the TPM clock */
/* Switch to FEI Mode */
/* MCG_C1: CLKS=0,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */
MCG_C1 = (MCG_C1_IREFS_MASK | MCG_C1_IRCLKEN_MASK);
/* MCG_C2: LOCRE0=0,??=0,RANGE0=0,HGO0=0,EREFS0=0,LP=0,IRCS=0 */
MCG_C2 = 0x00U;
/* MCG_C4: DMX32=0,DRST_DRS=0 */
MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03)));
/* OSC0_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
OSC0_CR = OSC_CR_ERCLKEN_MASK;
/* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=0 */
MCG_C5 = 0x00U;
/* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
MCG_C6 = 0x00U;
while((MCG_S & MCG_S_IREFST_MASK) == 0x00U) { /* Check that the source of the FLL reference clock is the internal reference clock. */
}
while((MCG_S & 0x0CU) != 0x00U) { /* Wait until output of the FLL is selected */
}
}
int i2cinit(void)
{
/* SIM_SCGC4: I2C0=1 */
SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;
/* I2C0_C1: IICEN=0,IICIE=0,MST=0,TX=0,TXAK=0,RSTA=0,WUEN=0,DMAEN=0 */
I2C1_C1 = 0x00U; /* Clear control register */
/* I2C0_FLT: SHEN=0,STOPF=1,STOPIE=0,FLT=0 */
I2C1_FLT = I2C_FLT_STOPF_MASK; /* Clear bus status interrupt flags */
/* I2C0_S: TCF=0,IAAS=0,BUSY=0,ARBL=0,RAM=0,SRW=0,IICIF=1,RXAK=0 */
I2C1_S = I2C_S_IICIF_MASK; /* Clear interrupt flag */
PORTE_PCR0 &= ~(PORT_PCR_MUX_MASK);
PORTE_PCR0 |= (PORT_PCR_MUX(6));
PORTE_PCR1 &= ~(PORT_PCR_MUX_MASK);
PORTE_PCR1 |= (PORT_PCR_MUX(6));
/* I2C0_C2: GCAEN=0,ADEXT=0,HDRS=0,SBRC=0,RMEN=0,AD=0 */
I2C1_C2 = 0x00U;
/* I2C0_FLT: SHEN=0,STOPF=0,STOPIE=0,FLT=0 */
I2C1_FLT = 0x00U; /* Set glitch filter register */
/* I2C0_SMB: FACK=0,ALERTEN=0,SIICAEN=0,TCKSEL=0,SLTF=1,SHTF1=0,SHTF2=0,SHTF2IE=0 */
I2C1_SMB = I2C_SMB_SLTF_MASK;
/* I2C0_F: MULT=0,ICR=0 */
I2C1_F = 0x00U; /* Set prescaler bits */
I2C1_C1 |=(I2C_C1_IICEN_MASK|I2C_C1_IICIE_MASK|I2C_C1_TXAK_MASK);
}
void EEPROMWrite(uint8_t addr, uint8_t data)
{
int i;
I2C1_C1 |= I2C_C1_TX_MASK; //Enable Transmit
I2C1_C1 |= I2C_C1_MST_MASK; //Enable Master Mode (Send Start Signal)
I2C1_D = 0xA0; //Send Write Command to EEPROM (Addr. 1010xxx0)
while(!(I2C1_S & I2C_S_TCF_MASK)); //Waits until transfer is finished
if((I2C1_S & I2C_S_RXAK_MASK) == 0x00) //If ACK received
{
I2C1_C1|=I2C_C1_TXAK_MASK; //Reset ACK Flag
I2C1_D = addr; //Send Address to write
while(!(I2C1_S & I2C_S_TCF_MASK)); //Waits until transfer is finished
if((I2C1_S & I2C_S_RXAK_MASK) == 0x00) //If ACK received
{
I2C1_C1|=I2C_C1_TXAK_MASK; //Reset ACK Flag
I2C1_D = data; //Send Data
while(!(I2C1_S & I2C_S_TCF_MASK)); //Waits until transfer is finished
if((I2C1_S & I2C_S_RXAK_MASK) == 0x00) //if ACK received
{
I2C1_C1|=I2C_C1_TXAK_MASK; //Reset ACK Flag
I2C1_C1 &= ~(I2C_C1_MST_MASK); //Disable Master Mode (Send Stop Signal)
}//end if((I2C1_S & I2C_S_RXAK_MASK) == 0x00)
}//end if((I2C1_S & I2C_S_RXAK_MASK) == 0x00)
}//end if((I2C1_S & I2C_S_RXAK_MASK) == 0x00)
}
I'm using a Logic Device that shows this:
Any help will be appreciated.
Thanks.
Hi Jaime,
I am not really sure about what you are missing or what is wrong. In the attachments you can find the initialization code and driver for I2C for FRDM-KL25Z and, also the functions to configure, write and read to/from Accelerometer MMA8451.
I think is better to check for IICIF (Interrupt Flag) register to ensure complete transfer and ACK return.
Hope this helps.
Hello, Adrian,
I am using your I2C library on Kl26Z Microcontroller to store data on EEPROM 24AA01T. Whenever I write on particular location say 0x01 and try to read that using I2C read function I always get 255.
Below is my main.c which uses your I2C library.
hal_i2c0_init(I2C0_BASE_PTR);
send_string_debug("I2C Writing...\r\n"); //Sent to Terminal
I2C_write(0xA0,0x01,32);
send_string_debug("I2C Writing Done...\r\n"); ////Sent to Terminal
delay(1000);
send_string_debug("I2C Reading...\r\n"); ////Sent to Terminal
I2C_R=I2C_Read(0xA0,0x01);
send_string_debug("I2C Reading Done...\r\n"); ////Sent to Terminal
sprintf(VR,"I2C Value is %d\r\n",I2C_R); //Converting to String
send_string_debug(VR); //Sent to Terminal
What do you think could be wrong here?
Thanks
Modify your post and style your code (use the advanced editor and select c++ syntax).
All of this is without Processor Expert. Just curious, Why?
I have the same problem! Can anybody help here please? Any help will be appreciated! Best regards!
See if this helps any:
KL25Z and I2C: Missing Repeated Start Condition | MCU on Eclipse