第5章 中断服务程序设计
- 格式:doc
- 大小:350.00 KB
- 文档页数:13
第5章MCS-51单片机的中断系统【例5-1】设允许外部中断0和串行口中断,禁止其它中断源的中断申请。
试根据假设条件设置IE的相应值。
解:⑴用位操作指令来编写如下程序段:SETB EX0 ;允许外部中断0中断SETB ES ;允许串行口中断CLR EX1 ;禁止外部中断1中断CLR ET0 ;禁止定时器/计数器T0中断CLR ET1 ;禁止定时器/计数器T1中断SETB EA ;CPU开中断⑵用字节操作指令来编写:MOV IE, #91H【例5-2】设置中断优先级控制寄存器IP的初始值,使得8031的2个外中断请求为高优先级,其它中断请求为低优先级。
解:⑴用位操作指令SETB PX0;2个外中断为高优先级SETB PX1CLR PS ;串行口、2个定时器为低优先级中断CLR PT0CLR PT1⑵用字节操作指令MOV IP,#05H【例5-3】假设允许外部中断0中断,并设定它为高级中断,其它中断源为低级中断,采用跳沿触发方式。
在主程序中可编写如下程序段:SETB E A ;EA位置“1”,CPU开中断SETB E X0 ;EX0位置“1”,允许外部中断0产生中断SETB P X0 ;PX0位置“1”,外部中断0为高级中断SETB I T0 ;IT0位置“1”,外部中断0为跳沿触发方式【例5-4】根据图5-9的中断服务程序流程,编写出中断服务程序。
假设现场保护只需要将PSW寄存器和累加器A的内容压人堆栈中保护起来。
解一个典型的中断服务程序如下:INT: CLR E A ;CPU关中断PUSH PSW ;现场保护PUSH ASETB E A ;CPU开中断中断处理程序段CLR E A ;CPU关中断POP A ;现场恢复POP PSWSETB E A ; CPU开中断RETI ;中断返回,恢复断点上述程序有几点需要说明的是:⑴本例的现场保护假设仅仅涉及到PSW和A的内容,如果还有其它的需要保护的内容,只需要在相应的位置再加几条PUSH和POP指令即可。
第5章中断服务程序设计中断服务程序(ISR)是嵌入式应用系统获取各种事件的基本手段,而“事件”是实时性问题的讨论基础和时间计算的起点。
ISR的设计质量直接影响到系统的实时性指标和操作系统的工作效率。
只要没有关中断,中断服务程序可以中断任何任务的运行,可将中断服务程序可成比最高优先级(0级)还高的“任务”。
5.1中断优先级安排原则中断源是系统及时获取异步事件的主要手段,其优先级安排原则如下:●紧迫性:触发中断的事件允许耽误的时间越短,设定的中断优先级就越高。
●关键性:触发中断的事件越关键(重要),设定的中断优先级就越高。
●频繁性:触发中断的事件发生越频繁,设定的中断优先级就越高。
●快捷性:ISR处理越快捷(耗时短),设定的中断优先级就越高。
中断服务程的功能应尽量简单,只要将获取的异步事件通信给关联任务,后续处理由关联任务完成。
5.2不受操作系统管理的中断服务程序正常情况下,ISR应受操作系统的管理,因很多任务是靠ISR触发的。
但在两种情况下ISR不受操作系统管理:①没有必要;②操作系统没有对该ISR进行管理。
实时操作系统uC/OS-Ⅱ移植到ARM7体系的CPU上时,没有对FIQ进行处理,即FIQ 是不受操作系统管理的。
选用FIQ来响应实时性要求最高的高速采样操作是一个有效措施,保护现场的工作量很小(FIQ专有的8个寄存器不需要保护)。
在工程模板的系统启动文件Startup.s中,已经把汇编代码部分处理好,用户只需要用C 语言编写快速中断服务函数FIQ_Exception()即可,不需考虑保护现场和恢复现场的问题。
程序:Startup.s中队FIQ的处理Reset ;异常向量表LDR PC,ResetAddr ;跳转到复位入口地址LDR PC,UndefinedAddrLDR PC,SWI_Addr ;跳转到软件中断入口地址LDR PC,PrefetchAddrLDR PC,DataAbortAddrDCD 0xb9205f80LDR PC,[PC,#-0xff0] ;跳转到向量中断入口地址(向量中断控制器)LDR PC,FIQ_Addr ;跳转到快速中断入口地址ResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortNouse DCD 0IRQ_Addr DCD 0FIQ_Addr DCD FIQ_Handler ;快速中断服务程序入口地址FIQ_Handler ;快速中断服务程序STMFD SP!,{R0-R3,LR} ;保护现场HL FIQ_Exception ;调用C语言编写的快速中断服务函数LDMFD SP!{R0-R3,LR} ;恢复现场SUBS PC,LR,#4 ;中断返回由于没有操作系统介入,FIQ的ISR无法与关联任务进行通信,所获取的信息不能及时得到关联任务的处理,故只能以原始形式保存在一个缓冲区内,等待以后进行离线处理。
典型的例子是高速数据采集系统。
由于使用FIQ方式进行采样,其ISR不受操作系统管理,所以只能用“使能中断源”和“关闭中断源”来控制采样过程。
这是需要设置一个采样任务来控制采样过程。
其代码结构如下程序。
程序:高速采样任务函数结构void TaskSamp(void *pdata) //高速采样任务函数{进行相关设置;while(1) //无限循环{等待启动信号’进行准备工作;使能采样中断;等待结束信号;停止采样中断;数据预处理;输出采样数据块;}}实验:将定时器1设置为FIQ,在FIQ中进行快速采样。
采样过程由采样任务进行控制,而采样任务本身由操作者通过按键进行控制,每次采样过程进行200次连续采样,采样周期为50us。
高速采样的程序流程图如图5-1所示,程序代码如下。
(a)按键任务(b)采样任务(c)FIQ图5-1 高速采样的程序流程图程序:高速采样示例#include “config.h”//文件config.h包含了includes.h和一些系统配置文件#define KEY (1<<20) //P0.20为按键控制I/0#define TaskStk 100 //定义任务堆栈长度OS_STK TaskKeyStk[TaskStk] //定义按键任务的堆栈OS_STK TaskSampStk[TaskStk]; //定义采样任务的堆栈void TaskKey(void *pdata); //声明按键任务,因为这段代码在创建它的主函数//后面void TaskSamp(void *pdata); //声明采样任务,因为这段代码在创建它的按键任务//函数的后面INT16U Samp[200]; //保存采样结果的数组INT8U count=0; //采样次数计数器void Show(INT16U *a,INT16U n) //显示波形函数{INT16U I;GUI_ClearSCR(); //清屏for(i=0;i<n;i++) //显示波形GUI_Point(i,240-a[i]*/300/3000,RED); //高度240点相当于3000mV}int main(void) //将main()函数设置为整型是为了防止编译警告{OSInit();OSTaskCreat(TaskKey,(void *)0,&TaskKeyStk[TaskStk-1],4); //创建按键任务OSStart();return 0;}void TaskKey(void *pdata) //按键任务{pdata=pdata;TargetInit(); //系统电路初始化GUI_Initalize(); //初始化LCD(液晶屏)PINSEL1=0x00400000; //设置P0.27连接到AINO//进行ADC模块设置,其中x<<n表示第n位设置为x(若x位超过一位,则向高位顺延)ADCR=(1<<0) | //SEL=1,选择通道0((Fpclk/1000000-1)<<8) | //即转换时钟为1Mhz(0<<16) | //BURST=0.软件控制转换操作(0<<17) | //CLKS=0,使用11clock转换(1<<21) | //PDN=1,正常工作模式(非掉电转换模式)(0<<22) | //TEST1:0=00,正常工作模式(非测试模式)(1<<24) | //START=1,直接启动ADC转换(0<<27) | //EDGE=0,引脚下降沿触发转换T1IR=0xffffffff; //复位中断源T1TC=0x00; //初始化定时器1T1PR=0x00; //设置定时器1的分频器(不分频)T1TCR=0x01; //使能定时器1T1MCR=0x03; //匹配时产生中断并复位定时器1T1MR0=Fpclk/20000; //定时时间为50usVICIntSelect=1<<5; //T1设置为快速中断while(1){OSTimeDly(2); //延时if((IO0PIN&KEY)!=0) continue; //未按键,再延时else //按下按键{while(IO0PIN&KEY) == 0) //等待按键释放{IO0SET=KEY;OSTimerDly(1); //延时}OSTaskCreate(TaskSamp,(void *)0,&TaskSamp[TaskStk-1],2); //创建采样任务}}}void TaskSamp(void *pdata) //高速采样任务{INT8U i; //临时变量INT32U Temp; //临时变量pdata=pdata;count=0; //初始化采样计数器VICIntEnable=1<<5; //打开定时器1的FIQ,开始采样while(1); //等待采样结束{OS_ENTER_CRITICAL(); //关中断i=count; //查询当前完成的采样次数OS_EXIT_CRITICAL(); //开中断if (i>=200) break; //完成预定采样次数,结束查询OSTimeDly(1); //未完成预定采样次数,延时一个时钟节拍继续//查询}for(i=0;i<200;i++) //将采样数据进行预处理,使数据以mV为单位{Temp=3000*Samp[i]; //参考电压为3000mVSamp[i]=(INT16U) (TEMP>>16);}Show(Samp,200); //显示采样信号的波形OSTaskDel(OS_PRIO_SELF); //删除自己}void FIQ_Exception(void) //快速中断服务函数{INT32U ADC_Data;T1IR=0x01; //清除中断源VICVectAddr=0; //通知中断控制器ADC_Data=ADDR; //通过读取ADC结果清除DONE标志位ADCR=(ADCR&0Xffffff00)|0x01|(1<<24); //切换通道并进行第一次转换while(ADDR&0x80000000)==0); //等待转换结束ADCR=ADCR|(1<<24); //再次启动转换while(ADDR&0x80000000)==0); //等待转换结束Samp[count]=(INT16U)(ADDR&0x0000FFFF); //读取并保存转换结果count++; //调整采样计数器if(count==200) VICIntEnClr=1<<5; //完成采样次数,关闭FIQ5.3 受操作系统管理的中断服务程序中断服务程序的结构受实时操作系统管理的ISR与不受实时操作系统管理的ISR有很大区别,体现在以下3个阶段。
①入中断:除了保护现场外,还需要调用“进入中断”服务函数。
②行功能代码:完成ISR的实质功能的代码外,还包含了对系统通信服务函数的调用,使关联任务得到同步信号或Ⅱ数据,从而进入就绪状态,但在ISR中不容许调用延时函数和可能被挂起系统服务函数。
③退出中断:执行“退出中断”流程。
必须将ISR中与具体功能无关的代码剥离出来,作为实时操作系统内核的一部分,提供给实时操作系统的用户。
实时操作系统uc/OS-Ⅱ移植到ARM7体系的CPU上时,这部分代码用一个汇编宏实现(移植文件IRQ.inc),并提供C语言接口,用户只需要用C语言编写ISR的功能代码即可。