K
K
Kopranych2016-11-20 16:03:31
Microcontrollers
Kopranych, 2016-11-20 16:03:31

STM32F4 discovery how to make interrupts work on the I2C bus?

Working on the i2c bus in the flags waiting mode, the controller receives data. I decided to do work on interrupts, but after generating the START condition, the interrupt does not occur, the program is executed further. Maybe wrong initialization? Tell me who knows.
The code:

void I2C_init(void)
{
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//тактируем пины для i2c
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);//тактируем сам i2c
   //--------------------------------------------
   GPIO_InitTypeDef busi2c;//создаем структуры 
   I2C_InitTypeDef i2c;//для инициализации
   //------------------------------------
   i2c.I2C_ClockSpeed = 100000;//100kHz
   i2c.I2C_Mode = I2C_Mode_I2C;
  i2c.I2C_DutyCycle = I2C_DutyCycle_2;
  i2c.I2C_OwnAddress1 = OWNADRESS;
  i2c.I2C_Ack = I2C_Ack_Enable;
  i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_Init(I2C1, &i2c);
   //---------------------------------------
   busi2c.GPIO_Pin = BUS_SCL|BUS_SDA;
   busi2c.GPIO_Mode = GPIO_Mode_AF;
   busi2c.GPIO_Speed = GPIO_Speed_2MHz;
   busi2c.GPIO_OType = GPIO_OType_OD;
   busi2c.GPIO_PuPd = GPIO_PuPd_UP;
   GPIO_Init(GPIOB, &busi2c);
   //---------------------------------------------
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);//включаем альтернативные 
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);//функции ножек
   //----------------------------------------------
   I2C_Cmd(I2C1, ENABLE);//включаем модуль i2c
   
}

void init_IT_i2c(void)
{

   NVIC_InitTypeDef IT_i2c;
   
   IT_i2c.NVIC_IRQChannel = I2C1_EV_IRQn;//прерывания по событию
   IT_i2c.NVIC_IRQChannelPreemptionPriority = 0;//приоритет прерывания чем ниже значение тем выше приоритет
   IT_i2c.NVIC_IRQChannelSubPriority = 0;//Sub приоритет прерывания чем ниже значение тем выше приоритет
   IT_i2c.NVIC_IRQChannelCmd = ENABLE;//включение параметра канала прерывания
   NVIC_Init(&IT_i2c);//инициализируем прерывание

   IT_i2c.NVIC_IRQChannel = I2C1_ER_IRQn;//прерывания по ошибке
   IT_i2c.NVIC_IRQChannelPreemptionPriority = 0;//приоритет прерывания чем ниже значение тем выше приоритет
   IT_i2c.NVIC_IRQChannelSubPriority = 0;//Sub приоритет прерывания чем ниже значение тем выше приоритет
   IT_i2c.NVIC_IRQChannelCmd = ENABLE;//включение параметра канала прерывания
   NVIC_Init(&IT_i2c);

   
   I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);//включили прерывания по событию
   I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);//включили прерывания по ошибке

}

void I2C_start_IT(void)
{
   // ждем освобождения шины
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
   I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE);//включаем прерывания для буфера приема и передачи
   I2C_GenerateSTART(I2C1, ENABLE);//генерируем старт
}

After generating START, the SB flag is lit, but interrupts do not fire.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Sergey Kordubin, 2016-11-21
@Roon_Boh

Fuck the jumper on any leg, and on this leg, fuck the state change interrupt, but do not forget to turn off the interrupt when receiving data transmission, otherwise it will not work for you, in fact, when a new bit arrives, it wakes up again.

T
Timur Khasanshin, 2016-11-24
@itxs

1) In the interrupt, you need to clear the flag of the origin of the interrupt, otherwise after one operation when turned on, it will no longer work.
2) NVIC is simpler: NVIC_EnableIRQ(I2C1_EV_IRQn); NVIC_EnableIRQ(I2C1_ER_IRQn);
3) The names of the interrupt functions must be taken from the .s file in the project, where they are linked into the interrupt vector area. I2C_start_IT(void) is located here not at all in the area of ​​vectors, so it does not work.
4) Interrupts of the peripheral itself (I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE); etc.) must be included in the initialization code of this peripheral.

K
Kopranych, 2016-11-29
@Kopranych

Now the sensor does not want to respond at all, the code hangs in the address confirmation mode and that's it:
[CODE]while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));[/CODE]
Although I haven't changed anything fundamental in the code. Maybe the sensor is dead, because it does not even respond to the working version of the code when everything is without interruptions? How to check the sensor on my MPU6050 gyroscope?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question