如何在中断中处理全局变量
How to handle global variables in interrupts
我是嵌入式系统的新手。对于我的最终学位项目,我正在开发一个使用 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_1
、BOTON_2
、BOTON_3
是分配给引脚的名称,通过上升沿检测将其配置为中断。
调试时,三个中断在按下按钮时工作正常,每个中断都在正确的时间。
变量boton_Flag
在main.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,这样程序就会保持 运行。但是,当我按下按钮时,尽管程序跳转到中断并更改了值,但当它 returns 到函数时,值再次为 0(其初始化值)。
我的结论可能是错误的,我没有正确地将变量传递给函数,程序将其解释为函数内部的局部变量,但我一点也不确定。
希望得到尽可能详细的解释,如果没有,请告诉我。
你是对的,你没有正确传递变量。按照你的方式,当函数被调用时,你创建一个局部变量(函数的局部变量)并为其分配全局 boton_flag
的值。
您可以通过两种方式解决此问题:
1.函数中使用全局变量即可。如果它已经是全局的,则无需将其传递给您的函数。
2. 通过引用传递boton_flag。即 numeroJugadores(&boton_Flag);
。如果你这样做,你将有一个指向 boton_flag
的指针,它稍微改变了 numeroJugadores
中的代码(你每次使用它时都必须取消引用 boton_flag
)。
我是嵌入式系统的新手。对于我的最终学位项目,我正在开发一个使用 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_1
、BOTON_2
、BOTON_3
是分配给引脚的名称,通过上升沿检测将其配置为中断。调试时,三个中断在按下按钮时工作正常,每个中断都在正确的时间。
变量
boton_Flag
在main.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,这样程序就会保持 运行。但是,当我按下按钮时,尽管程序跳转到中断并更改了值,但当它 returns 到函数时,值再次为 0(其初始化值)。
我的结论可能是错误的,我没有正确地将变量传递给函数,程序将其解释为函数内部的局部变量,但我一点也不确定。
希望得到尽可能详细的解释,如果没有,请告诉我。
你是对的,你没有正确传递变量。按照你的方式,当函数被调用时,你创建一个局部变量(函数的局部变量)并为其分配全局 boton_flag
的值。
您可以通过两种方式解决此问题:
1.函数中使用全局变量即可。如果它已经是全局的,则无需将其传递给您的函数。
2. 通过引用传递boton_flag。即 numeroJugadores(&boton_Flag);
。如果你这样做,你将有一个指向 boton_flag
的指针,它稍微改变了 numeroJugadores
中的代码(你每次使用它时都必须取消引用 boton_flag
)。