中断系统
1 数据传输方式
- 无条件传输 :处理器不必了解外部设备状态,直接进行数据传输,用于指示灯和按键等简单设备.。
- 查询方式 :传输前,一方先查询另一方的状态,若已经准备好就传输,否则就继续查询。
- 中断方式 :一方通过申请中断的方式与另一方进行数据传输,收发双方可以并行工作。
- 直接存储器访问 :处理器内部建立片内外设和内存之间的数据传输通道,传输过程不需要处理器参与。
2 中断系统的基本概念
2.1 中断全过程
- 中断发生: 当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。
- 中断处理: CPU暂停当前的工作,转去处理事件B。
- 中断返回: 当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继续处理事件A。
2.2 中断的作用
- 速度匹配: 可以解决快速的CPU与慢速的外部设备之间传送数据的矛盾。
- 分时操作: CPU可以分时为多个外部设备服务,提高计算机的利用率。
- 实时响应: CPU能够及时处理应用系统的随机事件,增强系统的实时性。
- 可靠性高: CPU可以处理设备故障及掉电等突发事件,提高系统可靠性。
2.3 中断优先级
处理器根据不同中断的重要程序设置不同的优先等级。
不同优先级中断的处理原则是: 高级中断可以打断低级中断;低级中断不能打断高级中断 。
2.4 中断向量
- 中断服务程序: 在响应一个特定中断的时候,处理器会执行一个函数,该函数一般称为中断处理程序或者中断服务程序。
- 中断向量: 中断服务程序在内存中的入口地址称为中断向量。
- 中断向量表: 把系统中所有的中断向量集中起来放到存储器的某一区。
- 查找中断向量:
- 编号:计算机系统对每一个中断源进行编号,这个号码称为中断类型号。
- 查表:根据中断类型号,到中断向量表中找到对应的表项。
- 执行:取出表项内容,即该中断源对应的中断服务程序地址,进入该程序执行相应操作。
2.5 中断响应过程
- 中断源发出中断请求。
- 判断处理器是否允许中断,以及该中断源是否被屏蔽。
- 中断优先级排队。
- 处理器暂停当前程序,保护断点地址和处理器的当前状态,根据中断类型号,查找中断向量表,转到对应的中断服务程序。
- 执行中断服务程序。
- 恢复被保护的状态,执行中断返回指令,回到被中断的程序。
3 STM32微控制器中断系统
3.1 基本概念
- 中断: 中断是由内核外部产生的,一般由硬件引起,比如外设中断和外部中断等。
- 异常: 异常通常是内核自身产生的,大多是软件引起的,比如除法出错异常、预取值失败等。
3.2 NVIC嵌套向量中断控制器
NVIC属于Cortex-M内核的组件,管理所有的中断和异常,为中断源分配中断通道
中断向量表
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1_2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
3.3 中断通道
微控制器片内集成了很多外设,对于单个外设而言,它通常具备若干个可以引起中断的中断源,而该外设的所有中断源只能通过指定的中断通道向内核申请中断。
以STM32F103芯片为例,它支持43个可屏蔽中断通道(不包括16个Cortex-M3的中断线),已经固定分配给相应的片内外设。由于中断源数量较多,而中断通道有限,会出现多个中断源共享同一个中断通道的情况。
3.4 中断优先级
- NVIC中有一个8位中断优先级寄存器NVIC_IPR,理论上可以配置0~255共256级中断。
- STM32只使用了其中的高4位,并分成抢占优先级和子优先级两组。
中断嵌套:
多个中断同时提出中断申请时
- 先比较抢占优先级,抢占优先级高的中断先执行。
- 如果抢占优先级相同,则比较子优先级。
- 二者都相同时,比较中断编号。编号越小,优先级越高。中断编号位于芯片头文件中。
STM32中断优先级分组
HAL库初始化函数HAL_Init将优先级分组设置为第4组,即有0~15,共16级抢占优先级,没有子优先级。编号越小的优先级越高:0号为最高,15号为最低。
3.5 EXIT外部中断控制器
GPIO引脚的外部中断
触发方式:
- 上升沿触发
- 下降沿触发
- 双边沿触发
引脚分组:
- 尾号相同的引脚一组,接入1个外部中断线。
- 同组引脚只能有一个设置为外部中断功能。
中断通道:
- EXTI0~EXIT4分别具有独立的中断通道
- EXTI5~EXIT9共享同一个中断通道
- EXTI5~EXIT9共享同一个中断通道
4 HAL库中断处理流程
4.1 编程步骤
在STM32CubeMX中完成
- 设置中断触发条件
- 设置中断优先等级
- 设能外设中断
HAL库的接口函数完成
- 清除中断标志
- 编写中断服务程序
4.2 HAL库对中断的封装处理
- 统一规定处理各个外设的中断服务程序
HAL_PPP_IRQHandler
。 - 在中断服务程序
HAL_PPP_IRQHandler
完成了中断标志的判断和清除。 - 将中断中需要执行的操作以回调函数的形式提供给用户。
启动文件startup_stm32fxxx.s
- 该文件存放在MDK-ARM组中。在该文件中,预先为每个中断编写了一个中断服务程序,只是这些中断服务程序都是死循环,目的只是 初始化中断向量表 ;
- 中断服务程序的属性定义为“
weak
”。weak
属性的函数表示:如果该函数没有在其他文件中定义,则使用该函数;如果用户在其他地方定义了该函数,则使用用户定义的函数。
中断服务程序文件:stm32fxxx_it.c
该文件存放在User组中,用于 存放各个中断的中断服务程序 ;
在使用CubeMX软件进行初始化配置时,如果使能了某一个外设的中断功能,那么在生成代码时,相对应的外设中断服务程序
HAL_PPP_IRQHandler
就会自动添加到该文件中,用户只需要在该函数中添加相应的中断处理代码即可。
外部中断所对应的中断服务程序外部中断线 中断服务程序的函数名称 外部中断线0(EXTI Line 0) EXTI0_IRQHandler 外部中断线1(EXTI Line 1) EXTI1_IRQHandler 外部中断线2(EXTI Line 2) EXTI2_IRQHandler 外部中断线3(EXTI Line 3) EXTI3_IRQHandler 外部中断线4(EXTI Line 4) EXTI4_IRQHandler 外部中断线5~9(EXTI Line[9:5]) EXTI9_5_IRQHandler 外部中断线10~15(EXTI Line[15:10]) EXTI15_10_IRQHandler 例如
/** * @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 */ }
4.3 外部中断处理流程
假设微控制器芯片为STM32F103,设置引脚PA0为外部中断功能。当引脚PA0出现脉冲边沿时,将触发外部中断。
由于外部中断主要是利用GPIO引脚实现,因此外部中断数据类型的定义放在stm32f1xx_hal_gpio.h
文件中,外部中断接口函数的实现放在stm32f1xx_hal_gpio.c
文件中。
引脚初始化
成员变量Mode的取值范围GPIO_MODE_IT_RISING
上升沿触发GPIO_MODE_IT_FALLING
下降沿触发GPIO_MODE_IT_RISING_FALLING
双边沿触发
外部中断通用处理函数
HAL_GPIO_EXTI_IRQHandler
/** * @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); } }
函数原型 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) 功能描述 作为所有外部中断发生后的通用处理函数 入口参数 GPIO_Pin:连接到对应外部中断线的引脚,范围是 GPIO_PIN_0~GPIO_PIN_15 返回值 无 注意事项 1. 所有外部中断服务程序均调用该函数完成中断处理2. 函数内部根据GPIO_Pin的取值判断中断源,并清除对应外部中断线的中断标志3. 函数内部调用外部中断回调函数HAL_GPIO_EXTI_Callback完成实际的处理任务4. 该函数由CubeMX自动生成 外部中断回调函数
HAL_GPIO_EXTI_Callback
/** * @brief EXTI line detection callbacks. * @param GPIO_Pin: Specifies the pins connected EXTI line * @retval None */ __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { /* Prevent unused argument(s) compilation warning */ UNUSED(GPIO_Pin); /* NOTE: This function Should not be modified, when the callback is needed, the HAL_GPIO_EXTI_Callback could be implemented in the user file */ }
函数原型 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 功能描述 外部中断回调函数,用于处理具体的中断任务 入口参数 GPIO_Pin:连接到对应外部中断线的引脚,范围是 GPIO_PIN_0~GPIO_PIN_15 返回值 无 注意事项 1. 该函数由外部中断通用处理函数HAL_GPIO_EXTI_IRQHandler调用,完成所有外部中断的任务处理2. 函数内部先根据GPIO_Pin的取值来判断中断源,然后执行对应的中断任务3. 该函数由用户根据实际需求编写
任务实践
基于STM32F103C8T6,开发板原理图
利用按键KEY1改变指示灯LED1的闪烁频率,闪烁频率设置为3档:
- 初始状态时,LED1按照1Hz的频率闪烁;
- 第一次按键后,LED1按照5Hz的频率闪烁;
- 第二次按键后,LED1按照20Hz的频率闪烁,并重复上述过程。
注:本任务例程使用的开发板,LED1与STM32的PA1相连接,KEY1与PA0相连接。KEY1原理图如下:
使用按键时,需要设置PA0为输入上拉模式,这样在KEY1没有按下时,PA0可以读取到高电平,KEY1按下时PA0可以读取到低电平。
- 配置PA0为GPIO_EXIT0,PA1为GPIO_Output
- PA1保持默认GPIO输出模式即可
- PA0配置为下降沿触发,上拉模式
- 使能外部中断线
- 配置中断优先级分组为第四组16级抢占优先级,没有子优先级
以上步骤生成如下代码:
stm32f1xx_hal_gpio.c
中生成GPIO引脚配置代码,并在main.c中调用void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); /*Configure GPIO pin : PA0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PA1 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* EXTI interrupt init*/ HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); }
- 开启外设时钟RCC
- 配置PA0,PA1两个引脚结构体
- 设置EXTI0中断优先级为0,并使能这个中断
stm32fxxx_it.c
中生成外设中断服务程序/** * @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 */ }
编写程序
在main.c
中定义指示灯闪烁频率,0代表1Hz,1代表5Hz,2代表20Hz/* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ volatile uint8_t Speed = 0; /* USER CODE END PV */
在
main.c
中编写应用代码/* USER CODE BEGIN 3 */ if (Speed == 0) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1); HAL_Delay(1000); } else if (Speed == 1) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1); HAL_Delay(200); } else { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1); HAL_Delay(50); } } /* USER CODE END 3 */
在
main.c
中外部中断回调函数HAL_GPIO_EXTI_Callback
/* USER CODE BEGIN 4 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_0) { Speed++; if (Speed == 3) { Speed = 0; } } } /* USER CODE END 4 */
-
微控制器
+关注
关注
48文章
7482浏览量
151009 -
处理器
+关注
关注
68文章
19155浏览量
229040 -
STM32
+关注
关注
2265文章
10870浏览量
354685 -
中断系统
+关注
关注
1文章
96浏览量
61000
发布评论请先 登录
相关推荐
评论