cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103RB I2C problem

felipe
Associate II
Posted on March 19, 2013 at 13:12

Hi,

I am trying to comunicate with MCP23016 by i2c and i am using STM32F103RB with uVision 4.

The problem is that if I send 0x40 is the same if I send 0x41. Its the red mark on the code.

My code is:

void I2C_Configuration(void)

{    

  

I2C_InitTypeDef  I2C_InitStructure;

  

GPIO_InitTypeDef  GPIO_InitStructure;

  

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

 

  

/* Configure I2C1 pins: SCL and SDA */

  

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;

  

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

  

GPIO_Init(GPIOB, &GPIO_InitStructure);

  

/* Enable I2C1 reset state */

  

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);

  

/* Release I2C1 from reset state */

  

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);

  

/* I2C configuration */

  

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

  

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

  

I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;

  

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

  

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

  

I2C_InitStructure.I2C_ClockSpeed = 100000;

  

/* Apply I2C configuration after enabling it */

  

I2C_Cmd(I2C1,ENABLE);

  

I2C_Init(I2C1, &I2C_InitStructure); 

}

unsigned int read_MCP(u8 WriteAddress, u8 cmdByte, u8 ReadAddress, u8 NumByteToRead) {

 

  

int lsbdata, msbdata;

  

unsigned int ldata;

    

int timeout=0;

    

int indice;

     

  

while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));       

  

  

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

  

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));       /* Test on I2C1 EV5 and clear it */

            

  

I2C_Send7bitAddress(I2C1, 0x40, I2C_Direction_Transmitter);

  

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));   /* Test on EV6 and clear it */

  

I2C_ClearITPendingBit(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

             

  

I2C_SendData(I2C1, GP0);       //CONFIGURA PARA LEITURA

  

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

              

  

I2C_GenerateSTOP(I2C1, ENABLE);

  

DelayUs(100);

  

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

  

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));       /* Test on I2C1 EV5 and clear it */

                

  

I2C_Send7bitAddress(I2C1,

0x41

, I2C_Direction_Transmitter);

  

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));   /* Test on EV6 and clear it */

  

I2C_ClearITPendingBit(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

  

while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE)); 

  

lsbdata = I2C_ReceiveData(I2C2);

  

I2C_ClearITPendingBit(I2C1, I2C_FLAG_RXNE);

  

while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE)); 

  

msbdata = I2C_ReceiveData(I2C2);

  

I2C_ClearITPendingBit(I2C1, I2C_FLAG_RXNE);

  

I2C_GenerateSTOP(I2C1, ENABLE);

  

ldata = (msbdata<<8);

  

ldata = ldata + lsbdata;

  

return(ldata);

}

Thats what mcp23016 needs.

0690X0000060542QAA.png

And here the screen shot of 0x40:

0690X000006054MQAQ.png

And here the screen shot of 0x41: (nothing changes)

0690X0000060543QAA.png

I also tried another number like 0x48 and 0x49 and its the same too. I dont know what to do.

Bye bye

5 REPLIES 5
Posted on March 19, 2013 at 14:40

You might also observe the use of I2C_Send7bitAddress(), the low order bit determines the direction, the address you want for the I2C device is in the high order 7-bits. So shift your address left by one if appropriate.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
felipe
Associate II
Posted on March 19, 2013 at 17:17

You mean like if I wanna 0x41 (to read) I have to put:

I2C_Send7bitAddress(I2C1, 0x20<<1, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

Posted on March 20, 2013 at 11:23

If you decide to use the ''library'' (which in my personal opinion is a completely useless intermediary ''layer''), you are bound to read the documentation available for it. And, if everything fails, simply read the source.

void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)

{

  /* Check the parameters */

  assert_param(IS_I2C_ALL_PERIPH(I2Cx));

  assert_param(IS_I2C_DIRECTION(I2C_Direction));

  /* Test on the direction to set/reset the read/write bit */

  if (I2C_Direction != I2C_Direction_Transmitter)

  {

    /* Set the address bit0 for read */

    Address |= I2C_OAR1_ADD0;

  }

  else

  {

    /* Reset the address bit0 for write */

    Address &= (uint8_t)~((uint8_t)I2C_OAR1_ADD0);

  }

  /* Send the address */

  I2Cx->DR = Address;

}

I believe it's now clear enough.

JW

Posted on March 20, 2013 at 11:35

> You might also observe the use of I2C_Send7bitAddress(), the low order bit determines

> the direction, the address you want for the I2C device is in the high order 7-bits.

> So shift your address left by one if appropriate.

Strictly speaking, either  I2C_Send7bitAddress()  or the documentation for it is flawed. It says, verbatim:

Address: specifies the slave address which will be transmitted

According to the I2C specification, the slave address IS the upper 7 bits, so there should be no requirement to left-shift it.

I know in the industry it's customary to call both forms (shifted or not) to be the slave address, but the material which is supposed to have reference value should stick to the standards as close as possible.

It's this sloppiness which makes me further believe that using the ''library'' is superfluous if not harmful.

JW

felipe
Associate II
Posted on March 21, 2013 at 13:57

Thank you all for the tips. I get it working. I had some more problems with the  I2C_GenerateSTART and    I2C_GenerateSTOP so I use the registers and  now its fine.

Byebye