2013-03-19 05:12 AM
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.
And here the screen shot of 0x40:
And here the screen shot of 0x41: (nothing changes)
I also tried another number like 0x48 and 0x49 and its the same too. I dont know what to do.
Bye bye
2013-03-19 06:40 AM
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.
2013-03-19 09:17 AM
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));
2013-03-20 03:23 AM
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. JW2013-03-20 03:35 AM
> 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.
JW2013-03-21 05:57 AM