cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F3Discovery I2C EEPROM not working

pichkorsky
Associate II
Posted on June 16, 2015 at 02:56

Greetings.

I am trying to use STM32F3Discovery(STM32F303VCT6)I2C interface to communicate with24C04 EEPROM device. And as for now all my attempts failed I've decided to ask for help.

I initialize I2C1, then awrite function calls for

I2C_TransferHandling(I2C1, 0xA0, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

where 0xA0 is a EEPROM devise address and 2 is NBYTES number.

After this program stuck in a while loop waiting for TXIS flag.

By monitoring I2C_CR2 and I2C_ISR registers I've found that all my attamps ends up in two ways:

First - I2C_CR2.Start bit hangs set(1) while I2C_ISR.Busy bit is set(1) - SDA and SCL lines are released

Second- I2C_CR2.Start is reseted (0) while I2C_ISR.ARLO bit gets set (1)- SDA and SCL lines are released

STM32F30x_DSP_StdPeriph_Lib V1.2.2 is used

I will be very grateful for any help.

Also please let me know If I forgot to specify anything.

Here you can find my main.c

/* Includes ----------------------------------------------------------*/

#include ''stm32f30x.h''

#include ''stdint.h''

/* Prototypes ---------------------------------------------------------*/

void

Init_I2C1(

void

);

uint8_t WR_eePROM(

void

);

main()

{

Init_I2C1();

WR_eePROM();

while

(1) {}

return

0;

}

/* Initializing I2C1 --------------------------------------------------*/

void

Init_I2C1(

void

)

{

GPIO_InitTypeDef GPIO_InitStruct;

I2C_InitTypeDef I2C_InitStruct;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);

// +

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

// +

/* */

GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_4);

// +

GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_4);

// +

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

// +

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

// +

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

// +

GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;

// +

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOB, &GPIO_InitStruct);

// +

/* I2C_InitStuct*/

I2C_InitStruct.I2C_Timing = 0x10C08DCF;

//0xC062121F; 0x10C091CF;

I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;

// +

I2C_InitStruct.I2C_DigitalFilter = 0x00;

// +

I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;

// +

I2C_InitStruct.I2C_OwnAddress1 = 0x00;

// +

I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;

// +

I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_Init(I2C1, &I2C_InitStruct);

// +

/* Enable the I2C peripheral */

I2C_Cmd(I2C1, ENABLE);

// +

}

/*---------------------------BYTE WRITE-----------------------------------*/

uint8_t WR_eePROM(

void

)

{

// Wait if Bus is busy

while

(I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET) {}

/* Configure slave address, nbytes, reload and generate start */

I2C_TransferHandling(I2C1, 0xA0, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

/* Wait until TXIS flag is set */

while

(I2C_GetFlagStatus(I2C1, I2C_ISR_TXIS) == RESET) { }

return

0;

}

/*---------------------------------------------------------------------*/

void

assert_failed(uint8_t* file, uint32_t line){

while

(1){}}

#stm32-i2c

3 REPLIES 3
chrif
Associate II
Posted on June 29, 2015 at 11:03

Hi,

''If the flag busy'' is set before the call of ''I2C_Init'', you have to switch order of functions calls so that you configure the GPIO and enable the alternate functions first then you enable the I2C clock''.

So, move the line Regards

Greetings.

I am trying to use STM32F3Discovery(STM32F303VCT6)I2C interface to communicate with24C04 EEPROM device. And as for now all my attempts failed I've decided to ask for help. I initialize I2C1, then awrite function calls for I2C_TransferHandling(I2C1, 0xA0, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); where 0xA0 is a EEPROM devise address and 2 is NBYTES number. After this program stuck in a while loop waiting for TXIS flag. By monitoring I2C_CR2 and I2C_ISR registers I've found that all my attamps ends up in two ways: First - I2C_CR2.Start bit hangs set(1) while I2C_ISR.Busy bit is set(1) - SDA and SCL lines are released Second- I2C_CR2.Start is reseted (0) while I2C_ISR.ARLO bit gets set (1)- SDA and SCL lines are released STM32F30x_DSP_StdPeriph_Lib V1.2.2 is used I will be very grateful for any help. Also please let me know If I forgot to specify anything. Here you can find my main.c


/* Includes ----------------------------------------------------------*/

#include ''stm32f30x.h''

#include ''stdint.h''


/* Prototypes ---------------------------------------------------------*/

void

Init_I2C1(

void

);

uint8_t WR_eePROM(

void

);


main()

{

Init_I2C1();

WR_eePROM();


while

(1) {}

return

0;

}



/* Initializing I2C1 --------------------------------------------------*/

void

Init_I2C1(

void

)

{

GPIO_InitTypeDef GPIO_InitStruct;

I2C_InitTypeDef I2C_InitStruct;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);

// +

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

// +




/* */

GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_4);

// +

GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_4);

// +


GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

// +

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

// +

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

// +

GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;

// +

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOB, &GPIO_InitStruct);

// +



/* I2C_InitStuct*/

I2C_InitStruct.I2C_Timing = 0x10C08DCF;

//0xC062121F; 0x10C091CF;

I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;

// +

I2C_InitStruct.I2C_DigitalFilter = 0x00;

// +

I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;

// +

I2C_InitStruct.I2C_OwnAddress1 = 0x00;

// +

I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;

// +

I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;


I2C_Init(I2C1, &I2C_InitStruct);

// +


/* Enable the I2C peripheral */

I2C_Cmd(I2C1, ENABLE);

// +




}



/*---------------------------BYTE WRITE-----------------------------------*/



uint8_t WR_eePROM(

void

)

{

// Wait if Bus is busy

while

(I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET) {}


/* Configure slave address, nbytes, reload and generate start */

I2C_TransferHandling(I2C1, 0xA0, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);



/* Wait until TXIS flag is set */

while

(I2C_GetFlagStatus(I2C1, I2C_ISR_TXIS) == RESET) { }

return

0;

}



/*---------------------------------------------------------------------*/



void

assert_failed(uint8_t* file, uint32_t line){

while

(1){}}

pichkorsky
Associate II
Posted on July 20, 2015 at 20:27

Thank you for advice.

I've moved the line 30, made some other changes, switched to the 'onboard'accelerometer and practiced more. Now I am able to write and read his registers just fine using the I2C interface. But still have problem with breadboarded EEPROM. I am usingsolderless breadboard for this with 2x4.7kOhm resistors to pull-up the SCL and SDA lines. By the way - how can I figure on which speed my I2C is working now, and how I can config this? Here are my recent read/write functions (in case they will come handy for someone StdPeriph V1.2.2 is used)

uint8_t Accel_Read(uint8_t Addr_to_read) 
{
uint8_t Data = 0;
// check bus busy status - generate START - wait TXE
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET) {}
I2C_TransferHandling(I2C1, LINEAR_ACCELERATION_W, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_TXE) == RESET) {} 
I2C_SendData(I2C1, Addr_to_read); 
// choosing sub address
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_TXE) == RESET) {}
// re-start - read request - receive data -
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) != RESET) {}
I2C_TransferHandling(I2C1, LINEAR_ACCELERATION_R, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET) {}
Data = I2C_ReceiveData(I2C1);
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) != RESET) {} 
// wait STOPF - clr STOPF
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET) {} 
I2C1 ->ICR = (1 << 5);
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) != RESET) {} 
return
Data;
}
void
Config_Accel(uint8_t Reg_Add, uint8_t Reg_Value)
{
// check bus busy status - generate START - wait TXE
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET) {}
I2C_TransferHandling(I2C1, LINEAR_ACCELERATION_W, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_TXE) == RESET) {} 
I2C_SendData(I2C1, Reg_Add); 
// appeal to CTRL_REG1_A
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_TXE) == RESET) 
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET) {} 
I2C_TransferHandling(I2C1, LINEAR_ACCELERATION_W, 1, I2C_AutoEnd_Mode, I2C_No_StartStop);
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_TXE) == RESET) {} 
I2C_SendData(I2C1, Reg_Value); 
// Set LIS3DH to low power mode with ODR = 25Hz. 0011 1111
while
(I2C_GetFlagStatus(I2C1, I2C_ISR_TXE) == RESET) {} 
// wait STOPF - clr STOPF
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET) {} 
I2C1 ->ICR = (1 << 5);
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) != RESET) {} 
}

pichkorsky
Associate II
Posted on July 22, 2015 at 01:44

The case is solved.

It turned out that I was trying to connect 5V powered EEPROM with ~3V powered MCU while I2C SDA and SCL line where pulled-up  with resistors to 5V.

All troubles gone when I switched EEPROM and SDA/SCL lines to the ~3V power supply.