标题:
CS-51系列单片机的软件复位方法
[打印本页]
作者:
cogobuy123
时间:
2012-10-19 17:17
标题:
CS-51系列单片机的软件复位方法
在单片机系统的应用中,我们经常需要用到复位技术来实现抗干扰。有的单片机(如
8098
)有专门的复位指令,某些增强型
MCS-51
系列单片机虽然没有复位指令,但片内集成了
WATCHDOG
电路,可以很容易实现复位。而普及型
MCS-51
系列单片机(如
8031
和
8032
)既无复位指令,又不带硬件
WATCHDOS
,如果不外接硬件
WATCHDOG
,就必须采用软件复位技术。所谓软件复位就是用一系列指令来模仿复位操作。在
MCS-51
系列单片机中,只要用指令使程序从起始地址(
0x0000
)开始执行,就可以复位单片机。本文介绍三种用
C
语言实现软件复位的简单方法
方法一:
void Reset(void)
{ unsigned char code rst[ ]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};
(*((void (*)(void))(rst)))();
}
先来看一下这段程序编译后的汇编码:
C:0x0015 E4 CLR A //
清除
ACC=0
C:0x0016 C0E0 PUSH ACC(0xE0) //
压
0
到堆栈
——8
位
C:0x0018 C0E0 PUSH ACC(0xE0) //
再压
0
到堆栈
——
再
8
位
C:0x001A 32 RETI //
清除中断激活标志并返回到
0x0000
执行
C:0x001B 020015 LJMP C:0015
可以发现,数组
rst[]
中的内容恰恰是上面前四行的汇编机器码,即程序中将代码当作数组的数据来存储。再来研究后面的那句函数调用
(*((void (*)(void))(rst)))()
,
rst
是数组名(即数组首元素地址),
(void(*)(void))
是函数指针的强制类型转换运算,
(void(*)(void))(rst)
是将数组名
rst
强制转换成一个无参数无返回值的函数的指针,指向
rst
的首地址。只需调用
(*((void (*)(void))(rst)))()
,即可将数组中的数据当作函数代码来运行,因为无论是数据还是代码都是以二进制存储的,本质上是相同的。
方法二:
void Reset(void)
{ ( * ( void (*)( ) )0 ) ( );
}
这段程序摘自《
C
缺陷与陷阱》,比方法一中的更为简洁。与方法一类似,它也是使用函数指针的强制类型转换运算将函数指针指向一个非函数的地址,但不同的是它直接指向程序起始地址
0x0000
,方法一先指向数组
rst
,再利用数组中的机器码使程序跳转到
0x0000
。它编译后的汇编只有一句
LCALL C_STARTUP(C:0000)
。
方法三:
void Reset(void)
{ VoidFunc(); //
请注意,函数
VoidFunc()
在程序中未定义
}
上面的
VoidFunc()
函数虽然没有定义,但在
Keil
环境中编译时只是警告,并不报错。编译后的汇编码为
LJMP C_STARTUP(C:0000)
,同方法二极为相似,使程序跳转到
0x0000
开始执行,同样实现了软件复位的功能。这种做法最为简单,但不符合
ANSI C
标准中函数应先定义后调用的要求,在其它某些环境中可能无法编译通过,因此不推荐。
总结
我们知道,在
MCS-51
单片机的所有指令中,只有
RETI
指令能清除中断请求标志。因此只有方法一能在中断子程序中被调用,方法二和方法三都不能,否则系统复位后,中断请求标志仍在,可能造成系统刚复位就错误地进入了中断子程序。实际应用中应根据实际情况,选择合适的方法。
由
科通芯城(
www.cogobuy.com
)
中国首个
电子元器件采购
自营电商
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0