I2C slave receiver on stm32f4

I am trying to perform the interrupt service routine of an i2c slave receiver on stm32f4. Here is my smart piece of code.

void I2C2_EV_IRQHandler() { switch (I2C_GetLastEvent(I2C2)) { //The address sent by the master matches the own address of the peripheral case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //The slave stretches SCL low until ADDR is //cleared and DR filled with the data to be sent I2C_ClearFlag(I2C2,I2C_FLAG_ADDR); break; //The application is expecting a data byte to be received case I2C_EVENT_SLAVE_BYTE_RECEIVED: I2C_ReceiveData(I2C2); break; //The application is expecting the end of the communication //Make sure that both ADDR and STOPF flags are cleared //if both are found set. case I2C_EVENT_SLAVE_STOP_DETECTED: if(I2C_GetFlagStatus(I2C2,I2C_FLAG_ADDR) == SET) I2C_ClearFlag(I2C2,I2C_FLAG_ADDR); if(I2C_GetFlagStatus(I2C2,I2C_FLAG_STOPF) == SET) I2C_ClearFlag(I2C2,I2C_FLAG_STOPF); } 

}

The interrupt will be called and the case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED will be introduced. Now SCL is low. The reference manual says that if I clear the address flag, the clock will continue and the data will be sent (Page 579 - slave receiver). In my opinion, an interrupt is always called if any data arrives, and the next state will be I2C_EVENT_SLAVE_BYTE_RECEIVED.

I can not find any example from stm or via google. Can someone help me or show me an example.

+4
source share
2 answers

now it works. My problem was that I could not reset ADDR and the STOPF register with these commands from the reference manual. But if this is done in a loop, this works fine for me. Here is my working interrupt procedure.

  void I2C3_EV_IRQHandler() { switch (I2C_GetLastEvent(I2C3)) { case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: STM_EVAL_LEDOn(LED3); STM_EVAL_LEDOff(LED5); break; case I2C_EVENT_SLAVE_BYTE_RECEIVED: STM_EVAL_LEDToggle(LED4); STM_EVAL_LEDOff(LED3); I2C_InputBuffer[I2C_InputBufferIndex++] = I2C_ReceiveData(I2C3); break; case I2C_EVENT_SLAVE_STOP_DETECTED: STM_EVAL_LEDOn(LED6); STM_EVAL_LEDOff(LED4); break; } I2C_CleanADDRandSTOPF(); if(I2C_InputBufferIndex > MOTOR_PACKAGE_SIZE-1) { motorHandleEvent(I2C_InputBuffer); I2C_InputBufferIndex = 0; uint8_t resetIndex; for(resetIndex = 0; resetIndex < MOTOR_PACKAGE_SIZE; resetIndex ++) I2C_InputBuffer[resetIndex] = 0; } } inline void I2C_CleanADDRandSTOPF() { while ((I2C3->SR1 & I2C_SR1_ADDR) == I2C_SR1_ADDR) { volatile uint32_t temp; temp=I2C3->SR1; temp=I2C3->SR2; } while ((I2C3->SR1&I2C_SR1_STOPF) == I2C_SR1_STOPF) { volatile uint32_t temp; temp=I2C3->SR1; I2C3->CR1 |= 0x1; } } 
+2
source

The hardware performs clock stretching to ensure that the slave supports the master. First, the slave waits to get an address match. Then you get an interrupt while the SCL is kept low. This allows the slave to basically provide flow control to the master. The master detects that the SCL is kept low on the slave and will wait for it to be released before the master sends more data. Thus, you will not receive additional interruptions when receiving data, because the master will not send more data until you start SCL. You can read about stretching hours here http://en.wikipedia.org/wiki/I%C2%B2C

0
source

Source: https://habr.com/ru/post/1403431/


All Articles