cancel
Showing results for 
Search instead for 
Did you mean: 

How can I use STM32 F030R8 as i2c slave using interrupt?

Svan.11.332
Associate II

Since quite some time I am trying to find a way for an STM32 chip to receive and send data as a slave over i2c. The master always sends the same amount of bytes and after sending these bytes, requests two bytes back from the slave. I used the CubeMX example software for i2c with succes, however this example code as found here:

https://github.com/fboris/STM32Cube_FW_F4/tree/master/Projects/STM32F401-Discovery/Examples/I2C/I2C_TwoBoards_ComIT

This code works and enabling a 'global i2c interrupt' and triggering an LED in this interrupt works as well. However when I try to put the code in the interrupt, the LED does not even go on. The LED is just for testing and in the end I would like to be able to receive information through i2c on an interrupt.

Putting following code in the main works for one receive and one send, however i would like to replace this code to the interrupt, which does not work as is:

if(HAL_I2C_Slave_Receive_DMA(&hi2c2, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)

 {

  // Transfer error in reception process 

  Error_Handler();

 }

while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY)

 {

 } 

if(HAL_I2C_Slave_Transmit_DMA(&hi2c2, (uint8_t*)aRxBuffer, 2)!= HAL_OK)

 {

  // Transfer error in transmission process 

  Error_Handler();

 }

the function initializing the i2c is as follows:

static void MX_I2C2_Init(void)

{

 hi2c2.Instance = I2C2;

 hi2c2.Init.Timing = 0x20303E5D;

 hi2c2.Init.OwnAddress1 = I2C_ADDRESS;

 hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

 hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

 hi2c2.Init.OwnAddress2 = 0;

 hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

 hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

 hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

 if (HAL_I2C_Init(&hi2c2) != HAL_OK)

 {

  _Error_Handler(__FILE__, __LINE__);

 }

  /**Configure Analogue filter 

  */

 if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)

 {

  _Error_Handler(__FILE__, __LINE__);

 }

  /**Configure Digital filter 

  */

 if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)

 {

  _Error_Handler(__FILE__, __LINE__);

 }

}

In CubeMX there is an NVIC enabled for DMA and i2c. Anybody who can help me out?

Help is very much appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions

>>I have only found ways online where the slave is constantly waiting until data is sent but this slave has a second task which can be paused but cannot wait for seconds.

All the examples probably have a linear, one-at-a-time, code flow, so you'd need to break that mindset, and use a stateful approach where it does what it can in a given instant, and leave if it can't, and can come back later and continue where it left off.

The HAL model here would you set up a listening/receiving request, and then continue, when something actually happens you'll get a callback (via interrupt) and there you manage the request, or queue another.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

5 REPLIES 5

You really can't put blocking code in an interrupt, or have it vector off to an infinite loop when things go awry.

You'd need a more stateful implementation if you're going to use interrupts effectively.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thank you for replying. That makes​ sense but the blocking that could happen could be solved by a timeout and is not the main problem. I'm trying to find out whether it is possible to be able to accept data written to the slave whenever the master sends this data. I have only found ways online where the slave is constantly waiting until data is sent but this slave has a second task which can be paused but cannot wait for seconds. As far as I know an interrupt would be the only way to enable this.

>>I have only found ways online where the slave is constantly waiting until data is sent but this slave has a second task which can be paused but cannot wait for seconds.

All the examples probably have a linear, one-at-a-time, code flow, so you'd need to break that mindset, and use a stateful approach where it does what it can in a given instant, and leave if it can't, and can come back later and continue where it left off.

The HAL model here would you set up a listening/receiving request, and then continue, when something actually happens you'll get a callback (via interrupt) and there you manage the request, or queue another.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thanks a lot! I just tried using the callback function from the HAL library and it transfers data without a problem. In each callback function it sets up a listening or receiving request and this works great so far.

I know this is an old topic, but can you please share your code on github and link it here? I'm trying to do the same and cannot figure out how to setup the interrupts.