cancel
Showing results for 
Search instead for 
Did you mean: 

I2C problems - ADDR bit is not set

salahuddinash
Associate II
Posted on May 24, 2014 at 11:45

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 

<b>I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)</b>

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 

<b>

#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){

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

}

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

while(1);

}

</b>

now what's the problem ??
0 REPLIES 0