AnsweredAssumed Answered

I2C problems - ADDR bit is not set

Question asked by ashraf.salahuddin on May 24, 2014
Hi everyone, 
I'm trying to implement I2C1 on stm32f4-discovery to let the kit contact with a light-to-digital sensor TSL2581CS ..
In the following code, the 


returns ERROR although, BUSY, MSL, TxE and TRA are set and the AF bit is not set meaning that the address sent is acknowledged !!?? 

here's the whole code 
#include <stm32f4xx.h>

// this slave address belongs to the STM32F4-Discovery board's 
#define SLAVE_ADDRESS 0x39 // the slave address (example)

void I2C1_init(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 the I2C1 functions to two different
      * pins:
      * 1. SCL on PB6 or PB8  
      * 2. SDA on PB7 or PB9
     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;       // we are going to use PB6 and PB9
     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);

/* This function issues a start condition and 
 * transmits the slave address + R/W bit
 * Parameters:
 *           I2Cx --> the I2C peripheral e.g. I2C1
 *           address --> the 7 bit slave address
 *           direction --> the transmission direction can be:
 *                               I2C_Direction_Tranmitter for Master transmitter mode
 *                               I2C_Direction_Receiver for Master receiver
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction){
      * EV5 : start bit sent (BUSY, MSL, SB)
      * EV6 : slave acknowledged address (BUSY, MSL, ADDR)
      * EV8 : DR ready for new byte to transmit, transmit buffer empty (BUSY, MSL, TxE)
      * EV9 : new byte received in the DR, receive buffer not empty (BUSY, MSL, RxNE) 
     // Wait until I2C1 is not busy any more ## Check flag BUSY = 0 
     while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
     // Send I2C1 START condition            ## Signal START on the bus 
     I2C_GenerateSTART(I2Cx, ENABLE);

     // Wait for I2C1 EV5(BUSY,MSL,SB)--> Slave has acknowledged start condition ## START correct
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

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

     /* wait for I2Cx EV6 (BUSY, MSL, ADDR, TXE,TRA), check if 
      * either Slave has acknowledged Master transmitter or
      * Master receiver mode, depending on the transmission direction  ##Slave address acknowledged
     if(direction == I2C_Direction_Transmitter){
     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)
     // wait for I2C1 EV8 --> last byte is still being transmitted (last byte in SR, buffer empty), next byte can already be written
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
     I2C_SendData(I2Cx, data);

/* This function reads one byte from the slave device 
 * and acknowledges the byte (requests another byte)
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx){
     uint8_t data;
     // enable acknowledge of received 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
     data = I2C_ReceiveData(I2Cx);
     return data;

/* This function reads one byte from the slave device
 * and doesn't acknowledge the received data 
 * after that a STOP condition is transmitted
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx){
     uint8_t data;
     // disable 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
     data = I2C_ReceiveData(I2Cx);
     return data;

/* This function issues a stop condition and therefore
 * releases the bus
void I2C_stop(I2C_TypeDef* I2Cx){

     // Send I2C1 STOP Condition after last byte has been transmitted
     I2C_GenerateSTOP(I2Cx, ENABLE);
     // wait for I2C1 EV8_2 --> byte has been transmitted
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

int main(void){
     uint8_t received_data;
     received_data += 0;
     I2C1_init();                                                                                                                     // initialize I2C peripheral

     I2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Transmitter); // start a transmission in Master transmitter mode
     I2C_write(I2C1, 0x01);                                                                                            // write one 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 = I2C_read_nack(I2C1); // read one byte and don't request another byte, stop transmission


now what's the problem ??