目录


一、NVIC

1.中断优先级

中断优先级:中断优先级分为抢占优先级和响应优先级;我们配置一个中断的抢占优先级和响应优先级来设置中断的优先级。
抢占优先级:在一个中断正在发生时,另外一个抢占优先级比它高的中断也发生了,那么抢占优先级高的那个中断就可以打断抢占优先级低的那个中断。
响应优先级:如果两个中断的同时发生,他们的抢占优先级相同,但一个的响应优先级高于另外一个,那么响应优先级高的那个中断就先发生。

2.中断优先级分组

我们通过调用函数或者直接操作寄存器来实现中断优先级的分组:
其中第二列是我们可以设置的中断优先级的范围,第三列是我们可以设置的响应优先级的范围。
在固件库中,我们通过调用下面这个函数来确定中断优先级分组:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

这个图片在文件夹 stm32f10x_exti.c 中的 misc.h这个文件夹可以找到;

二、外部中断的一般配置过程

1.初始化GPIO
2.开启IO口复用时钟
3.设置IO口与中断线的映射关系
4.初始化线上中断(EXTI),设置触发条件
5.配置中断分组(NVIC),并使能中断
6.编写中断服务函数
7.清除中断标志位

1.GPIO_Init()

我这里使用的是红外避障模块,IO口:PB4

void HongWai_Init(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据参数初始化GPIOB.4
}

要注意的点就是:因为红外避障模块遇到障碍物的时候会输出一个高电平,所以配置GPIO的模式的时候要配置成下拉输入。

2.void EXTIX_Init(void)编写

void EXTIX_Init(void)
{
    //1.GPIO初始化
    HongWai_Init();
    EXTI_InitTypeDef EXTI_InitStructre;
    NVIC_InitTypeDef NVIC_InitStructre;
    //2.开启IO口复用时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    //3.设置IO口与中断线的映射关系
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4);
    //4.初始化线上中断(EXTI),设置触发条件
    EXTI_InitStructre.EXTI_Line = EXTI_Line4;//配置中断线,和IO口有关
    EXTI_InitStructre.EXTI_LineCmd = ENABLE;//使能
    EXTI_InitStructre.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
    EXTI_InitStructre.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
    EXTI_Init(&EXTI_InitStructre);
    //5.配置中断分组(NVIC),并使能中断
    NVIC_InitStructre.NVIC_IRQChannel = EXTI4_IRQn;
    NVIC_InitStructre.NVIC_IRQChannelCmd = ENABLE;//使能
    NVIC_InitStructre.NVIC_IRQChannelPreemptionPriority = 2;//中断优先级配置
    NVIC_InitStructre.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStructre);
}

关键代码讲解:

//设置IO口与中断线的映射关系
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4);

因为我使用的是PB4,所以参数就是GPIO_PortSourceGPIOBGPIO_PinSource4

//4.初始化线上中断(EXTI),设置触发条件
	EXTI_InitStructre.EXTI_Line = EXTI_Line4;//配置中断线,和IO口有关
	EXTI_InitStructre.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发

因为我用的IO是PB4所以中断线就是EXTI_Line4;
EXTI_Trigger_Rising上升沿触发:当IO的电平由低转到高的时候会触发中断。

//5.配置中断分组(NVIC),并使能中断
	NVIC_InitStructre.NVIC_IRQChannel = EXTI4_IRQn;

如果io口为1-4:这个参数就是:EXTI1_IRQn ,EXTI2_IRQn,EXTI3_IRQn ,EXTI4_IRQn
如果io为5-9:这个参数就是:EXTI9_5_IRQn
io为10到15:io口为:EXTI15_10_IRQn

3.void EXTI4_IRQHandler()中断触发函数

这个函数名称不可改,和你使用的IO口有关,和上面的NVIC_InitStructre.NVIC_IRQChannel配置是一样的

因为我用的是pb4,所以我编写的中断服务函数就是EXTI4_IRQHandler()

void EXTI4_IRQHandler()
{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4))
	{
		LED0 = !LED0;
	}
	EXTI_ClearITPendingBit(EXTI_Line4);
}

我配置的触发方式是上升沿触发,所以进入到中断函数之后是高电平,所以我读取PB4的电平,如果为高电平就执行操作,中间的就可以自己写了。
一定不要忘了:EXTI_ClearITPendingBit(EXTI_Line4);

总结

奉上视频:

https://www.bilibili.com/video/BV1Ju411S77q/?spm_id_from=888.80997.embed_other.whitelist

最后能达到的效果就是当红外模块检测到障碍物时触发中断,可以在中断服务函数中改为让小车拐弯,这样就实现了一个避障功能。