AnsweredAssumed Answered

I2C problems

Question asked by paternoster.cedric on Mar 26, 2014
Latest reply on Apr 2, 2014 by gonzalez.laurent
Hi

I'm trying to write and read some data into a EEPROM (AT24MAC402) with my STM32F417 in I2C but the program loops in the START and don't write or read in the EEPROM. There is a status in "stm32f4xx_i2c.c" that stays in ERROR and never past in SUCCES.
I think that the Salve Address is correct so I do not know where the problem may be

Thanks for your help
Here is my program:

/**
 ******************************************************************************
 * @file         Test_I2C/main.c
 * @author       DVC-Co
 * @version      V1.0.1
 * @date         04-February-2014
 * @brief        Main program body
 ******************************************************************************
 */


/* Includes */
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"


#define SLAVE_ADDRESS 0xA0 


/* Private variables */
uint8_t received_data[2];
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx);
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx);


/* Private function prototypes */
void init_I2C1(void);
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction);
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
void I2C_stop(I2C_TypeDef* I2Cx);


/**
**===========================================================================
**
**  Abstract: main program
**
**===========================================================================
*/
int main(void)
{


     init_I2C1(); // initialize I2C peripheral


     while(1)
     {


          I2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Transmitter); // start a transmission in Master transmitter mode
          I2C_write(I2C1, 0x20); // write one byte to the slave
          I2C_write(I2C1, 0x03); // write another byte to the slave
          I2C_stop(I2C1); // stop the transmission


          I2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Receiver); // start a transmission in Master receiver mode
          received_data[0] = I2C_read_ack(I2C1); // read one byte and request another byte
          received_data[1] = I2C_read_nack(I2C1); // read one byte and don't request another byte, stop transmission
     }
}




void init_I2C1(void)
{
     GPIO_InitTypeDef GPIO_InitStruct;
     I2C_InitTypeDef I2C_InitStruct;


     // enable APB1 peripheral clock for I2C1
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
     // enable clock for SCL and SDA pins
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);


     /* setup SCL and SDA pins
      * You can connect I2C1 to two different
      * pairs of pins:
      * 1. SCL on PB6 and SDA on PB7
      * 2. SCL on PB8 and SDA on PB9
      */
     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // we are going to use PB6 and PB7
     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;               // set pins to alternate function
     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;          // set GPIO speed
     GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;               // set output to open drain --> the line has to be only pulled low, not driven high
     GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;               // enable pull up resistors
     GPIO_Init(GPIOB, &GPIO_InitStruct);                         // init GPIOB


     // Connect I2C1 pins to AF
     GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);     // SCL
     GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA


     // configure I2C1
     I2C_InitStruct.I2C_ClockSpeed = 100000;           // 100kHz
     I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;               // I2C mode
     I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;     // 50% duty cycle --> standard
     I2C_InitStruct.I2C_OwnAddress1 = 0x00;               // own address, not relevant in master mode
     I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;          // disable acknowledge when reading (can be changed later on)
     I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses
     I2C_Init(I2C1, &I2C_InitStruct);                    // init I2C1


     // enable I2C1
     I2C_Cmd(I2C1, ENABLE);
}




void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{


     //I2C_ClearFlag(I2Cx, I2C_FLAG_BUSY);
     // wait until I2C1 is not busy anymore
     while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));


     // Send I2C1 START condition
     I2C_GenerateSTART(I2Cx, ENABLE);


     // wait for I2C1 EV5 --> Slave has acknowledged start condition
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));


     // Send slave Address for write
     I2C_Send7bitAddress(I2Cx, address, direction);


     /* wait for I2C1 EV6, check if
      * either Slave has acknowledged Master transmitter or
      * Master receiver mode, depending on the transmission
      * direction
      */
     if(direction == I2C_Direction_Transmitter)
     {
          while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
          He stuck here
     }
     else if(direction == I2C_Direction_Receiver)
     {
          while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
     }
}


/* This function transmits one byte to the slave device
 * Parameters:
 *          I2Cx --> the I2C peripheral e.g. I2C1
 *          data --> the data byte to be transmitted
 */


void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
{
     I2C_SendData(I2Cx, data);
     // wait for I2C1 EV8_2 --> byte has been transmitted
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}


/* This function reads one byte from the slave device
 * and acknowledges the byte (requests another byte)
 */
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx)
{
     // enable acknowledge of recieved data
     I2C_AcknowledgeConfig(I2Cx, ENABLE);
     // wait until one byte has been received
     while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
     // read data from I2C data register and return data byte
     uint8_t data = I2C_ReceiveData(I2Cx);
     return data;
}


/* This function reads one byte from the slave device
 * and doesn't acknowledge the recieved data
 */
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx)
{
     // disabe acknowledge of received data
     // nack also generates stop condition after last byte received
     // see reference manual for more info
     I2C_AcknowledgeConfig(I2Cx, DISABLE);
     I2C_GenerateSTOP(I2Cx, ENABLE);
     // wait until one byte has been received
     while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
     // read data from I2C data register and return data byte
     uint8_t data = I2C_ReceiveData(I2Cx);
     return data;
}


/* This funtion issues a stop condition and therefore
 * releases the bus
 */


void I2C_stop(I2C_TypeDef* I2Cx)
{
     // Send I2C1 STOP Condition
     I2C_GenerateSTOP(I2Cx, ENABLE);
}

Outcomes