4333|0

58

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

单片机实现软件复位(软复位)的方法及讨论。(转帖)加自己整理。 [复制链接]

单片机实现软件复位(软复位)的方法及讨论

(天堂雨林博客blog.sina.com.cn/acer收集整理)

单片机软复位有什么好的方法?如从机收到复位命令(软件命令),程序怎么使机器复位?虽然要使软件始终处于可控状态,最好不要用"复位",因为复位是纯硬件过程,软件是不可控的.但是我们还是要讨论方法,一般流传的方法如下:

1、放狗;

2、((void(code *)(void))0x0000)();----->使用时建议去掉code项,不然出现未定义code的报错.

3、用单片机一个引脚控制点一下RSTRST;

4、用单片机一个引脚控制重新加电;

5、用单片机自带的软件复位指令或内狗指令;

6、goto大法;



天堂雨林博客对以上方法的意见:

方法1:“放狗”是单片机软复位的最好办法,也基本上是唯一的一个办法。但并不是所有单片机都具备看门狗的功能,也不是一个万全之策。



办法2:这不是复位,只是把程序转到地址0去执行,不如用一个JMP更直接。目前可能极少数单片机或者用户已经自行添加Boot load时用户程序的程序开始地址并不为0x0000,所以需要查找这些特定单片机的启动地址。
在keil C51下面可以这样实现:
void soft_reset(void)
{
((void (code *) (void)) 0x0000) ();
}
在需要软件复位的地方使用语句:
soft_reset();
一般可实现软件复位。


办法3:用软件实现的硬复位。需要牺牲一个单片机引脚,且增加了单片机外

部电路构造的复杂性,很不可取。


办法4:类似办法3,同样需要牺牲一个单片机引脚,且增加了单片机外部电路

构造的复杂性,很不可取。但不能把它单单地当成是复位,应该叫上电复位。



办法5:Atmel 89C不带内狗,S的有内狗,只是一条指令就行。如STC的单片机有软件复位指令,即ISP_CONTR,地址在0E7H 单元(即str ISP_CONTR=0xE7),MOV ISP_CONTR,#00100000B(C语言为ISP_CONTR=0x20),内狗也是一条指令MOV WDT_CONTR,#00111100B!
STC 51系列单片机Datasheet中指出:传统的8051 单片机由于硬件上未支持此功能,用户必须用软件模拟实现,实现起来较麻烦。现STC 新推出的增强型8051 根据客户要求增加了ISP_CONTR 特殊功能寄存器,实现了此功能。用户只需简单的控制ISP_CONTR 特殊功能寄存器的其中两位 SWBS / SWRST 就可以系统复位了。



办法6:程序从头(上电复位处)开始运行,且只有一个循环这种情况,当然可以用goto,如在main()的开头设一个start:,在程序的唯一循环中设定一个条件,然后goto命令。但需要注意,如果是在中断例程里,那么中断挂号寄存器仍置位,同级中断不能执行。所以必须先使中断挂号寄存器清零,EA = 0。只有RETI指令可以使中断挂号寄存器清零。51单片机有两级中断优先级,所以需要执行两次RETI指令。这用汇编是很简单的事,而C则比较难以实现。但是,goto命令尽量不要用,因为goto会到处乱窜,而且goto不能跑到函数外面去执行一个命令。



最后总结如下:最好使用办法5最为简洁方便,使用办法2实现也不失为一种好方法

关于方法2的补充:

void(*)() 这是一个函数指针
那么(*(void(*)())就是指向函数指针的指针
后面跟的地址为指向函数指针的指针地址。
这样的话执行上面程序就会自动跑到PC(0x0000)的地址开始执行程序,也就实现了软件复位功能与看门狗复位差不多。
也能实现任意地址跳转功能。(注意复位地址自己查看各单片机的main函数入口地址或复位的起始地址)

概念补充:

定义一个返回值是空函数指针的定义形式如下:

void (*p) ( )

当把函数指针赋值后,就能通过函数指针调用函数,调用形式如下,

(*p) ( );

或等价的简化形式:

p ( );

假设rst就是函数指针(相当于把rst的地址传递给P),则如下调用形式就可以令单片机复位再起。

(*rst ) ( );

但可惜,rst不是函数指针,而是数组名,虽然两者都是地址,但不可直接调用数组名。

如同把char型变量a赋值给int型变量b,(int) 表示强制类型转换:

b = (int) a

函数指针的强制类型转换公式如下(C语言的哲学是定义形式和使用一致):

( (void (*)() ) rst

这样经过转换后的rst就可以当作函数指针使用了,简单的调用形式如下:

#define K ( (void (*)( ) ) rst

(*K) ( )

或:

( * ( void (*)( ) )rst ) ( );

这样的语句就完成复位再启功能了。类型转换符()的优先级跟指针运算符*的优先级相同,
二者的结合方向是自右至左
,所以上述语句就能完成复位功能了。保险起见有些程序员常
常喜欢再加个括号:

#define K ( ( (void (*)( ) ) rst )

(*K) ( )



( *( ( void (*)( ) )rst ) ) ( );



由于没有输入参数,上述复位代码更严谨的写法是:

#define K ( ( (void (*)(void ) ) rst )

(*K) ( )



( *( ( void (*)(void ) )rst ) ) ( );

二:上电复位与看门狗信号复位的不同处理过程

共同的地方:

复位后状态:程序计数器PC的值为0000h
             I/O口为FFH状态
             堆栈指示器SP=07h
             所有特殊功能寄存器SFR的有效位均为0
不同的地方:
            上电复位,上电复位后内部RAM为随机数
             看门狗复位,片内RAM中数据不受影响 

 

 


 

 

 

此帖出自51单片机论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表