【问题标题】:How to handle global variables in interrupts如何处理中断中的全局变量
【发布时间】:2016-08-18 15:23:08
【问题描述】:

我是嵌入式系统的新手。对于我的期末学位项目,我正在开发一个使用 STM NUCLEO 板和 STM32F411RE 微控制器的系统。

另外,我正在使用 stmcube32 加载初始化代码。

此时我被卡住了,但首先让我解释一下背景:

  • 我有三个处理相同标志的中断例程,您可以在源文件 stm32f4xx_it.c 中看到:

    void EXTI15_10_IRQHandler(void) {
    
        /* USER CODE BEGIN EXTI15_10_IRQn 0 */
    
        if (__HAL_GPIO_EXTI_GET_IT(BOTON1_Pin) != RESET) {
            __HAL_GPIO_EXTI_CLEAR_IT(BOTON1_Pin);
            boton_Flag = 1;
        }
        if (__HAL_GPIO_EXTI_GET_IT(BOTON2_Pin) != RESET) {
            __HAL_GPIO_EXTI_CLEAR_IT(BOTON2_Pin);
            boton_Flag = 2;
        }
        if (__HAL_GPIO_EXTI_GET_IT(BOTON3_Pin) != RESET) {
            __HAL_GPIO_EXTI_CLEAR_IT(BOTON3_Pin);
            boton_Flag = 3;
        }
        /* USER CODE END EXTI15_10_IRQn 0 */
        //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
        //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
        //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
        /* USER CODE BEGIN EXTI15_10_IRQn 1 */
    
        /* USER CODE END EXTI15_10_IRQn 1 */
    }
    
  • 在头文件 stm32f4xx_it.h 中以这种方式声明我的全局变量:

     extern volatile uint8_t boton_Flag;
    
  • BOTON_1BOTON_2BOTON_3 是分配给引脚的名称,通过提高触发边沿检测配置为中断。

  • 在调试过程中,三个中断在按下按钮时完美运行,每个中断都在正确的时间。

  • 变量boton_Flagmain.c中是这样定义的:

    volatile uint8_t boton_Flag = 0;
    
  • main 函数中,我将全局变量 boton_Flag 传递给在 controlpanel.h 中声明的函数(我在开头有 #include "controlpanel.h"文件):

    int main(void) {
    
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration----------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick.*/
        HAL_Init();
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_TIM3_Init();
        MX_TIM4_Init();
    
        /* Initialize interrupts */
        MX_NVIC_Init();
    
        /* USER CODE BEGIN 2 */
        init_PanelConfig();
    
        numeroJugadores(boton_Flag);
    
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1) {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
    
        }
        /* USER CODE END 3 */
    }
    
  • 函数numeroJugadores(boton_Flag); 执行以下操作:

    uint8_t numeroJugadores(uint8_t boton_Flag) {
        uint8_t players = 4;
    
        while (boton_Flag != 2);
        boton_Flag = 0;
    
        while (boton_Flag != 2) {
            if (boton_Flag == 1)
                boton_Flag = 0;
            {
                players++;
                if ((players > 4) || (players < 1) ) {
                     players = 0;
                }
            }
            while (boton_Flag != 1);
    
            switch(players) {
              case 1:
                lcd_clear();
                lcd_goto(0, 0);
                lcd_on();
                lcd_puts("Numero de");
                lcd_goto(0, 1);
                lcd_puts("jugadores: 1");
                break;
              case 2:
                lcd_clear();
                lcd_goto(0, 0);
                lcd_on();
                lcd_puts("Numero de");
                lcd_goto(0, 1);
                lcd_puts("jugadores: 2");
                break;
              case 3:
                lcd_clear();
                lcd_goto(0, 0);
                lcd_on();
                lcd_puts("Numero de");
                lcd_goto(0, 1);
                lcd_puts("jugadores: 3");
                break;
              case 4:
                lcd_clear();
                lcd_goto(0, 0);
                lcd_on();
                lcd_puts("Numero de");
                lcd_goto(0, 1);
                lcd_puts("jugadores: 4");
                break;
            }
        }
        return players;
    }
    

那么,我的问题是什么?调试的时候发现程序一直卡在上面函数里面的第一条语句while (boton_Flag != 2);

它应该保持在那里,直到我按下 BOTON2 将标志更改为值 2,这样程序就会继续运行。但是,当我按下按钮时,尽管程序跳转到中断并更改了值,但当它返回函数时,该值再次为 0(其初始化值)。

我的结论可能是错误的,是我没有正确地将变量传递给函数,程序将其解释为函数内部的局部变量,但我完全不确定。

我希望得到尽可能好的解释,如果没有,请告诉我。

【问题讨论】:

  • 没有“嵌入式C”

标签: c variables embedded global interrupt


【解决方案1】:

你是对的,你没有正确传递变量。您拥有它的方式,当调用函数时,您创建一个局部变量(函数的局部变量)并将其分配给全局 boton_flag 的值。

有两种方法可以解决此问题:
1.只要在函数中使用全局变量即可。如果它已经是全局的,则无需将其传递给您的函数。
2. 通过引用传递 boton_flag。即numeroJugadores(&amp;boton_Flag);。如果你这样做,你将有一个指向boton_flag 的指针,它会稍微改变numeroJugadores 中的代码(每次使用它时都必须取消引用boton_flag)。

【讨论】:

  • 你是对的!这很明显。我的头此时被烧毁了。
  • @SergioCastillo 不过,您应该避免到处使用该全局变量,这只是意大利面条式编码,会导致错误。只需将其读入一个临时局部变量,然后让一个简单的状态机对该值执行操作即可。
  • @Lundin 它必须是全局的,因为它在中断处理程序中使用。在我看来,拥有不需要的额外局部变量会更麻烦。变量名应以G_ 或其他名称开头,以表明它是全局的。
  • @Riley 是的,它必须是一个全局的,但它只需要在一个地方与主程序共享 - 理想情况下你声明它static 并在一个地方复制它,然后做所有局部变量的工作。这不仅是为了避免意大利面条式代码,也是为了避免编译器优化和重入问题。例如,对变量的所有读/写都必须是原子的。该变量可能必须伴随信号量,在这种情况下,您不想到处发送垃圾邮件。使用随时可能发生变化的变量通常是有问题的。
  • @Lundin static 是个好主意。无论在哪里使用它,他都希望函数之外的东西能够改变它的值。另外,我认为在这个特定的代码中,读/写不必是原子的。
猜你喜欢
  • 1970-01-01
  • 2015-02-27
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-19
  • 2021-07-22
  • 1970-01-01
  • 2011-01-10
相关资源
最近更新 更多