电子开发 | 基础入门 | 电路原理图 | 姊舰鍥惧疄渚� | PLC鍩虹   銆婂鏋滃枩娆㈡湰绔欙紝璇锋寜 Ctrl+D 鎵嬪姩鏀惰棌锛佹劅璋㈡偍鐨勬敮鎸併€�涓€璧峰涔犱竴璧疯繘姝ワ紝鐢靛瓙寮€鍙戠帇娆㈣繋鎮紒.

电子开发网

电子开发网电子设计 | 电子开发网Rss 2.0 会员中心 会员注册

鈽呯數璺叕寮忔墜鍐岋紝鏈€鏂扮増銆婄數瀛愮數璺叕寮忚绠楀櫒銆嬶紝鐢佃矾鍏紡鏌ヨ鎵嬪唽 鐢佃矾鍏紡璁$畻鍣ㄣ€愮數瀛愪粠涓氫汉鍛樺繀澶囨墜鍐屻€�
鈽嗗崄澶╁浼氬崟鐗囨満瀹炰緥100 c璇█ chm鏍煎紡銆傝祫鏂欏唴瀹硅缁嗭紝瑕嗙洊渚嬪瓙澶氾紝鍐呭骞裤€愮數瀛愪粠涓氫汉鍛樺繀澶囨墜鍐屻€�
搜索: 您现在的位置: 电子开发网 >> 电子开发 >> 单片机 >> 正文

MCS-51单片机系统软复位的深入研究

作者:佚名    文章来源:本站原创    点击数:1869    更新时间:2009-6-12
摘要 在没有硬件看门狗的系统以及一些对单片机I/O口线状态高度敏感的系统中,软复位功能相当重要。标准MCS-51以及很多常见的51内核单片机没有提供“软复位”方法。本文分别以5lasm子程序和C51函数的形式,为MCS-51单片机系统提供完善的“软复位”方法。
关键词 MCS-51单片机软复位51asm C51


引 言
    复位是单片机的初始化操作,其作用是使单片机和系统中其他部件处于一个确定的初始状态,并从这个状态开始工作。
    标准MCS-51的复位逻辑比较简单,只有通过复位引脚RST进行外部扩展。对于具有外部看门狗芯片的系统,当单片机由于某种原因程序“跑飞”而没有按时“喂狗”,或由软件陷阱捕捉到程序运行的异常,而故意不“喂狗”时,看门狗芯片会给单片机的RST引脚提供一个复位信号,让单片机进行一次“硬”复位,以恢复程序的正常运行;有些5l内核的单片机具有片内的看门狗,或者提供可访问的寄存器实现“软件复位”。一般实现的也都是与在RST引脚提供复位信号等价的“硬”复位。
    在有些应用中,由于单片机所接外设严格依附干单片机口线的时序,甚至不允许硬件复位时对口线的复位操作;或由于系统没有外部看门狗,只能用软件监测程序运行异常并重新对单片机进行初始化操作,这时就需要所谓的“软复位”了。
    在互联网上可以找到一些软复位的方法,但都不够完善或不方便使用,基于C5l的软复位更是一个难点。本文提出一种功能完善、占用资源少的实现方法,在51asm和C51下都可方便使用。


1 “软复位”要实现的功能
    对于MCS-51系统,所谓“软复位”是一种由用户软件控制的复位活动,利用一系列指令来模拟硬件复位所实现的各种操作内容,并且重新从头开始执行用户程序。其内容包括:
    ①程序计数器PC的复位,从0000H开始执行程序;
    ②中断优先级状态触发器的复位;
    ③特殊功能寄存器的复位;
    ④程序跑飞前状态的尽量恢复。
    其中,特殊功能寄存器的复位可根据具体系统的需要,在软复位以前对相关寄存器逐个赋值再软复位的方法完成,或在复位以后的初始化程序中实现;程序跑飞前状态的恢复也可根据RAM中存留的数据来进行判断处理。本文重点讨论关于程序计数器的复位和中断优先级状态触发器的复位,在此基础上不难再增加特殊功能寄存器的复位和程序跑飞前状态的恢复,下文不再涉及相关代码。
    程序计数器的复位容易实现,一条“LJMP 0000H”即可。中断优先级状态触发器的复位则比较困难,由于它们对于用户程序是不可见的,无法直接读写其内容,只有用RETI指令才能清除。又由于51单片机两级中断机制,低优先级中断有可能被高优先级中断再次中断而形成中断再入,而一次RETl只能退出当前优先级中断并清除相应的中断优先级状态触发器,因此最坏情况下需要两次RETI才能确保中断优先级状态触发器的复位。综合考虑,可先用压栈的方法准备跳转后的入口地址,再用RETI来完成跳转和清除中断优先级状态触发器的双重任务,把以上过程执行两次,前一次的目标地址是后一次的入口,后一次则跳转到0000H,完成复位过程。


2 软复位的实现方法
    前已述及软复位要完成的功能,包含程序计数器PC的复位、中断优先级状态触发器的复位、特殊功能寄存器的复位(略)和程序跑飞前状态的恢复(略)。下面分别用汇编程序和C51程序来实现,重点介绍C51程序的实现方法。
2.1 51asm汇编程序实现

    使用时,在软件陷阱处理程序段或软件看门狗中用“LJMP #RST_O”指令跳转到此段程序入口处即可。
2.2 C51程序实现
    用C语言实现MCS-51系统的软复位,互联网上出现过多种版本,但都不够完善。以下基于业界应用最广泛的编译器Keil C51来讨论。如:

    这段程序,用强制类型转换把地址0000H转换成re-set_not_best_O()函数的入口。实际上调用函数reset_not_best_O()等价于“LJMP 0000H”,没有处理可能的中断状态问题。
    又如:

    这段代码中,一维字符数组中为复位代码的机器码。“(*((Void(*)())(rst)))()”是把rst这个字符数组的地址强制转换成函数指针,并调用。实际上调用函数reset_not_best_1()是执行了一段如下代码:

    可见,调用一次reset_not_best_l()函数相当于执行了1次清除中断优先级状态触发器的动作,然后跳转到0000H重新执行。但此段代码仍然可能被再次中断失效,或者当原来堆栈已经溢出时导致对0000H地址的压栈错误,不能正确实现“软复位”功能。除此之外,由于KeilC5l在把控制权交给函数main()之前对内部RAM进行初始化的代码是:

    此处R0作为循环变量使用,对内部RAM从7FH单元开始,按照每次递减的方法对内部RAM逐一进行清零。当R0指向00H时,以上程序可以很好地完成清零工作;然而R0依据RS0、RSl取值的不同,可以指向00H、08H、10H或18H单元。当:R0指向08H、10H或18H时,上面所列清零程序将陷入死循环。分析如下:
    以RS0=1、RSl=0,即RO指向08H为例。自标号LOOP处起始的循环进入时的状态是:R0=7FH,PC=#LOOP。设程序已执行到R0=08H,PC=#LOOP,此时执行PC指向处的指令“MOV @RO,A”,将把(RO)清零,也即08H单元清零。由于R0指向08H,实际上R0也被清零了,此时RO=00H,PC=#LOOPl;再执行一条指令“DJNZ R0,LOOP”,R0将由00H自减为OFFH,回到R0=OFFH,PC=#LOOP的状态;继续执行,将再次出现R0==08H,PC=#LOOP的状态,陷入死循环。当R0指向10H或18H单元时也类似会陷入死循环。为了避免上述问题,可以把字符数组中机器码改为与以下程序段对应:

    调用改造后的reset_not_best_l()函数将清除中断优先级状态触发器,并跳转到0000H单元继续执行,从而实现了软复位。但由于只执行了1次RETT指令,在复位前出现了中断再入的极端情况下,仍会出现低优先级中断放锁死的现象。由于无法在字符数组中实现对最终代码地址的取得,无法如2.1节汇编程序中的“MOV DPTR,#RSTl”一样读取绝对地址,因此也无法实现如同2.1节中的两次RETl来保证清除全部的中断优先级状态触发器。解决的办法是,在内存中设置标志flag,每次复位后都检查特定标志,接如下伪代码来判定(假定复位标志设为0x55,若复位后发现标志字为0x55则转正常初始化程序,否则置复位标志为0x55,再次复位):

    但这种办法有两个弊端:其一,万一在程序跑飞时刚好处在中断再入中,且flag所在的RAM地址中由于某种原因恰好是0x55,低级中断仍是被锁死的;其二,Keil C5l的缺省编译模式是加上了初始化程序段startup.A51的,在这段程序中对全部的内部RAM都进行了初始化,复位标志也会被清0,flag将失效。因此要正常使用标志flag必须手工修改startup.A5l,不要清除flag单元,或者禁止stanup.A5l的使用,自己对内部RAM进行初始化,都比较繁琐。
    若用以下reset_best()函数,则可顺利解决上述问题:

    在此函数中,首先定义了结构体类型ResetStruct,它包含字符数组rstcode和16位整型数addr两个成员。在结构体变量的RST实例中,RST.rstcode是复位代码对应的机器码,RST.addr的值是RST.rstcode这个数组的首地址+偏移量0x15。其实是以下汇编代码中标号rstl处的地址,也即是“#rstl”,由Keil C51在编译时自动计算得到。


    此reset_best()函数巧妙地利用C语言中数组名即是数组首地址(其实质就是这一段“软复位”代码的入口地址!),把数组名+偏移量0x15赋值给结构体的int型的成员addr,则正好把软复位代码中标号rstl的入口地址两个字节取了出来(由KeilC51在编译连接时完成),存放在RST.addr中,由于结构体连续存储,RST.addr会紧接着软复位代码RST.rstcode存放。见上段程序中的“DB #LOW(rstcode+OFH)”和“DB #HIGH(rstcode+09H)”。
    当本程序被调用并执行到“MOVC A,@A+PC”时,分两次取到的分别是“#rstl”的低位和高位字节,把它们压栈以后再调用RETI指令,除了清除可能有的中断优先级状态记录外,还会跳转到rstl执行后续的连续两次压栈操作,把第2次RETI的返回地址设为0000H,再通过紧接着的RETI指令,清除可能还有的中断优先级状态记录,并跳转到0000H完成完整的复位操作。
    本程序使用一个C51函数完成了完整的包含两次RETI在内的复位操作,消除了所有已知隐患,只需在应用程序中包含此reset_best()函数,在需要软复位时调用即可。2.1节中所列汇编语言的子程序也可使用本节分析时所用汇编代码代替。


结 语
    本文对MCS-51单片机的“软复位”进行了深入讨论,给出了分别基于51asm的汇编子程序和基于C5l的函数。使用本文所述的“软复位”方法,无论是5lasm程序还是C51程序,所需的资源消耗都很小,只占用二三十个字节的程序存储器,使用也非常简单,不会增加编程负担。当具体应用系统还需进行特殊功能寄存器的复位以度程序跑飞前状态的恢复时,在此基础上也很容易实现。特别是当单片机所接外设严格依附于单片机口线的时序,须尽量避免硬件复位对口线的复位操作或系统不具备硬件看门狗时,对于提高单片机系统的抗干扰能力有较大的实用价值。实际应用表明,这种软复位方法是非常有效的。

Tags:单片机,复位,知识,单片机研究  
责任编辑:admin
请文明参与讨论,禁止漫骂攻击,不要恶意评论、违禁词语。 昵称:
1分 2分 3分 4分 5分

还可以输入 200 个字
[ 查看全部 ] 网友评论
    没有任何评论
鐢靛瓙寮€鍙戠綉锛氭眹闆嗙患鍚堝悇绫荤數瀛愬埗浣滀笌鐢佃矾鍥剧殑缃戠珯锛宲lc宸ユ帶鎶€鏈�,妯$數鏁扮數鐭ヨ瘑,鍗曠墖鏈篍DA绛夌瓑锛佽崯钀冪數璺浘缃戠珯绮惧崕锛屼负宸ョ▼甯堝垱閫犱环鍊笺€傛杩庡叧娉ㄥ井淇″叕浼楀彿锛氱數瀛愬紑鍙戠綉锛�
最新推荐
璧勬枡鍖呬笅杞�
 [闂佸憡顨嗗ú婊勬櫠閺嶎厼瀚夊Δ锕佹硶閵堫偊鏌¢崒锔藉]闂佸憡銇炵粈渚€濡垫径灞稿亾濞戝磭绱扮紒鍙樺嵆瀹曪繝寮撮悩宸毈闂佸搫鐗嗛幖顐︽偪閸曨剛鐟归柨鐕傛嫹100 c闁荤姴娴勯幏锟�
 [闁哄鍎愰崹顖氣枎閵忋垻灏甸柨鐕傛嫹]婵炴垶鎸搁ˇ瀹犮亹缁€鐑睠闁诲孩鍐荤紓姘卞姬閸曨剛顩烽悹鎭掑妽閸╁倿寮堕悜鍡楃仧婵炲棭鏁-TR
 [闂佹椿婢€缁插鎯岄悙顒傤浄閻犳亽鍔嶉崺鍌炴偣娴g懓绀冩い鎿勬嫹]LM324闁哄鏅滈崝鏍棘閿燂拷4~20mA闁哄鍎戦幏锟�1~5V闂佹眹鍨归悘姘辩矈閿燂拷
 [闂佹椿婢€缁插鎯岄悙顒傤浄閻犳亽鍔嶉崺鍌炴偣娴g懓绀冩い鎿勬嫹]LM386婵$偛婀辩划顖炴倵椤掍焦濯撮柟鎹愵嚙椤斿﹪鏌涜箛鎿冨剶妞ゃ儲鎹囧銊╁箚瑜嬫禍锝夋煕閿濆啫濡奸悽顖ゆ嫹
 [闂佹椿婢€缁插鎯岄悙顒傤浄閻犳亽鍔嶉崺鍌炴偣娴g懓绀冩い鎿勬嫹]936闂佺粯甯掗敃銈堛亹閹绢喗鍋ㄥù锝呭暟閻斿懘鏌涘Ο鐓庢灁闁诡喖锕畷鍫曟晸閿燂拷
 [闂佸憡顨嗗ú婊勬櫠閺嶎厼瀚夊Δ锕佹硶閵堫偊鏌¢崒锔藉]闁烩剝甯掗幊搴ㄦ晬閹邦兘鏋栭柕蹇ョ磿閵堟挳鎮归悮瀛樺+濠电偞鎸撮弲娑氣偓鐧告嫹+闂佺缈伴崕鎾敆閻斿吋鍎嶉柛鏇ㄥ亜缁€锟�
 [闂備緡鍋呭銊╁极閵堝鍋ㄩ梻鍫熺〒閹藉秹鎮规担鐟扮妞ゆ挸鎲″ḿ顏堫敍濞嗘劦鍋�]S7-200PLC闂佹眹鍔岀€氼亞鎸掗姀銈嗗剳闁绘梹妲掗幏顐⒚归悪鍛 S7_2
 [闁哄鍎愰崹顖氣枎閵忋垻灏甸柨鐕傛嫹]S7-200闁圭厧鐡ㄩ幐濠氬几閸愨晝顩烽悹浣告贡缁€鍕煕韫囷絿鍘滅紒鎲嬫嫹,STEP7
 [闁哄鍎愰崹顖氣枎閵忋垻灏甸柨鐕傛嫹]ModbusPoll闂佸憡绮岄鐖媎busSalve闂佺ǹ楠忛幏锟�
 [闁哄鍎愰崹顖氣枎閵忋垻灏甸柨鐕傛嫹]STEP7濠碘槅鍨崜婵堚偓姘懇閺屽矁绠涢弬璺ㄦ▌婵炲濮伴崐鏇犺姳閿燂拷 Smart_
 [闁哄鍎愰崹顖氣枎閵忋垻灏甸柨鐕傛嫹]Modbus闁荤姴顑呴崯鎶芥儊椤栨粌鍨濋柛鎾楀倻瑙� v1.024 缂傚倷绶ら幏锟�
 [闁哄鍎愰崹顖氣枎閵忋垻灏甸柨鐕傛嫹]Modscan32闂佸憡绮岄鐖媎sim32,modb
 [闂佹椿婢€缁插鎯岄悙顒傤浄閻犳亽鍔嶉崺鍌炴偣娴g懓绀冩い鎿勬嫹]89c51闂佺ǹ绻愰ˇ閬嶆偟濞戙垹妫橀梺顐g闂嗗綊鏌i鍡楁珢缂佽鲸鐛otues
 [闂佹椿婢€缁插鎯岄悙顒傤浄閻犳亽鍔嶉崺鍌炴偣娴g懓绀冩い鎿勬嫹]婵炴垶鎸稿ú銈夊礋妤e啫鍌ㄩ柛鐐村Оotues婵炲濮惧▔鏇烇耿閿涘嫮鐭欓悗锝庝簽绾板秵绻濊閸旀鎮ラ敓锟�
 [闂佹椿婢€缁插鎯岄悙顒傤浄閻犳亽鍔嶉崺鍌炴偣娴g懓绀冩い鎿勬嫹]51闂佸憡顨嗗ú婊勬櫠閺嶎厼瀚夐柛婵嗗閸у﹦绱掔€h埖瀚� protues婵炲濮惧▔鏇烇耿閿燂拷
鏈€鏂版枃绔�
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 在线帮助 - 文章列表
返回顶部
刷新页面
下到页底
晶体管查询