×
嵌入式 > 嵌入式开发 > 详情

关于单片机的软复位

发布时间:2020-09-03 发布时间:
|
一、数组定位

main()
{
unsignedcharcoderst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};//复位代码
(*((void(*)())(rst)))();//执行上一行代码,将rst数组当函数调用
}
本来我告诉他嵌入如下代码:
clra
pushacc
pushacc
reti
结果他却玩了前面哪一段,而数组rst[]中的内容恰恰是上面的汇编机器码,他的做法是将
rst数组的数据当作代码保存,然后采用绝对地址方式指向该数组,将该数组中的代码当作
函数来运行。居然通过了!


l单片机复位的更好方法
帖子中汇编语言解释如下:
clra//清除ACC=0
pushacc//压0到堆栈——8位
pushacc//再压0到堆栈——再8位
reti//返回到0地址,从而执行。
本句的分析方法同上,但更加精炼,没有多余的汇编语句。

软件复位跟真正上电复位有很大差别:上电复位时大部分寄存器都有确定的复位值;软件
复位则只相当于从0地址开始执行而已,寄存器不会变为确定的复位值。

例:修改出错处理如下:
ERR: CLR EA ;正确的软件复位入口
MOV 66H,#0AAH ;重建上电标志
MOV 67H,#55H
MOV DPTR,#ERR1 ;准备第一次返回地址
PUSH DPL
PUSH DPH
RETI ;清除高级中断激活标志
ERR1: CLR A
PUSH ACC
PUSH ACC
RETI ;清除低级中断激活标志
这时,必须执行两次RETI,才能到达0000H,以保证清除全部中断激活标志,达到和硬件复位相同的效果。同样,软件陷井也必须由下列三条指令
NOP
NOP
LJMP STAT
改成:
NOP
NOP
LJMP ERR
才能达到目的。
当主程序受到干扰被软件陷阱捕获时,中断标志并未置位,执行ERR过程中,RETI指令等效于RET指令,同样可以达到软件复位的目的。有兴趣的读者可以将软件陷阱代替死循环,分别用LJMP STAT和LJMP ERR1来替代LJMP ERR,再将干扰检测分别设在低级中断和主程序中,实验结果必然证明同:只有LJMP ERR才能万无一失地实现软件复位,使系统摆脱干扰同,恢复正常。在MCS-51单片机的软件复位过程中,必须连续执行两次中断返回指令RETI才能确保系统恢复正常。

2、C语言复位

void reset (void){((void (code *) (void)) 0x0000) ();

复位程序并不能清除8051的中断系统和某些8051的外围设备,当您在中断程序中调用上面的软件复位程序后,中断将再不能触发。因此,以上的软复位程序不能在中断子程序中调用。

可以使用下面的程序跳到0000H实现软复位,下面的程序实际上是一个函数指针,指针指向了0000H地址。((void (code *) (void)) 0x0000) ();

下面的例子将实现软件自复位
void reset (void)
{
((void (code *) (void)) 0x0000) ();
}
void main (void)
{
reset ();
}

你可能注意到以上的软复位程序并不能清除8051的中断系统和某些8051的外围设备,当您在中断程序中调用上面的软件复位程序后,中断将再不能触发。因此,以上的软复位程序不能在中断子程序中调用。

下面的小段汇编函数可以在中断程序或主程序中调用,该函数将0x0000压栈,然后通过“RETI”出栈,这将清除中断环境并让程序从0000H重新开始运行。

?PR?RESET  SEGMENT CODERSEG ?PR?RESET
; C prototype:  void reset (void);PUBLIC resetreset: POP  ACC  ; pop return addressPOP  ACCCLR  A    ; push 0 as newPUSH ACC  ; return address to stackPUSH ACCRETI      ; execute return of interruptEND以上程序在选择bank 0寄存器组时工作良好,假如选择的不是bank0寄存器组,那么可能无法获得预料的结果。你应该在以上的程序或启动代码中加上“MOV PSW, #0”来选择bank 0寄存器组。

我的软复位,用了多年没问题
clrEA
callreset
callreset;用了多少中断优先级,就调用几次reset
jmpstart;跳转至0000h



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
CC-Link现场总线及应用实例