Notas de estudio STM32CubeMX (3) -Uso de interfaz EXTI (interrupción externa)

1. Nueva construcción

1. Abra el software STM32CubeMX y haga clic en "Nuevo proyecto"

2. Elija MCU y paquete

3. Configure los
ajustes de reloj RCC, seleccione HSE (reloj externo de alta velocidad),

seleccione Configuración de reloj para resonador de cristal / cerámica (oscilador de cristal / resonador de cerámica) , configure el reloj del sistema SYSCLK a 72MHz,
modifique el valor de HCLK a 72, y presiona Enter. Modifica automáticamente todas las configuraciones

4. Es
un paso muy importante configurar el modo de depuración ; de lo contrario, la
configuración SYS del depurador no se reconocerá después del primer programa de programación , seleccione Depurar como cable serial

Dos, interrupción externa EXTI

2.1 Configuración de parámetros

Al System Coreseleccionar la GPIOconfiguración.

Busque el pin correspondiente del botón en la figura de la derecha y selecciónelo GPIO_EXTIx.
Aquí xsignifica que está montado en varias líneas de interrupción, está montado en dicha interrupción GPIO_EXTI0 0.

  • Interrupción activada por flanco descendente abierto: es decir, cuando la tecla se presiona a nivel cuando se activa por un alto a bajo, entonces el GPIO modeseleccionadoExternal Interrupt Mode with Falling edge trigger detection

  • Abrir flanco de subida interrupciones provocadas: es decir, cuando se pulsa el botón de liberación después de que los cambios en el nivel de disparo de baja a alta, la GPIO modeseleccionadosExternal Interrupt Mode with Rising edge trigger detection

  • Las interrupciones activadas por flanco ascendente se activan al descender: eso se activa cuando se presiona de nuevo cuando suelta el gatillo , luego GPIO modeseleccionaExternal Interrupt Mode with Rising/Falling edge trigger detection

  • Si es un hardware de pullup o pulldown externo, GPIO Pull-up/Pull-downseleccione No pull-up and no pull-downni pull-up ni pull-down.

  • Si el hardware no es un pull externo, GPIO Pull-up/Pull-downseleccione Pull-upuna resistencia pullup interna.

    Configuración Las NVIC
    reglas de agrupación de prioridad de interrupción están Priority Grouppredeterminadas en cuatro bits, generalmente no cambian.
    Verifique la configuración externa simplemente interrumpa 0 y 13, y configure la prioridad de preferencia Preemption Priorityy en respuesta a la prioridad Sub Priority.

    • Anticipe la prioridad, cuanto menor sea el número, mayor será la prioridad
    • Si la prioridad de preferencia es la misma, determine la subprioridad. Del mismo modo, cuanto menor sea el número, mayor será la prioridad

2.2 Generar código

Nombres de elementos de ruta y

selección de entrada de elementos de un entorno de desarrollo de aplicaciones IDE MDK-ARM V5

cada periférico genera un ’.c/.h’archivo separado ,
no un gancho: Todo el código de inicialización se genera en main.c
verificado: archivo de código de inicialización generado en el periférico asociado. Por ejemplo, el código de inicialización GPIO se genera en gpio.c.
Haga clic en GENERAR CÓDIGO para generar código

2.3 Modificar la función de devolución de llamada de interrupción

Abra el stm32f1xx_it.carchivo de rutina de servicio de interrupción, busque EXTI0 rutina de servicio de interrupción El servicio de EXTI0_IRQHandler()
interrupción dentro de la función se llama el manejador de interrupciones externo GPIO HAL_GPIO_EXTI_IRQHandler()

para abrir el stm32f1xx_hal_gpio.carchivo, encuentre el prototipo del manejador de interrupciones externo HAL_GPIO_EXTI_IRQHandler(), su función principal es determinar si la línea de fecha interrumpe, borra la bandera de interrupción, luego llame a la función de devolución de llamada de interrupción HAL_GPIO_EXTI_Callback().

/ * NOTA: Esta función no debe modificarse, cuando se necesita la devolución de llamada,
la HAL_GPIO_EXTI_Callback podría implementarse en el archivo de usuario
* /
Esta función no debe cambiarse, si necesita usar la función de devolución de llamada, vuelva a implementar la función en el archivo de usuario.

HAL_GPIO_EXTI_Callback()De acuerdo con el indicador oficial, deberíamos definir la función nuevamente, que __weakes una bandera debilitada. La función con esta es una función debilitada, es decir, puede escribir una función con exactamente el mismo nombre y parámetros en otro lugar, y el compilador ignorará esta función. En su lugar UNUSED(GPIO_Pin), ejecute la función que escribió; y , esta es una definición a prueba de errores. Cuando el número de puerto GPIO entrante no se procesa de ninguna manera, el compilador no informará una advertencia. De hecho, ya no necesitamos preocuparnos por la función de servicio de interrupción cuando estamos desarrollando. Solo necesitamos encontrar la función de devolución de llamada de interrupción y reescribirla. Hay otro aspecto muy conveniente de esta función de devolución de llamada que no se refleja aquí. Cuando se habilitan múltiples interrupciones, STM32CubeMX organizará automáticamente las funciones de servicio de varias interrupciones juntas y llamará a una función de devolución de llamada, es decir, no importa cuántas interrupciones, solo necesitamos reescribir una función de devolución de llamada y juzgar el número de puerto entrante OK.

Luego solo stm32f1xx_it.cagregamos la parte inferior de este documentoHAL_GPIO_EXTI_Callback()

/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    
    
	if(GPIO_Pin==KEY1_Pin)
	{
    
    
        // 自定义应用程序
        HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
	}
}
/* USER CODE END 1 */

2.3 Comparación de la biblioteca HAL y el código de biblioteca estándar

STM32CubeMX usa el código generado por la biblioteca HAL:

#define KEY2_Pin GPIO_PIN_13
#define KEY2_GPIO_Port GPIOC
#define KEY2_EXTI_IRQn EXTI15_10_IRQn
#define KEY1_Pin GPIO_PIN_0
#define KEY1_GPIO_Port GPIOA
#define KEY1_EXTI_IRQn EXTI0_IRQn

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
    
    
    GPIO_InitTypeDef GPIO_InitStruct = {
    
    0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /*Configure GPIO pin : KEY2_Pin */
    GPIO_InitStruct.Pin = KEY2_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);

    /*Configure GPIO pin : KEY1_Pin */
    GPIO_InitStruct.Pin = KEY1_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);

    /* EXTI interrupt init*/
    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

/**
  * @brief This function handles EXTI line0 interrupt.
  */
void EXTI0_IRQHandler(void)
{
    
    
    /* USER CODE BEGIN EXTI0_IRQn 0 */

    /* USER CODE END EXTI0_IRQn 0 */
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    /* USER CODE BEGIN EXTI0_IRQn 1 */

    /* USER CODE END EXTI0_IRQn 1 */
}

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
    
    
    /* USER CODE BEGIN EXTI15_10_IRQn 0 */

    /* USER CODE END EXTI15_10_IRQn 0 */
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
    /* USER CODE BEGIN EXTI15_10_IRQn 1 */

    /* USER CODE END EXTI15_10_IRQn 1 */
}

/**
  * @brief  This function handles EXTI interrupt request.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
    
    
    /* EXTI line interrupt detected */
    if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
    {
    
    
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
        HAL_GPIO_EXTI_Callback(GPIO_Pin);
    }
}

Utilice el código de biblioteca estándar STM32:

#define KEY1_INT_GPIO_PORT         GPIOA
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN          GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource0
#define KEY1_INT_EXTI_LINE         EXTI_Line0
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn

#define KEY1_IRQHandler            EXTI0_IRQHandler


#define KEY2_INT_GPIO_PORT         GPIOC
#define KEY2_INT_GPIO_CLK          (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN          GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE    GPIO_PinSource13
#define KEY2_INT_EXTI_LINE         EXTI_Line13
#define KEY2_INT_EXTI_IRQ          EXTI15_10_IRQn

#define KEY2_IRQHandler            EXTI15_10_IRQHandler

 /**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
    
    
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源:按键1 */
  NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* 配置中断源:按键2,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
  NVIC_Init(&NVIC_InitStructure);
}

 /**
  * @brief  配置 IO为EXTI中断口,并设置中断优先级
  * @param  无
  * @retval 无
  */
void EXTI_Key_Config(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;

	/*开启按键GPIO口的时钟*/
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
												
	/* 配置 NVIC 中断*/
	NVIC_Configuration();
	
    /*--------------------------KEY1配置-----------------------------*/
	/* 选择按键用到的GPIO */	
    GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
    /* 配置为浮空输入 */	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
    GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 
    EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
	
    /* EXTI为中断模式 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 上升沿中断 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    /* 使能中断 */	
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
	
    /*--------------------------KEY2配置-----------------------------*/
    /* 选择按键用到的GPIO */	
    GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
    /* 配置为浮空输入 */	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

    /* 选择EXTI的信号源 */
    GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 
    EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
	
    /* EXTI为中断模式 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 下降沿中断 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    /* 使能中断 */	
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
}

void KEY1_IRQHandler(void)
{
    
    
    //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
	{
    
    
		// LED1 取反		
		LED1_TOGGLE;
        //清除中断标志位
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
	}  
}

void KEY2_IRQHandler(void)
{
    
    
    //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) 
	{
    
    
		// LED2 取反		
		LED2_TOGGLE;
        //清除中断标志位
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     
	}  
}

__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();Correspondiente al RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);correspondiente GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);HAL_NVIC_EnableIRQ(EXTI0_IRQn);correspondiente a NVIC_Init(&NVIC_InitStructure);EXTI_Init(&EXTI_InitStructure);
__HAL_GPIO_EXTI_GET_IT(GPIO_Pin)un correspondiente EXTI_GetITStatus(KEY1_INT_EXTI_LINE)
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin)a correspondienteEXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE)

Tres, asuntos que necesitan atención

El código de usuario se agregará USER CODE BEGIN Ny USER CODE END Nentre, de lo contrario, el próximo uso después de que STM32CubeMX vuelva a generar el código, se eliminará.


Escrito por Leung el 12 de enero de 2021

• Referencia: Tutorial 2 de la serie STM32CubeMX: Interrupción externa (EXIT)
    [STM32Cube_05] Use el botón de detección de interrupciones EXIT (configuración NVIC + mecanismo de manejo de interrupciones de la biblioteca HAL)
    "Guía de desarrollo Embedded-STM32" Parte 2 Conceptos básicos-Capítulo 3 Botones (biblioteca HAL)
    STM32CubeMX tutorial de combate real (tres) -interrupción externa (función de interrupción y HAL_Delay para evitar hoyos)

Supongo que te gusta

Origin blog.csdn.net/qq_36347513/article/details/112508465
Recomendado
Clasificación