原创 喂狗程序应该放到哪里【转自某论坛的一段话】

2009-8-3 09:45 5951 15 15 分类: MCU/ 嵌入式

【仅供大家参考学习使用】


文本方式查看主题

-  电子自由港--(磁动力工作室)  (http://www.cdle.net/bbs/index.asp)
--  51单片机  (http://www.cdle.net/bbs/list.asp?boardid=2)
----  喂狗程序应该放在哪  (http://www.cdle.net/bbs/dispbbs.asp?boardid=2&id=2436)





--  作者:ooxy
--  发布时间:2004-6-29 21:36:00

--  喂狗程序应该放在哪

一个温度采集控制系统,有采集显示控制在t0中断,键盘输入设定值功能在外部中断1,看门狗采用x5045,喂狗程序应该放在哪?谢谢!




--  作者:明浩
--  发布时间:2004-6-30 8:53:00

--  

可以放在T0中断程序中


喂狗时间很短,一般不会影响,最好是放在中断设定定时值的语句后面




--  作者:ooxy
--  发布时间:2004-6-30 8:55:00

--  

但是x5045最大时间只有1.4秒


在外部中断中用键盘输入温度控制门限值时,时间是不可预知的,如何能保证及时喂狗?




--  作者:明浩
--  发布时间:2004-6-30 9:34:00

--  

我是说放在T0定时器中断呀




--  作者:deyun
--  发布时间:2004-6-30 9:42:00

--  

喂狗是个很有学问的问题。


假如你在定时中断中喂狗,会出现这样的问题:程序跑飞了,到了一个死循环,但是定时中断还会发生,狗还是在不断的喂。这样的喂狗方法不是很科学。


假如你在主循环中喂狗,可以避免上述问题,但是有子程序返回时间不可以预知,这样会耽误喂狗,也不是很科学。


比较好的办法是调用不可预知返回时间的子程序前就立即托管中断喂狗,子程序返回后主循环收回喂狗权。




--  作者:孤湮直
--  发布时间:2004-6-30 9:56:00

--  
deyun老师,我觉的这样也不好,既然有不可预知时间的返回子程序,我想还是在主循环中喂狗最牢靠了。总不能因为这个子程序始终不返回而死等它,别的(除了中断)什么也不干了吧!否则喂狗就没多大意思了!


--  作者:ooxy
--  发布时间:2004-6-30 9:57:00

--  
我原来的打算是t0采集显示,在t0中嵌套t1采用pid或模糊控制,在外部中断1中输入温度                                          
门限值,这个喂狗就不知道放哪里好了。有没有更好的框架?



--  作者:孤湮直
--  发布时间:2004-6-30 10:07:00

--  
何不在主循环中做PID运算或是在外部中断1直接做PID运算,这个时间比较长哦。然后在T0中进行控制啊,反正这个时间很短。


--  作者:deyun
--  发布时间:2004-6-30 10:16:00

--  

以下是引用孤湮直在2004-6-30 9:56:40的发言:
deyun老师,我觉的这样也不好,既然有不可预知时间的返回子程序,我想还是在主循环中喂狗最牢靠了。总不能因为这个子程序始终不返回而死等它,别的(除了中断)什么也不干了吧!否则喂狗就没多大意思了!





假设你的子程序执行时间超过喂狗时间,你不能不做完就让看门狗复位把。



我从来不使用硬件看门狗,因为我觉得硬件没有多大意思。



看看我的软件看门狗:



;-------------------------------------------------------------------------------
; RESET.ASM
; 版权所有 (c) 1995-2003 德运电子保留所有版权.
; 程序干扰复位程序, 仅仅适用于Keil C51 V7.06或者更低
;-------------------------------------------------------------------------------



; 使用举例:
;
; void timer0(void) interrupt 1 using 0
; {
;  reset();
;  return;
; }
;
; // main program
; void main(void)
; {
; ET0 = 1;
; TR0 = 1;
; while(1)
; {
;  TH0 = 0;  // 正常运行时刻复位中断计时器
; }
; return;
;}



      PUBLIC reset
      PROC   SEGMENT CODE
      RSEG PROC
reset:
      mov psw, #00      ; 初始化程序状态字为复位程序做准备
      mov dptr, #0001   ; addr16 指针(0000H: 02HHLL LJMP HHLL)
      mov a, #01        ; LL 指针
      movc a, @a+dptr   ; LL 值送 ACC
      add a, #06        ; 跳过储存器初始化模块指上栈指针初始化部分
      push acc          ; 压入中断返回地址低8位
      clr a             ; HH 指针
      movc a, @a+dptr   ; HH 值送 ACC
      addc a, #00       ; 加进位
      push acc          ; 压入中断返回地址高8位
      reti              ; 中断强迫返回到主程序开始位置



      END




--  作者:ooxy
--  发布时间:2004-6-30 10:33:00

--  
谢谢各位老师的回复,虽然我还是不太明白,但我会努力的


--  作者:孤湮直
--  发布时间:2004-6-30 10:59:00

--  

deyun 老师,我C嵌ASM没有用过,你这个程序我用WAVE编译没法通过啊。


另,你这样编写的解释是否这样:当定时器溢出就进行喂狗,对吗?


啊,如果试验成功,我又从老师这里偷学一招了,长见识。我是菜鸟请多指教。




--  作者:明浩
--  发布时间:2004-6-30 12:26:00

--  deyun老师,我有困惑

如果一些情况造成晶体停振或程序在还没开中断的语句前不断循环,那软复位也就不能起到作用。如果不使用硬件复位可以吗?如果软件和硬件一起使用效果又如何呢?




--  作者:deyun
--  发布时间:2004-6-30 21:47:00

--  

以下是引用明浩在2004-6-30 12:26:45的发言:


如果一些情况造成晶体停振或程序在还没开中断的语句前不断循环,那软复位也就不能起到作用。如果不使用硬件复位可以吗?如果软件和硬件一起使用效果又如何呢?




晶体停振什么复位也不行,开中断写在程序开始阶段。软件和硬件一起效果最好。



--  作者:deyun
--  发布时间:2004-6-30 21:56:00

--  

以下是引用孤湮直在2004-6-30 10:59:48的发言:


deyun 老师,我C嵌ASM没有用过,你这个程序我用WAVE编译没法通过啊。



另,你这样编写的解释是否这样:当定时器溢出就进行喂狗,对吗?



啊,如果试验成功,我又从老师这里偷学一招了,长见识。我是菜鸟请多指教。




可以实用WAVE集成环境,把我写的程序存为RESET.ASM,在模块文件中加入。并在程序中这样写:

# pragma OT(9)
#include<at89x51.h>
alien void reset();   //  写上这一句




--  作者:孤湮直
--  发布时间:2004-7-1 8:58:00

--  

deyun 老师,您看一下,我这样做为什么不能跳到中断呢?


是不是我哪儿有错啊!


# pragma OT(9)   是什么意思!



# pragma OT(9)
#include<reg51.h>
alien void reset();   //  写上这一句



void timer0(void) interrupt 1 using 0
{
  reset();


TH0=0;
  return;


}


// main program
void main(void)
{
unsigned char i;
TMOD=0x01;
ET0 = 1;
TR0 = 1;
TH0=0x00;
while(1)
{
  i++;                         //TH0 = 0;  // 正常运行时刻复位中断计时器
  if(i>0xff) i="0";
}
return;
}


我是菜鸟多多指教!




--  作者:deyun
--  发布时间:2004-7-1 21:18:00

--  

缺少EA=1; //  开中断




--  作者:孤湮直
--  发布时间:2004-7-2 10:36:00

--  

多谢指点,疏忽了,失败啊!


deyun老师,我将EA=1;添上后确实可以进入timer0中断,但是只能进入一次啊,当回到初始化后再往下运行,此时就不能进入timer0中断了(我在定时器处设置了断点,第二次全速运行后不能跳入),请问这是什么现象,是不是我那个地方又忘了啊!

em06.gif


--  作者:deyun
--  发布时间:2004-7-3 6:55:00

--  

这个问题我不好说,你监视断点,看看是不SP指针也恢复了,因为不同的编译器初始化代码不同,汇编要相应的修改一下,我的例子紧紧在Franklin C51 V3.96, Keil C51 6.02, Keil C51 7.01, Keil C51 7.06, 89C51, 89C2051, 8031下,不使用外部RAM变量下测试通过,在其他的环境和使用外部RAM及8052的扩展RAM被占用的情况RESET.ASM必须相应的修改。


再强调一下,复位程序一定是要复位到main()函数的第一条语句,如果不是,则说明reset.asm的代码必须相应的修改。


参考下面的例子:


# pragma OT(9)        // 这是声明编译器优化等级
#include<reg51.h>
alien void reset();   // 写上这一句


unsigned char f;


void timer0(void) interrupt 1 using 0
{
  // 在这里写检查某些数据是否合法的代码,如果不合法可以改写f变量控制复位后的程序流向。
  reset();
}



void initsys()
{
f=0xaa;       // 初始化标志,建议使用字节而不使用位
TMOD=0x01;
ET0 = 1;
TR0 = 1;
EA = 1;
// 可以写部分寄存器初始化的代码。
return;
}


// main program
void main(void)
{
if(f!=0xaa)initsys(); // 只有上电复位才初始化MCU,也可以根据标志字节内容选择程序流向。
while(1)TH0 = 0;
return;
}


// 代码没有调试,请自己验证




--  作者:孤湮直
--  发布时间:2004-7-3 10:49:00

--  

deyun老师你好,你说的很对。


我在WAVE下查看过SP指针,当进入MAIN()函数的第一行,SP=8,进入中断后SP=0X0A,当第一次软件复位后SP=8,继续运行,怎么都进不了中断。


当我用KEIL运行时,确实很好,没又WAVE的那个毛病,多谢耐心指教!




--  作者:deyun
--  发布时间:2004-7-4 7:32:00

--  
这说明wave做的比KEIL差,我一直在使用软件看门狗+陷阱技术(陷阱可以调用RESET程序,不过必须修改RETI为RET,当然也可以在函数中判断是中断调用还是陷阱调用而使用不同的返回指令),关于陷阱的技巧这里就不做探讨了。总之写好C51程序不和我们课本上说的那么简单。


--  作者:孤湮直
--  发布时间:2004-7-5 8:53:00

--  

很长见识啊,那个RETI变成ret?好像不对吧,因为这样又变成WAVE那样的情况了。



我原本使用WAVE的,主要是查看参数比较方便。现在一直在使用KEIL,主要是KEIL生成的代码据说很紧凑。



[此贴子已经被作者于2004-7-5 8:58:18编辑过]



--  作者:deyun
--  发布时间:2004-7-5 9:48:00

--  

中断调用使用RETI,陷阱调用使用RET




--  作者:孤湮直
--  发布时间:2004-7-5 10:47:00

--  

呵呵,明白了。多谢指教!


我是菜鸟,呵呵,是有些笨,不要见怪呀!

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
15
关闭 站长推荐上一条 /3 下一条