中断系统
中断:在主程序运行过程中,当有特定的中断触发条件时,CPU您可以暂停当前正在运行的程序来处理中断程序,并将当前程序的地址压入堆栈。中断程序处理完成后,将地址弹出堆栈,返回刚刚暂停的位置继续执行程序。
中断优先级:当有多个中断源同时申请中断时,CPU优先级较高的中断源将根据中断源的优先级进行判断,stm中断优先级为抢占优先级和响应优先级。
中断嵌套:当一个中断程序正在运行时,有新的更高优先级中断源申请中断,CPU暂停当前的中断程序,处理新的中断程序,并将当前程序的地址压入堆栈。中断程序处理完成后,将地址弹出堆栈,然后执行第二优先级中断程序,直到返回主程序。
stm32的外部中断
EXTI(External interrupt/event controller)—通过NVIC中断申请或发生事件。 EXTI可监测指定GPIO口的电平,当IO当口发生电平变化时,EXTI将立即向NVIC通过发出中断申请NVIC后即可中断CPU主程序,使CPU执行EXTI相应的中断程序。 STM32的每个IO可作为外部中断输入,但每组IO由于所有口相同的引脚都不能同时外部中断,因此不能同时出发IO相同数量的引脚只能对应于相同的中断通道。 EXTI有 占用20条中断/事件线 EXTI0至 EXTI15,16-19分别是PVD输出,RTC时钟事件,USB唤醒事件,互联网以太网唤醒事件。
NVIC先挖个坑,之后再补充(中断分组)
中断函数
STM32中断向量表中只有这些函数的符号。要编写中断函数,必须设置相应的函数名,编译器可以通过函数名找到中断程序的入口。 可以看出,只有7个中断函数,其中0-4通道分别占用一个函数,5-9通道和10-15通道分别占用一个函数。在接下来的两个函数中,在进入中断函数后,可以判断哪个通道被触发并执行相应的中断程序。例如,7号通道被选为中断源。
常用库函数外部中断
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); ////配置结构的初始化EXTI void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct); ///默认初始化结构 EXTI_InitTypeDef EXTI_InitStructure; //定义结构体,可配置结构体成员设置EXTI模式 void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); //配置IO口与中断线的映射关系 FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); ///获得中断线状态,判断是否有中断 void EXTI_ClearITPendingBit(uint32_t EXTI_Line); ///中断后需要手动软件重置标志位,否则会在中断函数中循环
数字输出控制光敏传感器LED灯
void LightSensorExtiInit() { //PB7 上拉输入 光敏传感器DO //先初始化时钟,GPIO和AFIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //要使能GPIO提供时钟 //初始化GPIO GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); //映射中断源 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource7);//配置AFIO中断引脚,将7线拨到GPIOB上 //配置EXTI EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line7; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //这里设置上升沿和下降沿触发 EXTI_Init(&EXTI_InitStructure);//这里别写错了,是中断的初始化,不是结构体的初始化 //这里刚开始的时候写成EXTI_StructInit,导致一直没有现象,找了半天才找到问题= = //这里只有一个中断源,中断分组可以随便设置 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级,这里随便设置 NVIC_Init(&NVIC_InitStructure); } //先配置IO口,然后使能复用功能,之后配置中断功能,最后配置NVIC通道 //stm32中断函数的函数名都是固定的,对应中断向量表 void EXTI9_5_IRQHandler(void) { //先判断是不是这条通道 if(EXTI_GetITStatus(EXTI_Line7) == 1) { LEDTurn(); //LED
开关切换 } EXTI_ClearITPendingBit(EXTI_Line7); //最后要清除标志位,否则会一直申请中断,卡死 }
选择上升沿和下降沿触发,当光线太暗,光敏传感器的DO口从0输出1,是一个上升沿,此时LEDTURN触发,灯打开,光线变亮泽再触发,灯关闭,即实现了所需功能。