【STM32】标准库 菜鸟入门 外部中断

中断系统

中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行

作用:在没有中断的时候,系统要不断检测是否有中断产生,防止外部中断被忽略还是串口数据被覆盖,(串口通信接收到数据,定时器来说是定时时间到了,外部中断来说就是高低电平变化),有了中断可以执行其他事情,带到满族中断条件才进行。

中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源 ,0,1,2,3,4.....依次降低。

中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

 stm32的中断非常多,若果全部连接到cpu上的话会比较困难,中断很多容易产生拥堵,所以设置NVIC(CPU小助手),/n的意思是有n条线,经过NVIC的优先级筛选,一个又一个的输送到CPU中进行处理。比如医院的叫号系统。

优先级解析:

抢占优先级:病人在看病,来人之后直接打断,让医生帮他看病(中断嵌套)

响应优先级:病人在看病,来人之后还需要等待,但是却可以越过本来在排队的人,上一个看完马上到他

数值小的优先排队。 

中断号:

EXTI

中断有很多种,外部中断只是其中一种。

EXTI(Extern Interrupt)外部中断 EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

支持的触发方式:上升沿/下降沿/双边沿/软件触发

支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断(比如PA0与PB0) 

通道数:16个GPIO_Pin,外加PVD输出(PVD电源电压检测恢复时,电源电压从电压过低恢复时,需要PVD借助一下外部中断进入停止模式)、RTC闹钟(定好闹钟进入休眠,需要用就使用外部中断)、USB唤醒、以太网唤醒    因为外部中断有个功能,从低功耗模式的停止模式下唤醒STM32.

触发响应方式:中断响应/事件响应 (触发中断之后,可以不选择进入cpu处理,而是把中断信号传入外设,触发别的外设进行响应,不走正常的中断流程,ADC,DMA等)

EXTI基本结构

AFIO选择一组连接EXTI, EXTI上只有20个接收引脚,但是每一个GPIO外设就已经是16个引脚了,所以同号引脚只会有一个接在后续的通道上,所以前面会说所有GPIO口口能触发中断,但相同的Pin不能同时触发中断(比如PA0与PB0) 。

 其中9-5,15-10是一起的,效果是一样的,进一步区分还需要根据标志位来分别。

底下的20根连接外设的线是事件响应。

AFIO主要用于引脚复用功能的选择和重定义

AFIO经过数据选择器,把每一个寄存器中的每一个相同的位选择一个出来进行传入EXTI中。

在STM32中,AFIO主要完成两个任务:复用功能引脚重映射(就是刚开始服用肝功能那个表,功能切换就是用它)、中断引脚选择 

 

 从输入线输入,通过出发选择寄存器选择触发方式,下方的出口是触发事件,上面的是正常的中断响应。中断挂起寄存器置1,则信号通过,0则相反,这个需要请求然后给设置的。中断屏蔽寄存器跟信号相与,控制信号的输出是什么,比如中断寄存器置1,则出去的是0或者1由过来的信号自身决定.

支持的触发方式是上升沿下降沿以及软件触发,这个软件中断事件寄存器跟硬件的任意一条路只要存在都行,都能触发中断。

上面表示可以通过总线访问这些寄存器。

或门与门数据选择器,可以多输入,但是只能一个输出,非门是一个输入一个输出。

什么时候用外部中断:对于STM32来说,想要获取的信号是外部驱动的很快的突发信号,比如拧动旋转编码器(不知道什么时候来,辨别很快)。

对于按键的读取,一般采用主函数循环读取的方法,因为中断的话不好处理抖动问题。

图一,对射式红外传感器测速,光栅编码盘不断转动,遮挡透过不断切换,电平不断高低变换的方波,方波的个数代表角度,频率代表转速,只有一路输出,不能测量旋转方向。

图二,内侧两根跟中间c相连,外边分别跟两边的相连,,上面两个跟跟中间额按键相连,按键按下相连,松开断开。编码盘类似光栅一样的东西,可以接通触电的通断,输出两路波形,相对的光栅经过设计,分别相差90度的波形。转动时,分别以相差90度的导通。

正向旋转,B比A提前,反向旋转,B比A滞后90度。

上拉为高电平,导通则下拉为低电平。

中间那个东西旋转时,两边以相差90度相继导通。

第三个图,霍尔传感器型。

是重要开启,外设才能工作,比如NVIC,AFIO,以及I/O口,但是NVIC(内核外设都不需要开启时钟,住在皇宫,跟CPU一起的)跟EXTI两个外设的时钟是一直都开的,就不用手动开启了,只需要开启AFIO以及I/O口就行了。

配置外部中断输入引脚的时候,要看是怎么样进行配置的,可以查阅数据手册,看上面所给的要求以及建议。

AFIO没有单独的函数,都在GPIO文件夹里面,.h文件中寻找。

红外传感器计次

Keil5右键main.c,Close all ...关闭除了main其他所有的窗口

第一步,配置GPIO口以及AFIO的开启时钟函数,EXTI唤醒不用开启时钟,另外NVIC也不用。因为他是内核的外设

第二步,结构体进行初始配置,配置GPIO,在输入模式中如果不确定,可以参考手册8.1最后那里。

第三步,AFIO函数在GPIO.h文件中,GPIO_EXTILineConfig(GPIO_PortSourceGPIOX,GPIO_PinSourceX);

这个函数可以配置AFIO的数据选择器,来选择我们想要的中断引脚。如上代表的是号数据选择器上的PB14号引脚导通。

void CountSensor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
}

void EXTI_DeInit(void);  //电泳它可以把EXTI所有的配置清除,恢复到上电默认状态。
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);  //初始配置,但是因为EXTI只有一个,不用想GPIO 一样,直接用取地址的符号就好了。
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);  //
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);//软件触发外部中断

/*这两个用在主函数中*/
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//获取指定的标志位是否被置1
void EXTI_ClearFlag(uint32_t EXTI_Line);//对置1标志位清除

/*这两个用在中断函数中*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);//获取中断标志位是否被置1
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//清除中断挂起标志位        

最后两个只适用于获取中断标志位的,而倒数第三第四个则是可以获取任意位置的,所以一般中断程序中使用后面两个,主函数中使用倒数第三第四个。

NVIC的库函数就是在misc.h文件之中。

中断函数的函数声明在startup_stm32f10x_md.s;


void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); //指定优先级分组,中断不多问题都不大,优先级设置必须都一致,设置一遍就够了,但是如果在模块中,需要每个模块都声明。
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); //初始化NVIC

对于NVIC的初始化,他的中断通道一些参数不能直接查询到,需要在Ctrl+f之后勾选查找范围才能找到。

在文件夹中,减号收起,加号点开,选择自己的类型。

中断函数的函数名字一般都是固定的,我们可以在startup文件夹中进行参考,找到相应的中断函数名。

void ....(void)

{

}

由于前面说过有几个端口是一起的,所以要用EXTI_GetStatus();进行获取某位信息,具体用法在exti中跳转查看。if它......,之后记得清楚中断标志位,不然会一直进行中断申请,卡死在中断函数中。

中断函数不用声明,应为不用调用,自动执行。

旗帜本质就是把上面那些图的路给打通。

模块函数中的数返回主函数:

void EXTI15_10_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line14) == SET)//判断中断标志位,进入中断之后会置1
	{
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)//读取GPIO的电平
		{
			 LED_TURN();
		}
		EXTI_ClearITPendingBit(EXTI_Line14);
	}
}

如果要共用一个函数,必须放进.文件中声明,主函数也可以用

注意显示屏直接调用up主给的东西作为.c.h文件就行,直接在主函数引用OLED_Init();

NVIC的配置,有不同的端口要分批次配置,重新复制配置。

中断中最好不要设置什么高延时的函数代码,应为它是执行突发事件的,导致中断阻塞,最好不要在中断以及主程序中显示同一个硬件。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值