【问题标题】:STM32 HAL GPIO interrupt count too muchSTM32 HAL GPIO中断计数太多
【发布时间】:2017-05-11 12:05:13
【问题描述】:

我遇到了以下问题: 我的电子板上有 2 个输入:

#define TOR1_IN_uC_Port         GPIOC
#define TOR1_IN_uC_Pin          GPIO_PIN_5
#define TOR2_IN_uC_Port         GPIOE
#define TOR2_IN_uC_Pin          GPIO_PIN_6

我有这个初始化:

GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pin = TOR1_IN_uC_Pin;
HAL_GPIO_Init(TOR1_IN_uC_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = TOR2_IN_uC_Pin;
HAL_GPIO_Init(TOR2_IN_uC_Port, &GPIO_InitStruct);

HAL_NVIC_SetPriority(EXTI9_5_IRQn, 2, 1);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

我有这两个中断函数:

void EXTI9_5_IRQHandler(void)
{
    if(__HAL_GPIO_EXTI_GET_IT(TOR1_IN_uC_Pin) != RESET)
    {
        HAL_GPIO_EXTI_IRQHandler(TOR1_IN_uC_Pin);
        __HAL_GPIO_EXTI_CLEAR_IT(TOR1_IN_uC_Pin);
    }
    if(__HAL_GPIO_EXTI_GET_IT(TOR2_IN_uC_Pin) != RESET)
    {
        HAL_GPIO_EXTI_IRQHandler(TOR2_IN_uC_Pin);
        __HAL_GPIO_EXTI_CLEAR_IT(TOR2_IN_uC_Pin);
    }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == TOR1_IN_uC_Pin)
        Input1.Count++;
    else if (GPIO_Pin == TOR2_IN_uC_Pin)
        Input2.Count++;
}

我在输入端插入了一个 10Hz 的 GBF,但计数器计数太多。 当我在串口上打印计数器时,它显示大约 5kHz

当我手动读取输入的状态时,我无法验证输入是否太多。

【问题讨论】:

  • 什么是TOR4_IN_uC_Pin?我只看到 1 和 2 的定义。
  • 不匹配,我已经更正了我的帖子,谢谢
  • 做一些橡皮鸭并详细解释你的代码是如何工作的。也许您想添加更多代码,在我看来,代码肯定比您显示的要多。我正在考虑 HAL_GPIO_EXTI_IRQHandler 和 HAL_GPIO_EXTI_Callback 之间的链接。您需要确认/使用中断吗? 5kHz/10Hz 的因子似乎不太像算法错误(例如,逐一),更像是不断循环的 ISR 可以通过串行打印的最大频率……在边缘触发和电平之间有选择吗?触发?
  • 你在触发什么?等级?然后尝试如果您不断应用非触发级别会发生什么。边缘?然后尝试不断应用两个级别(即没有边缘)时会发生什么。如果在电平之外触发,请降低输入频率。你的计数会随着频率而变化吗?按比例?
  • 应用一些屏蔽,例如用锡箔纸包好所有东西(当然要小心无意接触)。这样算不算数?

标签: c interrupt stm32 gpio hal


【解决方案1】:

我也遇到过这个问题,过了一段时间才发现。这是因为您在中断返回非常接近时清除了 IRQ 标志。自己创建一个tail-chain 中断。

void EXTI9_5_IRQHandler(void)
{
    if(__HAL_GPIO_EXTI_GET_IT(TOR2_IN_uC_Pin) != RESET)
    {
        HAL_GPIO_EXTI_IRQHandler(TOR2_IN_uC_Pin);
        __HAL_GPIO_EXTI_CLEAR_IT(TOR2_IN_uC_Pin);
    }
    __DMB(); // add this
}

您必须等待巴士完成清除动作。 DMB instruction 对此有所帮助。

数据内存屏障充当内存屏障。它确保在 DMB 指令之后以程序顺序出现的任何显式内存访问之前观察到在 DMB 指令之前以程序顺序出现的所有显式内存访问。它不会影响在处理器上执行的任何其他指令的顺序。

【讨论】:

  • 这是一个荒谬的答案。清除中断标志不需要屏障。请不要给出错误的建议。
  • @PeterJ,不需要。你也可以添加一堆 nop,或者首先清除标志。
  • 标志应该先被清除。这是经验法则。在非常特殊的情况下(绝对不是在简单的中断例程中),所有障碍都应该被视为必要的邪恶。
【解决方案2】:

我解决了我的问题,这是由于 R.C. 引起的电气问题。输入和微型 GPIO 之间的电路。

信号上升时间过长(锯齿中的信号)。我现在已经很好地改变了我的电子和 mirco 计数。

【讨论】:

  • 这是您的解决方案。你可以接受。也许this 页面可以帮助您。您不能像在一个简单的论坛中那样关闭它。
【解决方案3】:
  1. EXTI - 总是先清除 IT 标志(其他中断也是如此)
  2. 切换总是会产生不止一个脉冲。
  3. HAL 和 EXTI - 我遇到了很多问题(也许我懒得学习这个可怕的库)并开始使用裸寄存器 - 所有问题都立即解决了 :)

【讨论】:

    猜你喜欢
    • 2019-04-20
    • 2018-01-09
    • 2018-02-22
    • 2021-05-20
    • 2017-04-07
    • 2016-10-16
    • 2015-09-24
    • 2018-08-26
    • 2021-08-27
    相关资源
    最近更新 更多