《嵌入式操作系统及ARM Cortex-MO》课件第四章_第1页
《嵌入式操作系统及ARM Cortex-MO》课件第四章_第2页
《嵌入式操作系统及ARM Cortex-MO》课件第四章_第3页
《嵌入式操作系统及ARM Cortex-MO》课件第四章_第4页
《嵌入式操作系统及ARM Cortex-MO》课件第四章_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第四章

异常与中断管理 4.1 LPC824异常管理 4.2 NVIC中断管理 4.3 LPC824外部中断

本章将介绍LPC824微控制器的异常与中断处理方法,重点介绍S断、多速率定时器中断和外部中断的响应方法,其他异常与中断的管理方ys法Ti与ck之定类时似器。中在启动文件startup_LPC82x.s中定义了中断向量表,以汇编语言的格式为各个异常和中断分配了地址标号,如表4-1所示。表4-1异常与中断向量的地址标号

表4-1中用汇编语言表示的各个异常与中断的地址标号,也用作C语言的异常与中断服务函数名,例如,SysTick定时中断的中断服务函数为“voidSysTick_Handler(void)”。 LPC824微控制器的异常就是Cortex-M0+的6个异常,即Reset、NMI、HardFault、SVCall、PendSV和SysTick,见1.6节表1-11。其中,Reset、NMI和HardFault异常的优先级依次为-3、-2和-1。SVCall、PendSV和SysTick异常的优先级可以配置为0、1、2或3,由系统异常优先级寄存器SHPR2和SHPR3设定,见表1-1。

LPC824异常的管理方法为:首先,配置异常,或称为初始化异常,异常是不能关闭的,所以,初始化异常是指设定异常产生的方式;然后,编写异常服务函数,在异常服务函数中添加对异常的响应处理。下面以SysTick异常(习惯上称SysTick定时器中断)为例,介绍异常的程序设计方法。 在项目ZLX01中,main函数实现LED灯闪烁的方式为:在无限循环体中,重复执行“延时约1秒再使LED灯闪烁”的操作。这种方式的缺点在于用户需要的LED灯闪烁功能只占用极少的CPU时间,而绝大部分CPU工作时间被延时函数占用,无法执行其他的操作。为了消除延时函数的影响,现在可用SysTick定时器中断服务实现LED灯闪烁功能,使得main函数的无限循环体中不再需要延时函数。 在项目ZLX01的基础上,新建项目ZLX02,保存在目录“D:\ZLXLPC824\ZLX02”中,此时的项目ZLX02与ZLX01完全相同(注意:工程文件名也相同)。新建文件systick.c和systick.h(这两个文件均保存到D:\ZLXLPC824\ZLX02\BSP目录下),并修改原来的main.c、includes.h和bsp.c文件,这些文件的代码和说明如程序段4-1至程序段4-5所示,项目ZLX02实现的功能如图4-1所示。4.1 LPC824异常管理图4-1 项目ZLX02的功能框图4.1 LPC824异常管理

程序段4-1systick.c文件 1 //Filename:systick.c 2 3 #include"includes.h" 4 5 voidSysTickInit(void) 6 { 7 SysTick->LOAD=300000-1;

8 SysTick->VAL=0;

9 SysTick->CTRL=(1uL<<0)|(1uL<<1)|(1uL<<2);

10 } 11

第5~10行的SysTickInit函数用于初始化SysTick定时器。第7~9行的SysTick结构体指针定义在LPC82x.h中,这里的“SysTick->LOAD、SysTick->VAL和SysTick->CTRL”分别对应着表1-6中的SysTick重装值寄存器SYST_RVR、SysTick当前计数值寄存器SYST_CVR和SysTick控制与状态寄存器SYST_CSR。根据1.5节可知,当LPC824工作在30MHz时钟下时,第7行将SYST_RVR设置为300000-1,SysTick定时器减计数到0的定时周期为100ms,即SysTick定时器中断频率为100Hz。第8行清零SysTick定时器的当前计数值,当SysTick定时器启动后,SYST_RVR的值自动装入SYST_CSR中。第9行打开SysTick定时器中断,并启动SysTick定时器。4.1 LPC824异常管理 12 voidSysTick_Handler(void) 13 { 14 staticInt32Ui=0;

15 i++;

16 if(i>=100) 17 { 18 LEDBlink();

19 i=0;

20 } 21 }

第12~21行的SysTick_Handler函数为SysTick定时器中断服务函数,函数名必须为SysTick_Handler(由表4-1中查得)。第14行定义静态变量i,每次SysTick中断到来后,i的值自增1(第15行),当i的值大于或等于100时(第16行为真),第18行调用LEDBlink函数使LED灯D9闪烁,然后,第19行清零i。因此,每100次SysTick定时器中断,LEDBlink函数将被调用一次,由于SysTick定时器中断的频率为100Hz,所以,LEDBlink函数每秒被调用一次,即LED灯D9每秒闪烁一次。4.1 LPC824异常管理

程序段4-2systick.h文件 1 //Filename:systick.h 2 3 #ifndef_SYSTICK_H 4 #define_SYSTICK_H 5 6 voidSysTickInit(void);

7 8 #endif

文件systick.h中给出了文件systick.c中定义的函数SysTickInit的声明,这样包括了systick.h文件的程序文件可以任意使用SysTickInit函数。本书中,除了main.c、includes.h和datatype.h文件外,其余的任一个.c文件都有同名的.h文件存在,在.c文件中定义实现特定功能的函数或任务,在与其同名的.h文件中包含.c文件中定义的函数的声明。4.1 LPC824异常管理

程序段4-3main.c文件 1 //Filename:main.c 2 3 #include"includes.h" 4 5 intmain(void) 6 { 7 BSPInit();

8 9 while(1) 10 { 11 } 12 }

与程序段3-1相比,这里的while无限循环体为空,main函数的主要作用在于第7行,即调用BSPInit函数初始化LPC824学习板外设,这里实现了对控制LED灯D9的PIO0_4口和SysTick定时器的初始化。4.1 LPC824异常管理

程序段4-4includes.h文件 1 //Filename:includes.h 2 3 #include"LPC82x.h" 4 5 #include"datatype.h" 6 #include"bsp.h" 7 #include"led.h" 8 #include"systick.h"

与程序段3-2相比,这里添加了第8行,即包括了头文件systick.h。

程序段4-5bsp.c文件

1 //Filename:bsp.c 2 3 #include"includes.h" 4 5 voidBSPInit(void) 6 { 7 LEDInit();

8 SysTickInit();

9 }4.1 LPC824异常管理 与程序段3-6相比,这里添加了第8行,即调用SysTickInit函数初始化SysTick定时器。第5~9行的BSPInit函数为LPC824学习板的外设初始化函数,后续工程中的外设初始化函数将被添加到该函数中。 将systick.c文件添加到工程LPC824PRJ管理器的BSP分组下,完成后的项目ZLX02如图4-2所示。图4-2 项目ZLX02工作界面4.1 LPC824异常管理 在图4-2中,编译链接项目ZLX02,完成后,点击“下载可执行代码到Flash”快捷钮,将可执行代码文件LPC824PRJ.axf下载到LPC824片上Flash中,然后,按一下LPC824-学习板上的复位按键(图3-13中的S19),将观察到LPC824学习板上的LED灯D9每秒闪烁一次。 项目ZLX02实现的功能与ZLX01相同,但是,在ZLX01中,延时函数无法做到准确地延时1秒,并且延时函数占用了大量CPU时间,应该避免使用;而ZLX02中,使用SysTick定时器中断服务函数处理LED灯闪烁问题,能够保证LED灯的闪烁周期是准确的1秒,并且不占用CPU时间。4.1 LPC824异常管理 LPC824微控制器的NVIC中断如表2-6所示,中断号从0至31,共有32个,其中有效的中断为28个。每个NVIC中断对应着6个中断管理寄存器,如表27所示。NVIC中断的管理方法为:首先,初始化NVIC中断对应的片上外设,有时一个片上外设有多个中断源,但这些中断都通过该外设使用同一个NVIC中断;然后,开放片上外设对应的NVIC中断,清除该NVIC中断的中断请求标志,可以为NVIC中断设定优先级;最后,编写NVIC中断的中断响应函数,一般地,中断响应函数包括两部分,即清除NVIC中断请求标志(有时还需要清除片上外设寄存器中的中断请求标志)和用户功能。

本节以多速率定时器MRT中断为例介绍NVIC中断的管理方法。由表26和表4-1可知,MRT中断的中断号为10,中断服务函数名为MRT_IRQHandler。下面首先在4.2.1小节介绍MRT定时器的工作原理,然后,在4.2.2小节介绍MRT定时器中断管理方法。4.2 NVIC中断管理4.2.1 多速率定时器MRT LPC824的多速率定时器(MRT)是一个31位的减计数定时器,具有4个独立的减计数通道,相当于4个单独的定时器,支持重复定时、单拍定时和单拍延时等三种工作模式。所谓的重复定时工作模式是指定时器从给定的初值减计数到0后,产生定时中断,然后再自动装入初值,再次减计数到0产生定时中断,一直循环下去,类似于SysTick定时器的情况。单拍定时工作模式是指定时器从给定的初值减计数到0后,产生定时中断,然后定时器进入空闲态,不再循环工作,即这种情况下仅产生一次定时中断。单拍延时工作模式是指定时器从给定的初值减计数到0的过程中,LPC824停止全部CPU活动和所有中断,定时器减计数到0后,不产生定时器中断,而是恢复CPU活动。 多速率定时器(MRT)的4个定时器通道的结构相同,下面以通道0(MRT0)为例介绍其工作原理,如图4-3所示。图4-3 MRT定时器通道0(MRT0)工作原理4.2 NVIC中断管理 由图4-3可知,MRT0的参考时钟为系统时钟,31位减计数器的当前计数值保存在TIMER0寄存器中,计数的初值保存在INTVAL0寄存器中,当TIMER0减计数到0后,将产生定时中断,定时中断的标志同时保存在STAT0和IRQ_FLAG寄存器中。

MRT定时器共有18个寄存器,如表4-2所示。表4-2 MRT寄存器(基地址:0x40004000)4.2 NVIC中断管理 由于MRT定时器的四个通道结构相同,因此,各个通道的寄存器的结构与含义也相同,所以这里仅介绍MRT0通道的寄存器含义。

1)INTVAL0寄存器

INTVAL0寄存器结构如表4-3所示,其中,向IVALUE位域写入正整数,将启动MRT0定时器,如果系统时钟为30MHz,当定时间隔为1秒时,IVALUE需写入值30000000=0x01C9C380;同时将LOAD位的值置为1,即IVALUE1的值立即赋给MRT0的TIMER0寄存器。表4-3 INTVAL0寄存器各位的含义4.2 NVIC中断管理

2)TIMER0寄存器

TIMER0寄存器结构如表4-4所示,其中,VALUE位域保存了MRT0定时器的当前计数值,当MRT0空闲时,读该寄存器返回0x00FFFFFF。表4-4 TIMER0寄存器各位的含义

3)CTRL0寄存器

CTRL0寄存器结构如表4-5所示,其中,INTEN位为1,开放MRT0定时器中断;为0,则关闭MRT0定时器中断。MODE位域为0表示MRT0工作在重复定时工作模式下,在这种模式下,MRT0减计数到0后,产生定时中断,然后再自动从INTVAL0寄存器装入定时间隔初值,进入下一次定时中断,一直循环下去。MODE位域为1表示工作在单拍定时工作模式下,这时,MRT0从IVALUE1减计数到0后,产生定时中断,然后进入空闲态,即这种工作模式下仅触发一次MRT0定时器中断。MODE位域为2表示工作在单拍延时工作模式下,使CPU等待一个定时节拍。表4-5 CTRL0寄存器各位的含义4.2 NVIC中断管理 4)STAT0寄存器

STAT0寄存器结构如表4-6所示,其中INTFLAG为MRT0中断标志位,当MRT0减计数到0后,将产生定时中断,并将INTFLAG位置1,通过向该位写入1将其清零。表4-6 STAT0寄存器各位的含义

5)IDLE_CH寄存器

IDLE_CH寄存器结构如表4-7所示,其中只有CHAN位域有效,该位域保存了空闲的定时器中通道号最小的定时器的通道号,例如,如果MRT0空闲,不管MRT1~3是否空闲,则CHAN=0;如果MRT0工作,MRT1空闲,不管MRT2~3是否空闲,则CHAN=1;依次类推,如果MRT0~3均工作,则CHAN=4,表示无空闲的定时器。表4-7 IDLE_CH寄存器各位的含义4.2 NVIC中断管理 6)IRQ_FLAG寄存器

IRQ_FLAG寄存器结构如表4-8所示,该寄存器将MRT0~3的中断标志位组合在一起。表4-8 IRQ_FLAG寄存器各位的含义 根据上述对MRT工作原理和寄存器的解释,下面4.2.2小节使用MRT0定时器,使其工作在重复定时工作模式下,定时中断的间隔为1秒,实现LED灯D9每隔1秒闪烁的功能。4.2 NVIC中断管理4.2.2 MRT定时器中断实例 在项目ZLX01的基础上,新建项目ZLX03(保存目录D:\ZLXLPC824\ZLX03),此时的项目ZLX03与ZLX01完全相同,然后,添加mrt.c和mrt.h文件(这两个文件均保存到D:\ZLXLPC824\ZLX03\BSP目录下),并修改main.c、includes.h和bsp.c文件,其中,main.c与程序段4-3相同,其余文件如程序段4-6至程序段4-9所示,项目ZLX03实现的功能与ZLX01相同,即每1秒使LED灯D9闪烁一次,如图4-4所示。图4-4 项目ZLX03的流程框图4.2 NVIC中断管理

程序段4-6mrt.c文件

1 //Filename:mrt.c 2 3 #include"includes.h" 4 5 voidMRT_IRQEnable(void) 6 { 7 NVIC_ClearPendingIRQ(MRT_IRQn);

8 NVIC_EnableIRQ(MRT_IRQn);

9 } 10

上述函数MRT_IRQEnable中调用了两个CMSIS库函数,即第7行的NVIC_ClearPendingIRQ和第8行的NVIC_EnableIRQ,分别用于清除MRT定时器对应的NVIC中断标志位(通过向ICPR0寄存器的第10位写入1实现,见表2-7)和开放MRT对应的NVIC中断(通过向ISER0寄存器的第10位写入1实现,见表2-7)。4.2 NVIC中断管理 11 voidMRTInit(void) 12 { 13 LPC_SYSCON->SYSAHBCLKCTRL|=(1uL<<10);//EnableMRTClockSource 14 LPC_SYSCON->PRESETCTRL&=~(1uL<<7);

15 LPC_SYSCON->PRESETCTRL|=(1uL<<7);//ResetMRT 16 17 LPC_MRT->CTRL0=(1uL<<0);//OpenMRT0Interrupt 18 LPC_MRT->INTVAL0=(30000000uL<<0)|(1uL<<31);

19 20 MRT_IRQEnable();

21 } 22

第11~21行的MRTInit函数为MRT0定时器初始化函数。第13行使MRT定时器的时钟源有效(见表2-18),第14、15行复位MRT定时器(见表2-14),第17行开放MRT0定时中断(见表4-5),第18行设定MRT0定时初值为30000000,并启动MRT0定时器,第20行调用MRT_IRQEnable函数开放MRT对应的NVIC中断。这里的LPC_SYSCON和LPC_MRT结构体指针定义在LPC82X.h文件中,分别表示LPC824片上SY-SCON模块和MRT模块的寄存器组指针,借助于它们可以直接访问这些模块的寄存器。4.2 NVIC中断管理 23 voidMRT_IRQHandler(void) 24 { 25 NVIC_ClearPendingIRQ(MRT_IRQn);

26 if((LPC_MRT->STAT0&0x01)==0x01) 27 { 28 LPC_MRT->STAT0|=(1uL<<0);

29 LEDBlink();

30 } 31 }

第23~31行的MRT_IRQHandler为MRT定时器对应的NVIC中断服务函数,函数名必须为MRT_IRQHandler(见表4-1)。第25行清除MRT定时器对应的NVIC中断请求标志位,第26行判断MRT定时器中断是否由MRT0定时器产生,即STAT0的第0位是否为1,如果为1,表示MRT0定时器产生了中断,则第28行清除MRT0定时中断在寄存器STAT0中的标志位,第29行调用LEDBlink使LED灯D9闪烁一次。4.2 NVIC中断管理

程序段4-7mrt.h文件

1 //Filename:mrt.h 2 3 #ifndef_MRT_H 4 #define_MRT_H 5 6 voidMRTInit(void);

7 8 #endif

文件mrt.h中包含mrt.c文件中定义的函数MRTInit的声明。文件mrt.c中有三个函数(见程序段4-6),其中,MRT_IRQEnable为mrt.c内部使用的函数,而MRT_IRQHandler为中断服务函数,这两个函数均不会被其他文件使用,所以,不需要在mrt.h中声明它们。4.2 NVIC中断管理

程序段4-8includes.h文件

1 //Filename:includes.h 2 3 #include"LPC82x.h" 4 5 #include"datatype.h" 6 #include"bsp.h" 7 #include"led.h" 8 #include"mrt.h"

对比程序段3-2,这里多了第8行,即包括了头文件mrt.h。

程序段4-9bsp.c文件

1 //Filename:bsp.c 2 3 #include"includes.h" 4 5 voidBSPInit(void) 6 { 7 LEDInit();

8 MRTInit();

9 }

对比程序段3-6,这里多了第8行,即添加了MRT初始化函数MRTInit。4.2 NVIC中断管理 将mrt.c添加到工程LPC824PRJ管理器的BSP分组下,完成后的项目ZLX03如图4-5所示。 在图4-5中,编译连接并运行项目ZLX03,可观察到LPC824学习板上的LED灯D9每隔1秒闪烁一次,而且,LED灯的闪烁周期是准确的1秒。图4-5 项目ZLX03工作界面

4.2 NVIC中断管理4.3.1 外部中断与模式匹配工作原理 LPC824最多支持8个外部中断,可以从PIO0口的16个I/O口中任选其中的8个管脚作为外部中断输入口,外部中断的触发有电平触发和边沿触发等方式,通过模式匹配引擎,还可组合这些输入信号的状态匹配复杂的布尔表达式。但是,选出的8个管脚如果用作外部中断,则不能用于模式匹配;同样地,若用于模式匹配,则不能用作外部中断输入脚。 借助于寄存器PINTSEL0~PINTSEL7(见表2-12第34~41号)从PIO0中任意选择8个I/O口用作外部中断或模式匹配输入端口。PINTSEL0~PINTSEL7寄存器均只有第[5:0]位有效,用符号INTPIN表示,INTPIN的取值为0~23,对应着PIO0_0~PIO0_23(对于LPC824,只有PIO0_0~PIO0_5、PIO0_8~PIO0_15、PIO0_17和PIO0_23有效)。例如,将PIO0_17作为外部中断6号输入,即PININT6,只需借助语句“PINTSEL6=(17μL<<0);”即可。LPC824最多支持8个外部中断输入,程序员可以仅使用其中的一个或几个中断。如果用PINTSEL0~PINTSEL7寄存器选出的某个I/O口用作外部中断,则全部选出的I/O口都只能工作在外部中断模式下;同理,如果选出的某个I/O口用于模式匹配输入口,则全部选出的I/O口都只能工作在模式匹配下,不能再作为外部中断输入口。如果选出的外部输入用于唤醒LPC824,则仅能工作在外部中断工作模式下。4.3 LPC824外部中断 外部中断的工作原理如图4-6所示。图4-6 外部中断工作原理 由图4-6可知,PINTSELn为NVIC外部中断n选择输入管脚,这里n=0~7。例如,用PINTSEL6为NVIC外部中断6选择输入管脚,参考表2-6,可知外部中断6(即PININT6_IRQ)中断号为30,根据表4-1可知,PININT6_IRQ中断的中断服务函数名为PIN_INT6_IRQHandler。4.3 LPC824外部中断 外部输入触发中断的条件有两种方式,即电平触发和边沿触发。其中,电平触发又包括高电平触发和低电平触发。而边沿触发又包括上升沿触发、下降沿触发和双边沿触发等方式。

LPC824模式匹配的工作原理如图4-7所示。图4-7 LPC824模式匹配工作原理

4.3 LPC824外部中断 由图4-7可知,LPC824模式匹配引擎由8个片(或称“位片”)组成,即第0片~第7片,由PINTSEL0~PINTSEL7寄存器选出的外部输入管脚分别记为IN0~IN7,IN0~IN7被送往所有的片,每片内部都有一个“多选一”选择器,由寄存器PMSCR控制,每片只能从IN0~IN7中选出一个输入,多个片可以选择相同的输入,例如,第0片和第1片都可以选IN5。然后,每个片选出的输入被送到“检测逻辑”单元,可以设置无记忆的边沿或电平匹配方式或带记忆功能的边沿匹配方式,匹配成功后,输出高电平。每个片都有一个“输出有效端”,用于控制该片是否送出中断控制信号,由寄存器PMCFG管理,第n片由PMCFG寄存器的第n位管理,当该位为1时,则送出中断信号;否则,不送出中断信号。这里的“输出有效端”在文献[3]中用“endpoint”表示。 从图4-7还可以看出,LPC824的模式匹配引擎的各个片是级联在一起的,每个片可以影响它的下一片,或受它的上一片的影响。如果第n片“输出有效端”关闭了,并且该片没有达到匹配条件,那么第n+1片被关闭。如果第n片“输出有效端”有效,那么第n+1片可以单独使用。通过这种方式,每个片扮演着数字逻辑中的“乘积项”的角色。

LPC824在模式匹配情况下,如果某个模式匹配成功,可以向LPC824内核发送一个RXEV通知,该信号(GPIO_INT_BMAT)可以通过开关矩阵寄存器连接到一个外部管脚上(参考表2-3的PINASSIGN11寄存器)。4.3 LPC824外部中断 下面将首先介绍LPC824外部中断和模式匹配相关的寄存器,然后,再回到图4-7进一步阐述模式匹配的工作原理。LPC824外部中断与模式匹配相关的寄存器有13个,如表4-9所示。表4-9 LPC824外部中断与模式匹配引擎寄存器(基地址为0xA0004000)4.3 LPC824外部中断 表4-9中各个寄存器的具体含义如下所示: 1)管脚中断模式寄存器ISEL ISEL寄存器只有第[7:0]位有效,用符号PMODE表示,如果第n位为0,表示外部中断n工作在边沿触发中断模式下;如果第n位为1,表示外部中断n工作在电平触发模式下,这里n=0~7,如表4-10所示。

2)管脚电平或上升沿中断有效寄存器IENR IENR寄存器只有第[7:0]位有效,用符号ENRL表示。如果第n位为0,表示关闭上升沿或电平触发外部中断n,如表4-11所示。如果第n位为1,表示开放上升沿或电平触发外部中断n,这时,如果ISEL寄存器的第n位为0,则上升沿触发外部中断n;如果ISEL寄存器的第n位为1,则进一步根据IENF寄存器的第n位决定电平触发中断的方式:如果IENF的第n位为0,则低电平触发外部中断n;如果IENF的第n位为1,则高电平触发外部中断n。表4-10 ISEL寄存器各位的含义表4-11请看下页

4.3 LPC824外部中断表4-11 IENR寄存器各位的含义

3)管脚电平或上升沿中断设置寄存器SIENR

只写的SIENR寄存器只有第[7:0]位有效,向其第n位写入1,则置位IENR寄存器的第n位,写入0无效,这里,n=0~7,如表4-12所示。这样,设置IENR寄存器的第6位为1,可以通过下述两种方式: IENR|=(1uL<<6);// “读出—取或—回写”方式或者

SIENR=(1uL<<6);// “不读只写”方式显然,后者更快速方便。表4-12 SIENR寄存器各位的含义4.3 LPC824外部中断

4)管脚电平或上升沿中断清除寄存器CIENR CIENR寄存器各位的含义如表4-13所示。 只写的CIENR寄存器只有第[7:0]位有效,在其第n位写入1,则清零IENR寄存器的第n位,写入0无效。这里,n=0~7。这样,清零IENR寄存器的第6位,可以有下述两种方式: IENR&=~(1uL<<6); //“读出—取与—回写”方式或者

CIENR=(1uL<<6); //“不读只写”方式显然,后者更快速方便。表4-13 CIENR寄存器各位的含义4.3 LPC824外部中断

5)管脚活跃电平或下降沿中断有效寄存器IENF IENF寄存器只有第[7:0]位有效,如表4-14所示,当第n位为0时,如果ISEL的第n位为0,则关闭下降沿触发外部中断n模式;如果ISEL的第n位为1,则设置低电平触发外部中断n模式。当IENF的第n位为1时,如果ISEL的第n位为0,则开放下降沿触发外部中断n模式;如果ISEL的第n位为1,则设置高电平触发外部中断n模式。表4-14 IENF寄存器各位的含义4.3 LPC824外部中断

6)管脚活跃电平或下降沿中断设置寄存器SIENF

只写的SIENF寄存器只有第[7:0]位有效,如表4-15所示,向其第n位写入0无效;向第n位写入1则置位IENF寄存器的第n位。因此,置位IENF寄存器第n位的方式有两种,即

IENF|=(1uL<<n); //“读出—取或—写回”方式或者

SIENF=(1uL<<n); //“不读只写”方式显然,后者更快速方便。表4-15 SIENF寄存器各位的含义4.3 LPC824外部中断

7)管脚活跃电平或下降沿中断清除寄存器CIENF

只写的CIENF寄存器只有第[7:0]位有效,如表4-16所示,向其第n位写入0无效;向第n位写入1则清零IENF寄存器的第n位。因此,清零IENF寄存器第n位的方式有两种,即

IENF&=~(1uL<<n); //“读出—取与—写回”方式或者

CIENF=(1uL<<n); //“不读只写”方式显然,后者更快速方便。表4-16 CIENF寄存器各位的含义4.3 LPC824外部中断

8)管脚中断上升沿寄存器RISE

管脚中断上升沿寄存器RISE即上升沿中断标志寄存器,只有第[7:0]位有效,如表4-17所示,第n位对应着外部中断n,n=0~7。当外部中断n出现上升沿时,无论该中断是否有效,RISE寄存器的第n位都将被置1,如果外部中断n有效,则将发出外部中断n请求。向RISE寄存器第n位写入1清零该寄存器第n位(即“写1清0”)。表4-17 RISE寄存器各位的含义

9)管脚中断下降沿寄存器FALL

管脚中断下降沿寄存器FALL,即下降沿中断标志寄存器,只有第[7:0]位有效,如表4-18所示,第n位对应着外部中断n,n=0~7。当外部中断n出现下降沿时,无论该中断是否使能,FALL寄存器的第n位都将被置1,如果外部中断n有效,则将发出外部中断n请求。向FALL寄存器第n位写入1清零该寄存器第n位(即“写1清0”)。表4-18 FALL寄存器各位的含义4.3 LPC824外部中断

10)管脚中断状态寄存器IST IST只有第[7:0]位有效,如表4-19所示,第n位对应着外部中断n,当外部中断n被触发后,IST的第n位自动置1,通过向其写入1清零该位,写入0无效。在电平触发外部中断n模式下,写入1清零IST的第n位,同时还将使得IENF寄存器的第n位取反,如果原来是低电平触发中断,则会转变为高电平触发中断;如果原来是高电平触发中断,则会转变为低电平触发中断。表4-19 IST寄存器各位的含义4.3 LPC824外部中断

11)匹配模式中断控制寄存器PMCTRL PMCTRL寄存器的第0位为0表示PINTSEL0~PINTSEL7选出的8个通用I/O口工作在外部中断输入模式下;第0位为1表示选出的8个通用I/O口工作在模式匹配下。PMCTRL寄存器的第1位为1时,表示当某个片发生匹配成功时向ARM内核发送RXEV信号;为0时,关闭RXEV信号。PMCTRL寄存器的第[31:24]位为PMAT位域,每位对应着一片寄存器(第24位对应片0,第25位对应片1,依次类推,第31位对应片7),如果该片匹配成功,则相应的位置1。PMCTRL寄存器如表4-20所示。表4-20 PMCTRL寄存器各位的含义4.3 LPC824外部中断

12)匹配模式中断位片源寄存器PMSRC

向PMSRC寄存器写入配置字前,需要先将PMCTRL寄存器的第0位清0,即关闭模式匹配引擎,然后写入PMSRC配置字,之后,置位PMCTRL寄存器的第0位,打开模式匹配引擎。PMSRC寄存器各位的含义如表4-21所示,其中,SRCn用于为片n选择外部输入管脚,n=0~7。表4-21 PMSRC寄存器各位的含义4.3 LPC824外部中断

13)匹配模式中断位片配置寄存器PMCFG

向PMCFG寄存器写入配置字前,需要先将PMCTRL寄存器的第0位清0,即关闭模式匹配引擎,然后写入PMCFG配置字,之后,置位PMCTRL寄存器的第0位,打开模式匹配引擎。PMCFG寄存器各位的含义如表4-22所示。表4-22中将要提到的“发生匹配事件时触发外部中断”的意思是指,当片n的输入与其设定的匹配逻辑相符合时,将会产生外部中断n,这里的“外部中断n”不是工作在外部中断模式下的外部中断n,两者产生的机理不同,但是两者的中断号相同,中断服务函数名都是PININTn_IRQHandler。表4-22中将要提到的“乘积项”是指多个片可以通过“与”操作联合起来实现复杂的逻辑表达式(或称布尔表达式),每个片的逻辑在这个表达式中扮演了“乘积项”的角色。表4-22 PMCFG寄存器各位的含义4.3 LPC824外部中断4.3 LPC824外部中断4.3 LPC824外部中断 由表4-10至表4-15可知,当工作在外部中断模式下时,通过设置这些表中的寄存器可设定中断触发的条件,如表4-23所示。表4-23中断触发条件相关的寄存器 例如,设置外部中断6为下降沿触发中断,参考表4-10至表4-16,可知其语句如下: ISEL&=~(1uL<<6); //PINTSEL6选择的管脚(即外部中断6)为边沿触发

CIENR=(1uL<<6); //关闭外部中断6上升沿触发

SIENF=(1uL<<6); //开启外部中断6下降沿触发4.3 LPC824外部中断 现在,回到图4-7,讨论LPC824工作在模式匹配下实现复杂逻辑表达式的方法。例如,要实现的逻辑表达式为:IN1+IN1*IN2+(~IN2)*(~IN3)*(IN6fe)+(IN5*IN7ev)。这里“*”号表示“与”,“+”号表示“或”,“~”号表示取反,“fe”表示有记忆的下降沿(fallingedge),“ev”表示无记忆的上升或下降沿匹配事件。该表达式选自文献[3],其含义为:如果IN1为高,或者IN1和IN2均为高,或者IN2与IN3均为低且IN6出现有记忆的下降沿匹配,或者IN5\为高且IN7出现无记忆的上升沿或下降沿匹配时,则表达式的输出为高。

下面介绍其设计过程: (1)由于逻辑表达式中出现了有记忆的匹配IN6fe,所以需要向PMCFG寄存器写入值,清除各片的记忆。

(2)通过设置PMCFG寄存器,使片0选IN1,片1选IN1,片2选IN2,片3选IN2,片4选IN3,片5选IN6,片6选IN5,片7选IN7。

(3)设置PMCFG寄存器,使得片0、片1和片2均为高电平匹配,参考表4-22,CFG0、CFG1和CFG2均设为4;片3和片4设为低电平匹配,即CFG3和CFG4均设为5;片5设为带记忆的下降沿匹配,即CFG5设为2;片6设为高电平匹配,即CFG6设为4;片7设为无记忆的上升沿或下降沿匹配,即CFG7设为7。然后,将片0、片2、片5和片7设为乘积项输出端,即PROD_ENDPTS0、PROD_ENDPTS2和PROD_ENDPTS5为1,片7始终为乘积项输出端。

4.3 LPC824外部中断 (4)设置PMCTRL寄存器,使得片0、片2、片5和片7的匹配将分别触发外部中断0、外部中断2、外部中断5和外部中断7。 通过上述配置,如果外部中断0、2、5或7中的任一个被请求了,说明前述的逻辑表达式为真。4.3 LPC824外部中断4.3.2 LPC824外部中断实例 结合图3-6和图3-4,下面的实例实现的功能为:当用户按下按键S18(见图36)时,LPC824学习板的LED灯D9(见图34)状态切换,即原来是点亮的,则熄灭;原来是熄灭的,则点亮。 在项目ZLX01的基础上,新建项目ZLX04,保存在目录D:\ZLXLPC824\ZLX04下,此时的项目ZLX04与项目ZLX01完全相同。然后,添加文件iokey.c和iokey.h,这两个文件保存到目录D:\ZLXLPC824\ZLX04\BSP下,并将iokey.c文件添加到工程LPC824PRJ管理器的“BSP”分组下。接着,修改文件main.c、includes.h和bsp.c。最后,完成的项目ZLX04工作界面如图4-8所示,项目ZLX04的执行流程如图4-9所示。 项目ZLX04中,main.c文件与程序段4-3相同,新添加的文件iokey.c和iokey.h以及修改的文件includes.h和bsp.c分别如程序段4-10至程序段4-13所示。图4-8、4-9请看下页4.3 LPC824外部中断

图4-8 项目ZLX04工作界面

图4-9 项目ZLX09执行流程框图4.3 LPC824外部中断

程序段4-10iokey.c文件

1 //Filename:iokey.c 2 3 #include"includes.h" 4 5 voidGPIOIntEnable(void) 6 { 7 NVIC_ClearPendingIRQ(PIN_INT6_IRQn);

8 NVIC_EnableIRQ(PIN_INT6_IRQn);

9 } 10

第5~9行的GPIOIntEnable函数用于清除外部中断6的NVIC中断标志并开放外部中断6。第7~8行调用了CMSIS库中的中断管理函数,这些中断管理函数位于core_cm0plus.h文件中,常用的函数如表4-24所示。表4-24请看下页4.3 LPC824外部中断表4-24 常用中断管理函数4.3 LPC824外部中断 表4-24中IRQn_Type是LPC82x.h中自定义的枚举变量定型。由LPC82x.h中可查得外部中断6的枚举常量为PIN_INT6_IRQn,如果只知道外部中断6的中断号为30,可以将第7~8行写作:“NVIC_ClearPendingIRQ((IRQn_Type)30uL);NVIC_EnableIRQ((IRQn_Type)30uL);”,这样不需要从LPC82x.h文件中查找各个NVIC中断的枚举常量值。注意,表4-24中,序号6对应的函数NVIC_SetPriority中的priority参数只能取值为0、1、2和3,这是因为LPC824中NVIC中断仅有4级优先级,且优先级号越小,优先级别越高。

11 voidIOKeyInit(void) 12 { 13 LPC_IOCON->PIO0_0=(3uL<<3); //PIO0_0Repeatmode 14 LPC_GPIO_PORT->DIRCLR0=(1uL<<0); //PIO0_0AsInput 15 16 LPC_PIN_INT->ISEL&=~(1uL<<6); //PININT6Edge 17 LPC_PIN_INT->CIENR=(1uL<<6); //PININT6Falling 18 LPC_PIN_INT->SIENF=(1uL<<6);

19 20 LPC_SYSCON->PINTSEL6=(0uL<<0); //PIO0_0AsPININT6 21 LPC_SYSCON->SYSAHBCLKCTRL|=(1uL<<6);//EnableGPIOClock 22 23 GPIOIntEnable();

24 } 254.3 LPC824外部中断 第11~24行的IOKeyInit函数用于初始化PIO0_0端口,使其作为外部中断6输入口。第13~14行将PIO0_0设为输入口,且工作在上拉电阻和下拉电阻都有效的模式下,此时,输入高电平时,上拉电阻有效;输入低电平时,下拉电阻有效。第16~18行将外部中断6设置为下降沿触发。第20行将PIO0_0用作外部中断6输入口,第21行给GPIO口模块提供工作时钟(见表2-18)。 26 voidPIN_INT6_IRQHandler(void) 27 { 28 NVIC_ClearPendingIRQ(PIN_INT6_IRQn);

29 30 LPC_PIN_INT->FALL=(1uL<<6);

31 32 LEDBlink();

33 } 第26~33行的函数为外部中断6的中断服务函数,函数名必须为PIN_INT6_IRQHandler(见表4-1)。第28行清除外部中断6的NVIC中断请求标志,第30行清除外部中断6的FALL寄存器中的中断请求标志,第32行调用LEDBlink函数使LED灯D9切换工作状态。4.3 LPC824外部中断

程序段4-11iokey.h文件

1 //Filename:iokey.h 2 3 #ifndef_IOKEY_H 4 #define_IOKEY_H 5 6 voidIOKeyInit(void);

7 8 #endif

文件iokey.h中给出了iokey.c文件中的函数声明,文件iokey.c中有三个函数,由于只有IOKeyInit函数会被外部文件使用,所以,文件iokey.h中仅给出了IOKeyInit函数的声明。

程序段4-12includes.h文件

1 //Filename:includes.h 2 3 #include"LPC82x.h" 4 5 #include"datatype.h" 6 #include"bsp.h" 7 #include"led.h" 8 #include"iokey.h"

对比程序3-2,这里的includes.h文件中添加了第8行,即包括了头文件iokey.h。4.3 LPC824外部中断

程序段4-13bsp.c文件

1 //Filename:bsp.c 2 3 #include"includes.h" 4 5 voidBSPInit(void) 6 { 7 LEDInit();

8 IOKeyInit();

9 } 对比程序段3-6,这里的bsp.c文件添加了第8行,即调用了IOKeyInit函数初始化PIO0_0端口,使其作为外部中断6的输入端口,并且开放外部中断6。

在图4-8的基础上,编译链接并运行项目ZLX04,当按下LPC824学习板上的S18按键时,可以看到LED灯D9切换状态,每按下S18按键一次,LED灯D9就切换一次状态。4.3 LPC824外部中断4.3.3 LPC824模式匹配实例 LPC824模式匹配引擎支持具有8个最小项的复杂逻辑关系式,这里结合LPC824学习板,实现一种简单的逻辑关系式,即(~IN6)*IN6ev,IN6ev表示IN6输入的匹配条件为无记忆的上升沿或下降沿,所以(~IN6)*IN6ev表示IN6出现下降沿且IN6为低电平时,(~IN6)*IN6ev为真,实际上就是用这种模式匹配表达式模拟IN6输入端出现下降沿事件。 对于逻辑关系式(~IN6)*IN6ev,根据图4

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论