抢占式优先级和响应优先级。抢占优先级先判断,如果存在多个中断同时到达且它们的抢占优先级相同则再判断响应优先级
如果不是同时到达且抢占优先级同则按先后顺序依次执行。当同时到达且抢占优先级和响应优先级都同则根据中断表中的排位顺序决定哪个先执行(越靠前越先执行)
中断初始化里的中断源定义在stm32f10x.h头文件(300行附近 )
中断初始化里的抢占式优先级配置(第二组则值是0--3)
中断初始化里的响应式优先级配置(第二组则值是0--3)
中断初始化里的使能配置(enable , disable)
中断服务程序的文件名也是固定的,在启动文件startup_stm32f10x_hd.s中查看(100行附近)
345产生事件,678产生中断(事件和中断区别)
从外部激励信号来看,中断和事件是没有分别的,只是在芯片内部分开,一路信号会向CPU产生中断请求,另一路信号会向其它功能模块发送脉冲触发信号,其它功能模块如何相应这个触发信号,则由对应的模块自己决定。
中断和事件的区别自行看自己的资料文件,由于是付费版权不在这里放出
复用:STM32有很多的内置外设,这些外设的外部引脚都是与GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。
重映射:每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
为了使不同器件封装的外设IO功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。
打个比方说,串口1的TX,RX引脚是在PA9,和PA10端口,但是同时它有两个映射端口PB6,PB7。开启重映射,PB6和PB7同样可以使用串口1。
映射的引脚是固定的
- 初始化用来产生中断的 GPIO; 这步我们省了,因为在key.c里面已经初始过了单片机的按键
- AFIO映射
- 初始化 EXTI;
- 配置 NVIC;
- 编写中断服务函数(名字固定)
exti.c
#include "exti.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
void My_EXTI_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC初始化要用的结构体(2*)
EXTI_InitTypeDef EXTI_InitStructure; //初始化EXTI初始化用结构体(3*)
//1*AFIO进行映射(开启时钟然后映射)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//stm32f10x_it.c的rcc头文件中
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//映射,在system_stm32f10.c的gpio.h中寻找
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);//映射
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);//
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);//
//2*NVIC配置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //中断源, NVIC函数在misc.c里面,配置中断通道在stm32f10x.h中找通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //配置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 3; //配置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_InitStructure); //初始化
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//3*初始化EXTI外部中断
EXTI_InitStructure.EXTI_Line = EXTI_Line0; //中段线0 ,在misc.c的stm32f10x_exti.h
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //模式:中断
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //触发方式:上升沿
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line2|EXTI_Line3|EXTI_Line4;//中段线2
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //模式:中断
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //触发方式:下降沿
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
//4*中断服务函数
void EXTI0_IRQHandler() // 名字在启动文件startup_stm32f10xhd.s中
{
if(EXTI_GetITStatus(EXTI_Line0)==1) //获取中断线的标志位,看是否有中断,在misc.c的stm32f10x_exti.h
{
delay_ms(10); //消抖
if(K_UP==1)
{
led2=0;
}
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
}
void EXTI2_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line2)==1)
{
delay_ms(10);
if(K_LEFT==0)
{
led3=1;
}
}
EXTI_ClearITPendingBit(EXTI_Line2);
}
void EXTI3_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line3)==1)
{
delay_ms(10);
if(K_DOWN==0)
{
led2=1;
}
}
EXTI_ClearITPendingBit(EXTI_Line3);
}
void EXTI4_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line4)==1)
{
delay_ms(10);
if(K_RIGHT==0)
{
led3=0;
}
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
exti.h
#ifndef _exti_H
#define _exti_H
#include "system.h"
void My_EXTI_Init(void);
#endif
mian.c
#include "systick.h"
#include "led.h"
#include "system.h"
#include "key.h"
#include "exti.h"
int main()
{
u8 i;
SysTick_Init(72); //系统时钟初始
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//在misc.c里的misc.h中寻找
KEY_INIT(); //初始化KEY
LED_INIT(); //初始化LED
My_EXTI_Init();
while(1)
{
i++; //每加20就变led状态,每次延时10ms,200ms变换一次
if(i%20==0)
{
led1=!led1;
}
delay_ms(10);
}
}