目的——学会中断配置结构,总中断的开关,中断优先级的配置,了解中断服务函数 将两个板级支持包bsp.exti.c和bsp.exti.h 在打开的工程文件内导入User文件夹内 KEIL\Target Option\C/C++\include paths 添加 User\exti文件夹 misc.h /* for NVIC嵌套向量中断控制器and SysTick系统滴答SystemTick校准值寄存器*/ stm32f10x_rcc.h 系统时钟 stm32f10x_gpio.h 输入输出接口 stm32f10x_exti.h 外部中断事件控制器 以上四个.h文件需要包含进去(stm32f10x_conf.h) 准备工作完成 看main.c文件 stm32f10x.h bsp.led.h bsp.exti.h 三个头文件要用到 #define CLI() __set_PRIMASK(1) #define SEI() __set_PRIMASK(0) 定义总中断的开与关(要成对使用) LED_GPIO_Config(); LED配置 LED1_ON; 打开LED 外部中断线配置 EXTI_PC13_Config(); 进入定义 在bsp.exti.c文件可以找到PC13中断的详细配置 GPIO_InitTypeDef GPIO_InitStructure GPIO的初始化 EXTI_InitTypeDef EXTI_InitStructure; 外部中断先路的初始化 固件库P100 配置中断线路PC13和AFIO端口复用时钟 RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE); 这里要了解所有被门控的APB2外设时钟 AFIO 功能复用时钟 GPIOA,B,C,D,E GPIO端口时钟 ADC1,2 ADC时钟 TIM1,2 定时器时钟 SPI1 串行外设接口时钟 USTART1 通用同步异步收发器时钟 ALL APB2所有外设时钟 配置PC13的嵌套向量中断控制器 NVIC_Configuration(); 进入定义 static void NVIC_Configuration(void) NVIV配置为静态函数 NVIC_InitTypeDef NVIC_InitStructure; NVIC初始化 参考固件库P167 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);给抢占优先级配置1位 最高n位 最低n位 优先组级别 | 抢占式优先级 | 响应优先级或称副优先级 | 4 | 4位/16级 2^4 | 0位/0级 2^0 | 3 | 3位/8级 2^3 | 1位/2级 2^1 | 2 | 2位/4级 2^2 | 2位/4级 2^2 | 1 | 1位/2级 2^1 | 3位/8级 2^3 | 0 | 0位/0级 2^0 | 4位/16级 2^4 |
由于仅配置1位,所以需要选用 PriorityGroup 1 PriorityGroup总共分为0,1,2,3,4五组,每一组抢占优先级的位数都不同 关于优先级的顺序 抢占优先级>响应优先级 IRQ 中断请求 Interrupt Request 配置P[A][B][C][D][E]13位中断源(因为要求程序用PC13中断LED灯) NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn P166有NVIC_IRQChannel描述(各种需要使能的中断) EXTI15_10_IRQn中断请求通道宏P(A-E)(10-15) 在stm32f10x.h文件中可以找到EXTI0-15的各个宏 0-4是每个都有如EXTI0,EXTI1—EXTI4 EXTI9_5_IRQn 外部中断线9-5ExternalLine[9:5] Interrupt EXTI15_10_IRQn 15-10 当用到别的接口时,需要注意宏的不同 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0 ; 开始配置抢占优先级 当有多个抢占优先级时,具有高抢占优先级的中断可以在低抢占优先级的中断处理过程中被响应,即中断嵌套。也就是高抢占优先级的中断可以嵌套在低抢占优先级的中断里 NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; 配置响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; 中断使能(否则中断不运作前提是总中断开启) NVIC_Init(&NVIC_InitStructure); NVIC初始配置完成 中断配置完成以后可以开始配置中断服务函数 此时返回main.c /* wait interrupt */ 此时一直在等待中断的来临 while(1) { } 在user\stm32f10x.it.c里面可以找到中断服务程序 void EXTI15_10_IRQHandler(void) PC13的函数名不要写错 if(EXTI_GetITStatus(EXTI_Line13) != RESET) 判断PC13线路中断是否触发 P102 若产生中断,则LED取反 LED1_TOGGLE; EXTI_ClearITPendingBit(EXTI_Line13); 取反完成后清除中断标志位 固件库P103 最后提到了中断总开关 在core_cm3.c文件中可以看到关于PRIMASK的程序 Set the priority mask bit in the prioritymask register 对于PRIMASK的设置 __ASM void __set_PRIMASK(uint32_t priMask) { msrprimask, r0 bxlr } 将r0的内容丢到primask 再跳转到lr中存放的地址,但是lr中存放的是什么地址 ARM中的LR有两种特殊用途:一是保存子程序返回地址 二是当异常发生时,LR中保存的值等于异常发生时PC的值减4或者减2。因此可以在各种异常模式下返回到异常发生前的相应位置继续执行 在这里bx lr是作为子程序的返回 所以main.c中的set_PRIMASK(1) set_PRIMASK(0)可以关闭 开启总中断
|