外部中断的设置和一些寄存器的介绍
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1)初始化IO 口为输入。
外部中断输入的IO 口的状态,可以设置为上拉/下拉输入,也可以设置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触发。在干扰较大的地方,就算使用了上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一定程度防止外部干扰带来的影响。
①使能IO口的时钟
②清除原来的相应的设置
③设置成上拉输入0x80
④把GPIO_ODR相应的位设置成 1
2)开启IO 口复用时钟,设置IO 口与中断线的映射关系。
STM32 的IO 口与中断线的对应关系需要配置外部中断配置寄存器EXTICR,这样我们要先开启复用时钟,然后配置IO 口与中断线的对应关系。才能把外部中断与中断线连接起来。
①使能复用时钟
RCC_APB1ENR第0位AFIOEN:辅助功能IO时钟使能RCC->APB1ENR |= 1<<0
②设置外部中断配置寄存器(AFIO_EXTICR1)
总共有三个配置寄存器,分别对应着15个中段线。每个寄存器存放四个。如上图。
在设置这些位时仍然2步:
首先:清除原来的设置。AFIO->EXTICR[0]&=~(0x000F<<0); //清除中断线0的原来的设置
然后:设置映射到那个端口。AFIO->EXTICR[0]|=0<<0;//设置引脚为0000也就是A口扩展:事件控制寄存器(AFIO_EVCR)
位7 EVOE:允许事件输出(Event output enable) 位7 该位可由软件读写。当设置该位后,Cortex的EVENTOUT将连接到由PORT[2:0]和PIN[3:0]选定的I/O口。
位6:4PORT[2:0]:端口选择000:选择PA 001:选择PB 010:选择PC 011:选择PD 100:选择PE
位3:0 PIN[3:0]:引脚选择(x=A…E)
0000:选择Px0 0001:选择Px1 0010:选择Px2 0011:选择Px3 0100:选择Px4 0101:选择Px5 0110:选择Px6 0111:选择Px7 1000:选择Px8 1001:选择Px9 1010:选择Px10 1011:选择Px11 1100:选择Px12 1101:选择Px13 1110:选择Px14 1111:选择Px15
3)开启与该IO 口相对的线上中断/事件,设置触发条件
我们要配置中断产生的条件,STM32 可以配置成上升沿触发,下降沿触发,或者任意电平变化触发,但是不能配置成高电平触发和低电平触发。这里根据自己的实际情况来配置,同时要开启中断线上的中断。这里需要注意的是:如果使用外部中断,并设置该中断的EMR、位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。而不设置EMR,软件仿真就可以进入中断服务函数,并且硬件上也是可以的。建议不要配置EMR 位
①配置中断屏蔽寄存器(EXTI_IMR) 的相应中断线设置成 1
被设置成1 也就是开放来自线上的中断请求。
②设置触发方式。上升沿触发选择寄存器(EXTI_RTSR) 下降沿触发选择寄存器(EXTI_FTSR) 直接在相应的触发方式写1 就行了。
扩展:事件屏蔽寄存器(EXTI_EMR)使用如图上面中断屏蔽寄存器
软件中断事件寄存器(EXTI_SWIER) SWIERx: 线x上的软件中断位18:0 当该位为’0’时,写’1’将设置EXTI_PR中相应的挂起位。如果在EXTI_IMR和EXTI_EMR中允许产生该中断,则此时将产生一个中断。
注:通过清除EXTI_PR的对应位(写入’1’),可以清除该位为’0’。
挂起寄存器(EXTI_PR)PRx: 挂起位(Pending bit) 位18:0
0:没有发生触发请求
1:发生了选择的触发请求
当在外部中断线上发生了选择的边沿事件,该位被置’1’。在该位中写入’1’可以清除它,也可以通过改变边沿检测的极性清除。
4)配置中断分组(NVIC),并使能中断
配置中断的分组,以及使能,对 STM32 的中断来说,只有配置了 NVIC的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority :响应优先级
//NVIC_Channel :中断编号
//NVIC_Group :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8
NVIC_Channel,u8 NVIC_Group) {
u32 temp;
u8 IPRADDR=NVIC_Channel/4; //每组只能存4个,得到组地址
u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
IPROFFSET=IPROFFSET*8+4; //得到偏移的确切位置
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位
if(NVIC_Channel<32)NVIC->ISER[0]|=1< 话,相反操作就OK) else NVIC->ISER[1]|=1<<(NVIC_Channel-32); NVIC->IPR[IPRADDR]|=temp< } 关于终端分组的介绍请参考《中断分组》。 5)编写中断服务函数 中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断, 但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃!所以在开启了某个中 断后,一定要记得为该中断编写服务函数。在中断服务函数里面编写你要执行的中断后的操 作。 这里要强调的是,在中断函数里要注意一下几点: ①是否需要清除中断标志,这个在中断挂起里面相应位写1即可。 ②在中断函数里尽量不要写太多的代码,应该使其快速的完成。 ③中断处理函数名是固定的,别写错了。 例如:void EXTI4_IRQHandler(void){} 格式一般为void X_IRQHandler(void){}. 而在系统中对应的中段号也要一一对应。 #define WWDG_IRQChannel ((u8)0x00) /* Window WatchDog Interrupt */ #define PVD_IRQChannel ((u8)0x01) /* PVD through EXTI Line detection Interrupt */