cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Interrupts

vbk22398
Associate III
I want to know the difference of the below 4 cases. Why the results are not as expected. Stm32 board is an i2c master with speed of 400kbps and slave is software simulation using Aardvark Total Phase Control Software.
uint8_t i2c_tra[10] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10 },
i2c_rec[10] = { 0 };
the data i send from the software is 11 22 33 44 55 66 66 77 88 99. This should be received in the i2c_rec.
////////////////////////////////////////////////////////////////////////////////////////////
while (1){
HAL_I2C_Master_Transmit_IT(&hi2c2,0x33<<1,i2c_tra,10);
HAL_I2C_Master_Receive_IT(&hi2c2,0x33<<1,i2c_rec,10);
HAL_Delay(100);
}
 
only sending is proper and no receiving done
/////////////////////////////////////////////////////////////////////////////////////////////
while (1) {
HAL_I2C_Master_Transmit(&hi2c2,0x33<<1,i2c_tra,10,100);
HAL_I2C_Master_Receive_IT(&hi2c2,0x33<<1,i2c_rec,10);
HAL_Delay(100);
  }
 
sending and receiving only once
//////////////////////////////////////////////////////////////////////////////////////////////
while (1) {
HAL_I2C_Master_Transmit(&hi2c2,0x33<<1,i2c_tra,10,100);
HAL_I2C_Master_Receive(&hi2c2,0x33<<1,i2c_rec,10,100);
HAL_Delay(100);
  }
 
sending and receiving is proper.no issue.
////////////////////////////////////////////////////////////////////////////////////////////////
while (1) {
HAL_I2C_Master_Transmit_IT(&hi2c2,0x33<<1,i2c_tra,10);
HAL_I2C_Master_Receive(&hi2c2,0x33<<1,i2c_rec,10,100);
HAL_Delay(100);
  }
 
only sending is happening nothing is received
/////////////////////////////////////////////////////////////////////////////////////////////////
Please let me know the difference of the above 4 cases.
1 ACCEPTED SOLUTION

Accepted Solutions
Danish1
Lead II

I2C is very slow in microcontroller terms. The processor could do thousands of machine instructions in the time it takes to do an I2C transfer.

The “base” functions (without _IT, without _DMA) are ”blocking” - they do not return until the requested action is complete. During the transfer the processor is largely sitting idle.

Where you do have something else for the processor to do at the same time as the slow I2C transfer, you can use the _IT or _ DMA version of the call. The processor will return immediately so you can tell it to do other things. But until you get a callback/interrupt telling you that the I2C transfer is complete, you can’t do anything else with I2C - that bit of hardware is busy.

This should explain why you don’t see all the requested transactions when the first call is an interrupt one. Incidentally I assume those functions return a value. This would normally be HAL_OK but they should give an error code if the I2C is still busy with an earlier transaction.

I should add that I don’t use HAL because I don’t find enough documentation about how to use it. My needs are rarely close enough to the examples, and automatically-generated “help” files give no greater insight than reading the source code.

View solution in original post

3 REPLIES 3
Danish1
Lead II

I2C is very slow in microcontroller terms. The processor could do thousands of machine instructions in the time it takes to do an I2C transfer.

The “base” functions (without _IT, without _DMA) are ”blocking” - they do not return until the requested action is complete. During the transfer the processor is largely sitting idle.

Where you do have something else for the processor to do at the same time as the slow I2C transfer, you can use the _IT or _ DMA version of the call. The processor will return immediately so you can tell it to do other things. But until you get a callback/interrupt telling you that the I2C transfer is complete, you can’t do anything else with I2C - that bit of hardware is busy.

This should explain why you don’t see all the requested transactions when the first call is an interrupt one. Incidentally I assume those functions return a value. This would normally be HAL_OK but they should give an error code if the I2C is still busy with an earlier transaction.

I should add that I don’t use HAL because I don’t find enough documentation about how to use it. My needs are rarely close enough to the examples, and automatically-generated “help” files give no greater insight than reading the source code.

ThankYou ! @Danish1 for the reply. So if I want to send or receive using Interrupts or DMA, what should I do. Only polling method will not be sufficient in all the cases. So could you direct me towards what should be done, to make I2C work using the Interrupt method?DMA Method.

I strongly recommend the Reference Manual for your STM32. This is the best source of documentation for the peripherals ST place around the arm processor core. It has an entire chapter on I2C, and another on DMA. But I will admit that its completeness does give a steep learning-curve. You should also have access to the Programming Manual which describes the arm core and the peripherals that Arm designed; this might help you understand interrupt-handling.

@vbk22398 wrote:

ThankYou ! @Danish1 for the reply. So if I want to send or receive using Interrupts or DMA, what should I do. Only polling method will not be sufficient in all the cases. So could you direct me towards what should be done, to make I2C work using the Interrupt method?DMA Method.


And there you have described the problem as I see it. I am not aware of documentation that tells us how to use the HAL libraries. The best we have are examples of their use - for example (I didn't pick up which stm32 microcontroller you're using) looking in STM32Cube_FW_F4_V1.25.2 (the version I happen to have downloaded, back from 2021) we have Projects\STM32F429I-Discovery\Examples\I2C the following directories:

  • I2C_TwoBoards_AdvComIT
  • I2C_TwoBoards_ComPolling
  • I2C_TwoBoards_ComDMA
  • I2C_TwoBoards_RestartAdvComIT
  • I2C_TwoBoards_ComIT
  • I2C_TwoBoards_RestartComIT

Careful study of the source-code in those examples might give you enough information on how to use the HAL calls in interrupt or DMA modes. But you'll probably have to do quite a few experiments to verify that your understanding is correct. And just hope that you have covered "unexpected" failures that didn't turn up during your tests.