软中断在51单片机中的实现及其应用(2)

2019-05-18 21:03

D触发起 中断申请 CLR# (74HC74) Q INT0# CPU (51兼容单片机) P1.0 SET#

图1 边沿触发中断申请改为低电平触发中断申请

INT0# CPU (51兼容单片机) P1.0 中断申请 CLK D D触发起 (74HC74) Q SET#

图2低电平触发中断申请改为CPU撤销信号的低电平触发中断申请

6、软中断在实时操作系统环境下的应用

在基于51单片机的嵌入式系统中,数据采集处理、程序控制和数据通讯是三个主要的应用方面,以下三小节分别描述数据采集处理任务、程序控制任务和数据通讯任务中软中断的使用,以帮助读者加深对软中断的理解。

6.1软中断服务在数据采集处理任务中的应用

实时操作系统下,中断处理占用的时间越短,系统的实时性越好。在一些应用中,数据处理的实时性要求很高,系统的响应时间在0.5毫秒以内。如果数据处理的时间在最坏情况下超过0.3毫秒,系统的软件设计就受到挑战。如果将数据处理全部放入中断中进行处理,系统中其它任务的实时性会受到严重影响。解决的办法通常是以下两种:1)不使用51单片机,改用其它处理速度更快的处理器(如ARM处理器);2)不使用操作系统。这两种解决办法要受到产品成本和开发效率的约束。

软中断的应用可以成为上述问题的第3种解决方法,并且是最优的解决方法。 使用一个最低优先级的中断源来实现软中断,将数据处理放入软中断中完成。这样,软中断就可以随时剥夺任何一个正在运行的任务而优先执行,执行完成后可以回到正在执行的任务,也可以切换到已就绪的更高优先级的任务。如此,系统的实时性就提高了,同时,软件开发效率也提高了。具体的办法是,在数据采集中断中,只完成数据的获取,将数据存放到队列中,然后申请软中断服务后退

出中断服务程序。只要系统中没有其它中断事务等待处理,软中断就可以开始处理,并且在软中断处理过程中可以响应其它的硬件中断,从而保证系统的实时性。由于软中断总是优先于任务执行,所以能够保证数据处理的实时性。当队列中没有数据时,软中断退出,执行其它任务。在这样的机制下,没有频繁的上下文切换,因此CPU的使用效率得到提高,以保证整个系统的实时性。

以下代码片断是一种车辆检测器的代码,使用了软中断来处理数据。可以看出,找外部中断0中将数据放入队列,然后申请软中断。在软中断中,只要队列中还有数据,就循环处理直到队列为空才退出软中断。

?? void int0_int(void) interrupt IE0_VECTOR {//外部中断0 TR0 = 0; //读计数器 NewNode = QMalloc();//申请分配内存 if(NewNode < Q_MAX_LEN) {//内存分配成功 LoopQ[NewNode].LoopChannel = LoopCounter; // TH2,TH1,TH0,TL7,TL6,TL5,TL4,TL3,TL2,TL1,TL0,P2.7,P2.6,P2.5,P2.4,P2.3 // 读取21位计数值拼成2字节,组成16位计数值 LoopQ[NewNode].LoopNv = ((TH0 & 0x03) * 8192) + (TL0 * 32) + ((P2>>3) & 0x1F); LoopQ[NewNode].TimeStamp = 0;//没有测速,不需要时间戳 AddLoopNode(NewNode); SWI_IRQ();//申请软件中断,以便处理数据 } LoopSet();//计算并设置下一个通道 LoopProcTimer = 0; } ?? //软中断服务函数 void SWI_ISR(void) interrupt SWI_NUM {// while(1) { ProcNode = GetLoopNode();//从队列中取待处理的数据 if(ProcNode == 0xFF) break;//队列中没有数据,退出 lopcout = LoopQ[ProcNode].LoopChannel;//取通道号 nv[lopcout] = LoopQ[ProcNode].LoopNv;//取测量数据 QFree(ProcNode);//释放内存以便循环使用 LoopProc();//通道计算 } CLEAR_SWI();//清除可能需要清除的标志 }

6.2 软中断在程序控制任务中的应用

在操作系统中的程序控制任务,其运行受系统内核支配。如果程序控制任务

在逻辑上有严格的时间安排,很可能被高优先级任务剥夺运行而导致逻辑失败。 这种任务如果全部安排在中断中完成处理,会影响系统中其它任务的实时性。这时比较好的方法就是利用软中断来处理时间要求很严格部分。通过软中断,申请在指定时刻执行指定的代码。

以下的代码是程序控制任务计算出来的控制序列,通过申请软中断服务,将待执行的程序控制交给系统,系统在定时器的严格同步下,将非常准确地完成控制过程。代码中,35毫秒后,功能1和功能4将“同时”启动执行,实际上功能1先于功能4执行,时间上相差大约10uS左右。

?? SWI_REQ(20,func1,data1);//申请20ms后执行功能1,其所需的参数在data1 SWI_REQ(25,func2,data2);//申请25ms后执行功能2,其所需的参数在data2 SWI_REQ(26,func3,data3);//申请26ms后执行功能3,其所需的参数在data3 SWI_REQ(35,func1,data4);//申请35ms后执行功能1,其所需的参数在data4 SWI_REQ(35,func4,data5);//申请35ms后执行功能4,其所需的参数在data5 SWI_REQ(36,func3,data6);//申请36ms后执行功能3,其所需的参数在data6 ??

6.3 软中断在数据通讯任务中的应用

在数据通讯中,有些通讯协议对系统的响应时间有严格的要求,两个数据包之间的空闲时间有严格的限制,超过一定时间就认为超时。

这种情况下,数据通讯任务如果全部安排在中断中完成处理,则会影响系统其它任务的实时性,如果放在任务中运行,运行的时间又不可控制。当然可以在任务中关闭中断来处理实时性要求较强的代码,可是这样做会影响其他部分的实时性。

比较好的方法,就是利用软中断,将需要提供的实时服务通过软中断申请将目标代码和数据在不影响系统实时性的条件下优先执行。

首先,在系统中建立一个软中断函数执行的链表,将等待执行代码入口地址和数据入口地址放在这个链表中。一旦内核运行完毕,就自动来检测这个链表中是否存在待执行的软中断代码。如果有软中断代码,立即按照优先顺序执行。当所有的软中断代码执行完成后,就检查是否有高优先级的任务已经就绪等待执行,若有,进行任务调度。当然,申请软中断服务本身就可能引发任务调度。这得看软中断服务完成后,是否有更高优先级任务进入就绪态。

比如,有一个任务在发送完成一个数据包后,有严格的时间要求在20ms后准确启动第二个数据包的发送。如果利用OSWait()或OSTimeDly()的方式,则完全不可能在20ms后准确开始。如果关闭中断等待20ms,系统的效率将十分低下。用软中断的方法是,向系统申请一个软中断服务,将服务要求的启动时刻、提供服务函数入口地址以及数据的存储地址提供给系统,就可以在指定的时刻运行这段代码,完成数据的发送工作。即使当前任务在申请完软中断服务后被剥夺,也能保证指定的数据在20ms后发送出去。

软中断函数执行链表的结构:

typedef struct Swi_List _MALLOC_MEM_ * SwiNode; typedef struct Swi_List{ unsigned int TimeDelay;//延迟多少时间开始执行,等于0表示立即执行 void (*Func)(unsigned char * pInOut);//执行的函数入口地址 unsigned char * pInOut;//执行函数的数据输入输出地址 SwiNode NextNode;//下一个节点的地址 }; 这样的伪代码就是:

?? //准备第一个数据包 Send(Packet1);//发送第一个数据包 //准备第二个数据包 SWI_REQ(20,Send,Pachet2);//申请20ms后发送第二个数据包 ?? 7、无操作系统环境下软中断的应用

在没有操作系统软件环境中,如果要执行的事务比较简单也比较少,用轮询的方法调度各个模块就基本可以满足。然而当事务比较多或事务比较复杂时,实时性的协调就很难。在这种情况下,就可以利用软中断来简化各个模块之间的时间协调,可大大提高系统的实时性和可协调性。

在一个没有操作系统的51单片机应用系统中开发软件,软中断不仅可以用来帮助对临界段的管理,以实现硬件资源的互斥访问以及共享数据的互斥访问,还可以实现无阻塞等待。

还举6.3节的例子,一个模块在发送完成一个数据包后,有严格的时间要求在20ms后准确启动第二个数据包的发送。

用软中断在系统中申请一个20ms的延时定时器,定时器到时执行回调函数Send(),完成第二个数据包的发送。

这样的伪代码就是:

unsigned char Packet_Send(void) { ?? If(CanSend==0)return 1;//发送忙,返回1 If(IsPendInTimer(Send))return 2;//Send函数被挂起在定时器的服务列表中,第二个数据包还没有启动发送,返回2 ?? //准备第一个数据包 Send(Packet1,len1);//发送第一个数据包 //准备第二个数据包 SWI_REQ(20,Send,Pachet2,len2);//申请20ms后发送第二个数据包 return 0;//发送完成,返回0 } 下面一个例子,揭示软中断如何实现硬件资源的互斥访问。

大家都使用过I2C总线器件,比如实时时钟、温度传感器、EEPROM等等。不论单片机自带的硬件I2C控制器还是用软件模拟的I2C控制器,我们都必须保证对22

IC总线操作的完整性,避免多个模块之间同时争用IC总线。在实时操作系统环境下,这个很容易实现,但在没有实时操作系统来管理时,就需要设置信号量来帮助各个模块之间协调使用。我们都知道,I2C总线是低速总线,软件模拟中线控制器时将耗费很多CPU时间,并且一个模块必须完成访问后才能释放访问权限。在没有实时操作系统的软件环境中,CPU将不得不等待。为了提高CPU的利用率,在I2C总线的驱动程序中使用软中断,能够很好地协调各模块之间使用I2C总线访问不同的器件。

软中断服务执行指定的发送或接收函数,并将结果复制到指定的内存地址中,然后还可以执行指定的回调函数(如果有的话)。 由于软中断优于任何模块获得CPU运行,故模块之间提交的软中断独立于模块代码而完整运行(硬件中断不妨碍其正确执行)。由于收发的硬件操作仅在软中断中执行,自然实现了硬件资源的互斥访问。同时,软中断中对共享的变量操作也具有了原子性。参阅例程4所示代码片断。

//模块1: Void M1() { SWI(1,&MySwiNode1);//申请软中断 //退出该模块,软件中断执行完成后,实时时钟的数据自动保存在clock[]中 } //模块2: Void M2() { (省略) SWI(1,&MySwiNode2);//申请软中断 //退出该模块,软件中断执行完成后,温度数据自动保存在temp[]中 } void main(void) { ?? //运行模块1 M1(); //运行模块2 M2(); ?? } 8、结语

在51单片机中,利用硬件中断的中断向量,实现软中断是完全可行的,并且使用软中断能够优化应用软件的执行效率。


软中断在51单片机中的实现及其应用(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:在金融消费者权益保护领导小组会议上的讲话

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: