中断系统
- 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
- 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
- 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回
中断执行流程
NVIC基本结构
CPU相当于一个医生,NVIC相当于叫号系统,EXTI、TIM、ADC、USART相当于病人,看这里面谁的更紧急谁就优先级越小。
NVIC优先级分组
响应优先级:上个病人在看病,这个病人看病完了之后,紧急的病人即使后来的,也会最先进去看病,插队的优先级。
抢占优先级:如果这个病人更加紧急,并且此时已经有人在看病,那么就会把看病的人放在一边,先让更紧急的病人看病,看完之后再看放在一边的病人。
EXTI简介
- EXTI(Extern Interrupt)外部中断
- EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
- 支持的触发方式:上升沿/下降沿/双边沿/软件触发
- 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
- 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
- 触发响应方式:中断响应/事件响应
EXTI基本结构
AFIO复用IO口
- AFIO主要用于引脚复用功能的选择和重定义
- 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择
EXTI框图
旋转编码器介绍
- 旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向
- 类型:机械触点式/霍尔传感器式/光栅式
建议
尽量别在中断函数里调用复杂函数,可以执行一个标志位,在主函数或其他函数里执行其他代码。
代码部分
配置流程
1、开启时钟;
2、开启AFIO时钟;
3、GPIO配置;
4、选择用作EXTI线路的GPIO引脚;
5、EXTI配置;
6、配置NVIC优先级分组;
7、NVIC配置;
8、找到EXTI函数并在里面写用户代码(在startup_stm32f10x_md.s中)。
中断配置
1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 1.开启GPIOB时钟2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 2.开启AFIO时钟3 4 GPIO_InitTypeDef GPIO_InitStructure; // 3.GPIO配置5 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;6 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;7 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 GPIO_Init(GPIOB, &GPIO_InitStructure);9 10 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); // 4.选择用作EXTI线路的GPIO引脚 11 12 EXTI_InitTypeDef EXTI_InitStructure; // 5.EXTI配置 13 EXTI_InitStructure.EXTI_Line = EXTI_Line14; 14 EXTI_InitStructure.EXTI_LineCmd = ENABLE; 15 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 16 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 17 EXTI_Init(&EXTI_InitStructure); 18 19 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 6.配置NVIC优先级分组 20 21 NVIC_InitTypeDef NVIC_InitSturcture; // 7.NVIC配置 22 NVIC_InitSturcture.NVIC_IRQChannel = EXTI15_10_IRQn; 23 NVIC_InitSturcture.NVIC_IRQChannelCmd = ENABLE; 24 NVIC_InitSturcture.NVIC_IRQChannelPreemptionPriority = 1; 25 NVIC_InitSturcture.NVIC_IRQChannelSubPriority = 1; 26 NVIC_Init(&NVIC_InitSturcture);
1 void EXTI15_10_IRQHandler(void) // 8.找到EXTI函数并在里面写用户代码(函数在Startup_stm32f10x_md.s)2 {3 if (EXTI_GetITStatus(EXTI_Line14) == SET)4 { 5 if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)6 {7 CountSensor_Count++;8 } 9 EXTI_ClearITPendingBit(EXTI_Line14); 10 } 11 }