简体   繁体   English

STM32 - 中断模式下的 I2C 不起作用

[英]STM32 - I2C in interrupt mode doesn't works

I am using a STM32 board to send I2C commands to a I2C slave using interrupt mode.我正在使用 STM32 板使用中断模式将 I2C 命令发送到 I2C 从设备。 I have initialized I2C module as below,我已经初始化了 I2C 模块,如下所示,

  hi2c2.Instance = I2C2;
  hi2c2.Init.Timing = 0x00303D5B;
  hi2c2.Init.OwnAddress1 = 0;
  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();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
  {
    Error_Handler();
  }

And for transfer I use the HAL API,对于传输,我使用 HAL API,

HAL_I2C_Master_Transmit_IT(&hi2c2, 0x60, buffer, 2);

But this code doesn't seem to work for me.但是这段代码似乎对我不起作用。

In buffer, first byte is the register address on the I2C slave and second byte is the data.在缓冲区中,第一个字节是 I2C 从设备上的寄存器地址,第二个字节是数据。 When I use the blocking mode API,当我使用阻塞模式 API 时,

HAL_I2C_Master_Transmit(&hi2c2, 0x60, buffer, 2,HAL_MAX_DELAY);

It works fine.它工作正常。 Any suggestions what could be wrong here?任何建议这里可能有什么问题?

Have you actually enabled the I2C Interrupt?你真的启用了 I2C 中断吗? That might be the Problem.那可能是问题所在。

查看您的 HAL_I2C_MspInit 函数,以及是否调用了 HAL_NVIC_SetPriority(I2C2_IRQn, 0, 0) 和 HAL_NVIC_EnableIRQ(I2C2_IRQn)。

The reason your interrupt HAL call doesn't work while your polling one does, is because when using the interrupt, you need to make sure that the bus is ready first.您的中断 HAL 调用在轮询中不起作用的原因是因为在使用中断时,您需要先确保总线准备就绪。 You have to manually do the "timeout" that is embedded in the HAL_MAX_DELAY of the polling HAL call.您必须手动执行嵌入在轮询 HAL 调用的HAL_MAX_DELAY中的“超时”。

Thus:因此:

  1. Polling implementation (that you called correctly):轮询实现(您正确调用):
HAL_I2C_Master_Transmit(&hi2c2, 0x60, buffer, 2, HAL_MAX_DELAY);
  1. Interrupt implementation:中断实现:
while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY)
{
}
HAL_I2C_Master_Transmit_IT(&hi2c2, 0x60, buffer, 2);

will do the trick.会做的伎俩。

It also means that without the ready check, your code could work as intended if you call your interrupt HAL at a low enough frequency, because then, the bus is always ready when you need it.这也意味着如果没有就绪检查,如果您以足够低的频率调用中断 HAL,您的代码可以按预期工作,因为这样,总线在您需要时始终准备就绪。 This is a pernicious bug: in appearance, your code could function without the check... but only by accident (or luck, depending on how you call it).这是一个有害的错误:从表面上看,您的代码可以在没有检查的情况下运行……但只是偶然的(或运气,取决于您如何称呼它)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM