STM32CubeMX study notes (3)-EXTI (external interrupt) interface use

1. New construction

1. Open the STM32CubeMX software and click "New Project"

2. Choose MCU and package

3. Configure the clock
RCC settings, select HSE (external high-speed clock),

select Clock Configuration for Crystal/Ceramic Resonator (crystal oscillator/ceramic resonator) , configure the system clock SYSCLK to 72MHz,
modify the value of HCLK to 72, and press Enter. Automatically modify all configurations

4. It
is a very important step to configure the debug mode , otherwise the debugger
SYS setting will not be recognized after the first programming program , select Debug as Serial Wire

Two, EXTI external interrupt

2.1 Parameter configuration

In System Coreselecting GPIOsettings.

Find the corresponding pin of the button in the figure on the right and select it GPIO_EXTIx.
Here xmeans mounted on several interrupt lines, is mounted on such GPIO_EXTI0 0 interrupt.

  • Open falling edge triggered interrupt: i.e., when the key is pressed level when triggered by a high to low, then the GPIO modeselectedExternal Interrupt Mode with Falling edge trigger detection

  • Open rising edge triggered interrupts: i.e., when the release button is pressed after the trigger level changes from low to high, the GPIO modeselectedExternal Interrupt Mode with Rising edge trigger detection

  • Rising edge triggered interrupts are turned on falling: that is triggered when pressed again when you release the trigger , then GPIO modeselectExternal Interrupt Mode with Rising/Falling edge trigger detection

  • If external pullup or pulldown hardware, then GPIO Pull-up/Pull-downselect No pull-up and no pull-downneither pull-up nor pull-down on.

  • If the hardware is not an external pull, then GPIO Pull-up/Pull-downselect Pull-upan internal pullup resistor.

    Configuration NVIC
    Interrupt priority grouping rules Priority Groupdefaults to four bits, generally do not change.
    Check the external configuration just interrupt 0 and 13, and configure the preemption priority Preemption Priorityand in response to the priority Sub Priority.

    • Preempt the priority, the smaller the number, the higher the priority
    • If the preemption priority is the same, determine the sub-priority. Similarly, the smaller the number, the higher the priority

2.2 Generate code

Path item names and item input

selection of an application development environment IDE MDK-ARM V5

each peripheral generates a separate ’.c/.h’file
not hook: All initialization code is generated in main.c
checked: initialization code file generated in the associated peripheral. For example, the GPIO initialization code is generated in gpio.c.
Click GENERATE CODE to generate code

2.3 Modify the interrupt callback function

Open the stm32f1xx_it.cinterrupt service routine file, find EXTI0 interrupt service routine EXTI0_IRQHandler()
interrupt service inside the function is called the GPIO external interrupt handler HAL_GPIO_EXTI_IRQHandler()

to open the stm32f1xx_hal_gpio.cfile, find the external interrupt handler prototype HAL_GPIO_EXTI_IRQHandler(), its main role is to determine is the date line interrupts, clear the interrupt flag, Then call the interrupt callback function HAL_GPIO_EXTI_Callback().

/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
This function should not be changed, if you need to use the callback function, please re-implement the function in the user file .

HAL_GPIO_EXTI_Callback()According to the official prompt, we should define the function again, which __weakis a weakened flag. The function with this is a weakened function, that is, you can write a function with exactly the same name and parameters elsewhere, and the compiler will ignore this function. Instead UNUSED(GPIO_Pin), execute the function you wrote; and , this is an error-proof definition. When the incoming GPIO port number is not processed in any way, the compiler will not report a warning. In fact, we don’t need to bother about the interrupt service function anymore when we are developing. We only need to find the interrupt callback function and rewrite it. There is another very convenient aspect of this callback function that is not reflected here. When multiple interrupts are enabled, STM32CubeMX will automatically organize the service functions of several interrupts together and call a callback function, that is, no matter how many interrupts, we only need to rewrite a callback function and judge the incoming port number That's it.

Then we just stm32f1xx_it.cadd the bottom of this documentHAL_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 Comparison of HAL library and standard library code

STM32CubeMX uses the code generated by the HAL library:

#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);
    }
}

Use STM32 standard library code:

#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();Corresponding to RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);the corresponding GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);HAL_NVIC_EnableIRQ(EXTI0_IRQn);corresponding to NVIC_Init(&NVIC_InitStructure);EXTI_Init(&EXTI_InitStructure);
__HAL_GPIO_EXTI_GET_IT(GPIO_Pin)a corresponding EXTI_GetITStatus(KEY1_INT_EXTI_LINE)
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin)a correspondingEXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE)

Three, matters needing attention

User code to be added to USER CODE BEGIN Nand USER CODE END Nbetween, otherwise the next use after STM32CubeMX regenerate the code, it will be deleted.


Written by Leung on January 12, 2021

• Reference: STM32CubeMX series tutorial 2: External interrupt (EXIT)
    [STM32Cube_05] Use EXIT interrupt detection button (NVIC configuration + HAL library interrupt handling mechanism)
    "Embedded-STM32 Development Guide" Part 2 Basics-Chapter 3 Buttons ( HAL library)
    STM32CubeMX actual combat tutorial (three)-external interrupt (interrupt and HAL_Delay function to avoid pits)

Guess you like

Origin blog.csdn.net/qq_36347513/article/details/112508465