软件“看门狗”技术
若失控的程序进入“死循环”,通常采用“看门狗”技术使程序脱离“死循环”。通过不断检测程序循环运行时间,若发现程序循环时间超过最大循环运行时间,则认为系统陷入“死循环”,需进行出错处理。
“看门狗”技术可由硬件实现,也可由软件实现。在工业应用中,严重的干扰有时会破坏中断方式控制字,关闭中断。则系统无法定时“喂狗”,硬件看门狗电路失效。而软件看门狗可有效地解决这类问题。
笔者在实际应用中,采用环形中断监视系统。用定时器T0监视定时器T1,用定时器T1监视主程序,主程序监视定时器T0。采用这种环形结构的软件“看门狗”具有良好的抗干扰性能,大大提高了系统可靠性。对于需经常使用T1定时器进行串口通讯的测控系统,则定时器T1不能进行中断,可改由串口中断进行监控(如果用的是MCS-52系列单片机,也可用T2代替T1进行监视)。这种软件“看门狗”监视原理是:在主程序、T0中断服务程序、T1中断服务程序中各设一运行观测变量,假设为MWatch、T0Watch 、T1Watch,主程序每循环一次,MWatch加1,同样T0、T1中断服务程序执行一次,T0Watch、 T1Watch加1。在T0中断服务程序中通过检测T1Watch的变化情况判定T1运行是否正常,在T1中断服务程序中检测MWatch的变化情况判定主程序是否正常运行,在主程序中通过检测T0Watch的变化情况判别T0是否正常工作。若检测到某观测变量变化不正常,比如应当加1而未加1,则转到出错处理程序作排除故障处理。当然,对主程序最大循环周期、定时器T0和T1定时周期应予以全盘合理考虑。限于篇幅不赘述。
硬件抗干扰技术
单片机系统因干扰复位或掉电后复位均属非正常复位,应进行故障诊断并能自动恢复非正常复位前的状态。
非正常复位的识别
程序的执行总是从0000H开始,导致程序从 0000H开始执行有四种可能:一、系统开机上电复位;二、软件故障复位;三、看门狗超时未喂狗硬件复位; 四、任务正在执行中掉电后来电复位。四种情况中除第一种情况外均属非正常复位,需加以识别。
(1 )硬件复位与软件复位的识别
此处硬件复位指开机复位与看门狗复位,硬件复位对寄存器有影响,如复位后PC=0000H, SP=07H,PSW=00H等。而软件复位则对SP、SPW无影响。故对于微机测控系统,当程序正常运行时,将SP设置地址大于07H,或者将PSW的第5位用户标志位在系统正常运行时设为1。那么系统复位时只需检测PSW.5标志位或SP值便可判此是否硬件复位。
由于硬件复位时片内RAM状态是随机的,而软件复位片内RAM则可保持复位前状态,因此可选取片内某一个或两个单元作为上电标志。设40H用来做上电标志,上电标志字为78H,若系统复位后40H单元内容不等于78H,则认为是硬件复位,否则认为是软件复位,转向出错处理。若用两个单元作上电标志,则这种判别方法的可靠性更高。
(2 )开机复位与看门狗故障复位的识别
开机复位与看门狗故障复位因同属硬件复位, 所以要想予以正确识别,一般要借助非易失性RAM或者EEROM。当系统正常运行时,设置一可掉电保护的观测单元。当系统正常运行时,在定时喂狗的中断服务程序中使该观测单元保持正常值(设为 AAH),而在主程中将该单元清零,因观测单元掉电可保护,则开机时通过检测该单元是否为正常值可判断是否看门狗复位。
(3 )正常开机复位与非正常开机复位的识别
识别测控系统中因意外情况如系统掉电等情况引起的开机复位与正常开机复位,对于过程控制系统尤为重要。如某以时间为控制标准的测控系统,完成一次测控任务需1小时。在已执行测控50分钟的情况下,系统电压异常引起复位,此时若系统复位后又从头开始进行测控则会造成不必要的时间消耗。因此可通过一监测单元对当前系统的运行状态、系统时间予以监控,将控制过程分解为若干步或若干时间段,每执行完一步或每运行一个时间段则对监测单元置为关机允许值,不同的任务或任务的不同阶段有不同的值,若系统正在进行测控任务或正在执某时间段,则将监测单元置为非正常关机值。那么系统复位后可据此单元判系统原来的运行状态,并跳到出错处理程序中恢复系统原运行状态。
非正常复位后系统自恢复运行的程序设计
对顺序要求严格的一些过程控制系统,系统非正常复位否,一般都要求从失控的那一个模块或任务恢复运行。所以测控系统要作好重要数据单元、参数的备份,如系统运行状态、系统的进程值、当前输入、输出的值,当前时钟值、观测单元值等,这些数据既要定时备份,同时若有修改也应立即予以备份。
当在已判别出系统非正常复位的情况下,先要恢复一些必要的系统数据,如显示模块的初始化、片外扩展芯片的初始化等。其次再对测控系统的系统状态、运行参数等予以恢复,包括显示界面等的恢复。之后再把复位前的任务、参数、运行时间等恢复, 再进入系统运行状态。
应当说明的是,真实地恢复系统的运行状态需 要极为细致地对系统的重要数据予以备份,并加以数据可靠性检查,以保证恢复的数据的可靠性。
其次,对多任务、多进程测控系统,数据的恢复需考虑恢复的次序问题。
系统基本初始化是指对芯片、显示、输入输出方式等进行初始化,要注意输入输出的初始化不应造成误动作。而复位前任务的初始化是指任务的执行状态、运行时间等。
对于软件抗干扰的一些其它常用方法如数字滤波、RAM数据保护与纠错等,限于篇幅,本文未作讨论。在工程实践中通常都是几种抗干扰方法并用,互相补充 完善,才能取得较好的抗干扰效果。从根本上来说,硬件抗干扰是主动的,而软件是抗干扰是被动的。细致周到地分析干扰源,硬件与软件抗干扰相结合,完善系统监控程序,设计一稳定可靠的单片机系统是完全可行的。
基础知识
本段仅针对硬件设计人员和软件设计人员,为了便于对硬件的理解要有一定的汇编语言基础。
总线
我们知道,一个电路总是由元器件通过电线连接而成的,在模拟电路中,连线并不成为一个问题,因为各器件间一般是串行关系,各器件之间的连线并不很多,但计算机电路却不一样,它是以微处理器为核心,各器件都要与微处理器相连,各器件之间的工作必须相互协调,所以需要的连线就很多了,如果仍如同模拟电路一样,在各微处理器和各器件间单独连线,则线的数量将多得惊人,所以在微处理机中引入了总线的概念,各个器件共同享用连线,所有器件的8根数据线全部接到8根公用的线上,即相当于各个器件并联起来,但仅这样还不行,如果有两个器件同时送出数据,一个为0,一个为1,那么,接收方接收到的究竟是什么呢?这种情况是不允许的,所以要通过控制线进行控制,使器件分时工作,任何时候只能有一个器件发送数据(可以有多个器件同时接收)。器件的数据线也就被称为数据总线,器件所有的控制线被称为控制总线。在单片机内部或者外部存储器及其它器件中有存储单元,这些存储单元要被分配地址,才能使用,分配地址当然也是以电信号的形式给出的,由于存储单元比较多,所以,用于地址分配的线也较多,这些线被称为地址总线。
数据地址指令
这三者的本质都是一样的——数字,或者说都是一串‘0’和‘1’组成的序列。换言之,地址、指令也都是数据。指令:由单片机芯片的设计者规定的一种数字,它与我们常用的指令助记符有着严格的一一对应关系,不可以由单片机的开发者更改。地址:是寻找单片机内部、外部的存储单元、输入输出口的依据,内部单元的地址值已由芯片设计者规定好,不可更改,外部的单元可以由单片机开发者自行决定,但有一些地址单元是一定要有的(详见程序的执行过程)。数据:这是由微处理机处理的对象,在各种不同的应用电路中各不相同,一般而言,被处理的数据可能有这么几种情况:
1.地址(如MOV DPTR,1000H),即地址1000H送入DPTR。
2.方式字或控制字(如MOV TMOD,#3),3即是控制字。
3.常数(如MOV TH0,#10H)10H即定时常数。
4.实际输出值(如P1口接彩灯,要灯全亮,则执行指令:MOV P1,#0FFH,要灯全暗,则执行指令:MOV P1,#00H)这里0FFH和00H都是实际输出值。又如用于LED的字形码,也是实际输出的值。
理解了地址、指令的本质,就不难理解程序运行过程中为什么会跑飞,会把数据当成指令来执行了。
P0/P2/P3功能
初学时往往对P0口、P2口和P3口的第二功能用法迷惑不解,认为第二功能和原功能之间要有一个切换的过程,或者说要有一条指令,事实上,各端口的第二功能完全是自动的,不需要用指令来转换。如P3.6、P3.7分别是WR、RD信号,当微处理机外接RAM或有外部I/O口时,它们被用作第二功能,不能作为通用I/O口使用,只要一微处理机一执行到MOVX指令,就会有相应的信号从P3.6或P3.7送出,不需要事先用指令说明。事实上‘不能作为通用I/O口使用’也并不是‘不能’而是(使用者)‘不会’将其作为通用I/O口使用。你完全可以在指令中按排一条SETB P3.7的指令,并且当单片机执行到这条指令时,也会使P3.7变为高电平,但使用者不会这么去做,因为这通常会导致系统的崩溃。
程序执行过程
单片机在通电复位后8051内的程序计数器(PC)中的值为‘0000’,所以程序总是从‘0000’单元开始执行,也就是说:在系统的ROM中一定要存在‘0000’这个单元,并且在‘0000’单元中存放的一定是一条指令。
堆栈
堆栈是一个区域,是用来存放数据的,这个区域本身没有任何特殊之处,就是内部RAM的一部份,特殊的是它存放和取用数据的方式,即所谓的‘先进后出,后进先出’,并且堆栈有特殊的数据传输指令,即‘PUSH’和‘POP’,有一个特殊的专为其服务的单元,即堆栈指针SP,每当执一次PUSH指令时,SP就(在原来值的基础上)自动减2,每当执行一次POP指令,SP就(在原来值的基础上)自动加2。由于SP中的值可以用指令加以改变,所以只要在程序开始阶段更改了SP的值,就可以把堆栈设置在规定的内存单元中,如在程序开始时,用一条MOV SP,#5FH指令,就是把堆栈设置在从内存单元60H开始的单元中。一般程序的开头总有这么一条设置堆栈指针的指令,因为开机时,SP的初始值为07H,这样就使堆栈从08H单元开始往后,而08H到1FH这个区域正是8031的第二、三、四工作寄存器区,经常要被使用,这会造成数据的混乱。不同作者编写程序时,初始化堆栈指令也不完全相同,这是作者的习惯问题。当设置好堆栈区后,并不意味着该区域成为一种专用内存,它还是可以象普通内存区域一样使用,只是一般情况下编程者不会把它当成普通内存用了。
开发过程
这里所说的开发过程并不是一般书中所说的从任务分析开始,我们假设已设计并制作好硬件,下面就是编写软件的工作。在编写软件之前,首先要确定一些常数、地址,事实上这些常数、地址在设计阶段已被直接或间接地确定下来了。如当某器件的连线设计好后,其地址也就被确定了,当器件的功能被确定下来后,其控制字也就被确定了。然后用文本编辑器(如EDIT、CCED等)编写软件,编写好后,用编译器对源程序文件编译,查错,直到没有语法错误,除了极简单的程序外,一般应用仿真机对软件进行调试,直到程序运行正确为止。运行正确后,就可以写片(将程序固化在EPROM中)。在源程序被编译后,生成了扩展名为HEX的目标文件,一般编程器能够识别这种格式的文件,只要将此文件调入即可写片。在此,为使大家对整个过程有个认识,举一例说明:
单片机试验板 ORG 0000H
LJMP START
ORG 040H
START:
MOV SP,#5FH ;设堆栈
LOOP:
NOP
LJMP LOOP ;循环
END ;结束
评论