2012-05-26 01:14 AM
Hi guys,
I'm working on a STM32F4 Discovery board and trying send over I2C. Therefore I'm using the functions from the Standard Peripheral Library. Unfortunately the device stucks after sending the address while checking theI2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
Here is my initialization:#define IMU_I2C I2C1
#define IMU_I2C_CLK RCC_APB1Periph_I2C1
#define IMU_I2C_SCL_PIN GPIO_Pin_6
#define IMU_I2C_SCL_GPIO_PORT GPIOB
#define IMU_I2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
#define IMU_I2C_SCL_SOURCE GPIO_PinSource6
#define IMU_I2C_SCL_AF GPIO_AF_I2C1
#define IMU_I2C_SDA_PIN GPIO_Pin_9
#define IMU_I2C_SDA_GPIO_PORT GPIOB
#define IMU_I2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
#define IMU_I2C_SDA_SOURCE GPIO_PinSource9
#define IMU_I2C_SDA_AF GPIO_AF_I2C1
void
i2c_init(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// Enable Clk
RCC_APB1PeriphClockCmd(IMU_I2C_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(IMU_I2C_SCL_GPIO_CLK | IMU_I2C_SDA_GPIO_CLK, ENABLE);
// Performing a Reset
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_APB1PeriphResetCmd(IMU_I2C_CLK, ENABLE);
RCC_APB1PeriphResetCmd(IMU_I2C_CLK, DISABLE);
// Remap Pins
GPIO_PinAFConfig(IMU_I2C_SCL_GPIO_PORT, IMU_I2C_SCL_SOURCE, IMU_I2C_SCL_AF);
GPIO_PinAFConfig(IMU_I2C_SDA_GPIO_PORT, IMU_I2C_SDA_SOURCE, IMU_I2C_SDA_AF);
// Initialize SCL
GPIO_InitStructure.GPIO_Pin = IMU_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IMU_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
// Initialize SDA
GPIO_InitStructure.GPIO_Pin = IMU_I2C_SDA_PIN;
GPIO_Init(IMU_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
// I2C configuration
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Cmd(IMU_I2C, ENABLE);
I2C_Init(IMU_I2C, &I2C_InitStructure);
}
My sending function is like the examples from ST but it stucks after sending the address while checking the EV6 flag.
void
i2c_write_buf(uint8_t address, uint8_t* buf, int32_t len)
{
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
/* Send I2C1 START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on I2C1 EV5 and clear it */
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send slave Address for write */
I2C_Send7bitAddress(I2C1, address, I2C_Direction_Transmitter);
/* Test on I2C1 EV6 and clear it */
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//I2C stucks here!!!
while
(len--)
{
/* Send I2C1 slave register address */
I2C_SendData(I2C1, *buf++);
/* Test on I2C1 EV8_2 and clear it */
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
/* Send I2C1 STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE);
}
For initialization and sending I followed the examples from ST. On the I2C pins the is a magnetometer with external pullups.
Does anyone know where there is a mistake??
Thanks, Robert
#stm32-i2c-master
2012-05-26 05:58 AM
My device has a 7-bit address of 0x68 and I do use the one byte left shifted 0xD0.
2012-05-27 05:12 AM
At least for the M3 devices, especially the stm32f10x, there is a corresponding entry in the errata sheet. The peripheral my get stuck if not all EV_<x> events are handled.
This issue is supposedly fixed, as tThe stm32f4 errata sheet does not list it. I must admit, after reading the first posts of frustrated users, I switched back to bit-banging. It's more resource hungry, but works The 7-bit slave address is a common source of confusion. This address is completed with the access type (read/write), which defines the LSB. Effectively, this forms an 8-bit address, where each device consumes two addresses. You might need to consult the reference manual how the regarding peripheral register handles this. If you check the bus with a scope, you will need to see a 0xD0 or oxD1 as address, i.e. the left-shifted variant.2012-05-27 07:37 AM
Today I found out that the schematic for my breakout board was wrong. My chip does not use address 0x68 - it uses 0x69. For this reason I got no ACK and therefore the communication stucked.
2013-08-31 05:12 PM
I have same problem getting stuck on EV6 using I2C1 (PB08 & PB09) on a
STM32F4 Discovery board with BB and Display.I shift the 7-bit Slave address and verify proper bits on SDA followed by theslave ACK on SDA. I can verify that using the wrong address, I do not get the ACK from the slave on SDA.My problem with getting stuck at EV6 is that STM32F4 gives a 10-bit AddressACK (I2C_EVENT_MASTER_MODE_ADDRESS10) instead of 7-bit addressACK (I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED).Below is my initialization, configuring 7-bit address mode. please advise.-Ramin___________________________________________________________/******************************************************************************** Function Name : I2C_BusInit* Description : Configure I2C-Bus* Input : None* Output : None* Return : None* Attention : None*******************************************************************************/void I2C_BusInit(void){ GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; uint32_t timeout = (100 * I2C_TIMEOUT); // RAMIN int i; // Ramin// I2C_DeInit(Open_I2C); //========================================================================================= // Enable I2C CLOCK //----------------------------------------------------------------------------------------- RCC_APB1PeriphClockCmd(Open_I2C_CLK, ENABLE); //========================================================================================= // Enable GPIO CLOCK: For the SCL/SDA Pins //----------------------------------------------------------------------------------------- RCC_AHB1PeriphClockCmd(Open_I2C_SCL_GPIO_CLK | Open_I2C_SDA_GPIO_CLK, ENABLE); //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // ?????????????????? RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // Performing a Reset RCC_APB1PeriphResetCmd(Open_I2C_CLK, ENABLE); // ? RCC_APB1PeriphResetCmd(Open_I2C_CLK, DISABLE); // ? //========================================================================================= // Pemap Pins: GPIO Alternate functions configuration (Connect GPIO pins to peripheral) //----------------------------------------------------------------------------------------- GPIO_PinAFConfig(Open_I2C_SCL_GPIO_PORT, Open_I2C_SCL_SOURCE, Open_I2C_SCL_AF); GPIO_PinAFConfig(Open_I2C_SDA_GPIO_PORT, Open_I2C_SDA_SOURCE, Open_I2C_SDA_AF); // ********************************************************************************// for (i=0; i<timeout; i++); // ***************** DELAY HARD CODED ****************** // ******************************************************************************** //========================================================================================= // GPIO INITIALIZATION: Configure I2C SCL & SDA GPIO 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_Pin_6, GPIO_Pin_7 for PB6 and PB7 GPIO_Pin_8, GPIO_Pin_9 for PB8 and PB9 */ //----------------------------------------------------------------------------------------- GPIO_InitStructure.GPIO_Pin = Open_I2C_SCL_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // set pins to alternate function GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // set GPIO speed GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // Open Drain GPIO_OType_OD --> Line has to be only pulled low, not driven high GPIO_OType_PP GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // enable pull up resistors ?????? GPIO_PuPd_UP; (GPIO_PuPd_NOPULL)//GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; // enable pull up resistors ?????? GPIO_PuPd_UP; (GPIO_PuPd_NOPULL) /* Configure I2C pins: SCL */ GPIO_Init(Open_I2C_SCL_GPIO_PORT, &GPIO_InitStructure); // init GPIOB /* Configure I2C pins: SDA */ GPIO_InitStructure.GPIO_Pin = Open_I2C_SDA_PIN; GPIO_Init(Open_I2C_SCL_GPIO_PORT, &GPIO_InitStructure); // init GPIOB //========================================================================================= // Configure I2C CONTROLLER // Apply I2C configuration after enabling it //----------------------------------------------------------------------------------------- I2C_InitStructure.I2C_ClockSpeed = I2C_SCL_SPEED; // 100 KHz (400kHz = Fast Mode) I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // I2C mode I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 50% duty cycle --> standard I2C_InitStructure.I2C_OwnAddress1 = 0; // I2C_OWN_ADDR; // own address, not relevant in master mode I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // I2C_Ack_Enable/I2C_Ack_Disable; Disable ACK when reading (can be changed later on) I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //========================================================================================= // Enable I2C PORT //----------------------------------------------------------------------------------------- I2C_Cmd(Open_I2C, ENABLE); I2C_Init(Open_I2C, &I2C_InitStructure); //========================================================================================= // Configure the SPI interrupt priority //-----------------------------------------------------------------------------------------//NVIC_InitStructure.NVIC_IRQChannel = Open_I2C_IRQn;// NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;// NVIC_Init(&NVIC_InitStructure);// I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT, ENABLE);// I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT, ENABLE);// I2C_GenerateSTART(I2C1, ENABLE);}