自己设计干扰,自己玩看门狗

本文分享了一段C51程序的编写经历,涉及软件抗干扰设计,包括指令冗余、陷阱捕获和软件看门狗等方法。通过模拟干扰信号测试程序的稳定性和复位能力,旨在提升单片机系统的鲁棒性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

        这,我忘了是什么时候写的程序了,好像是当初偶做学院的一个项目时遗留下来的小程序,当时,偶还不懂事,“乱搞”的一个程序,程序中,貌似很多错误哦,现在,由于偶要为电脑打扫卫生,虽然有BUG,可偶还是不想就这样把这程序删了,毕竟是自己的心血,所以决定把它记录下来,记录自己成长的路呵呵,让她成为一段美好的回忆吧!!!!!!

源程序:

=================================================================================================================

/*-------------------程序文档------------------------------------------------

程序功能:关于C51的软件抗干扰设计
用到的方法可能有:指令冗余技术,陷阱捕获,软
件看门狗等                                 
芯片:89C52, 引脚P2.0~P2.2分别控制LED0~LED2
P3.2为外部中断INT0,其中,LED0~LED2闪亮分别表
示单片机系统的主程序正常运行,低、高级中断正
常运行,INT0用于按键模拟干扰信号,使主程序受
干扰,亦即程序“跑飞”了,我们将通过软件的方法
让主程序程序复位(正常运行)

  MAKE BY AC   ALL RIGHT RESERVE!

  DATE 2011.04.11               
--------------------------------------------------------------------------------*/
 #include<reg52.h>
 #include<intrins.h>
 #define uchar unsigned char       //宏定义标识符
 #define uint unsigned int
 
 sbit LED0=P2^0;                          //定义指示灯
 sbit LED1=P2^1;
 sbit LED2=P2^2;
 //sbit RESET=?悲剧了,无法控制单片机的复位引脚
 //只好用嵌入汇编办法了(我不喜欢用goto语句)

void init(void);    //初始化函数声明
void reset(void);

uchar flag1,flag2,flag3;               //定义3个标志用于检测
 void main()
 {
 init();                                         //程序初始化函数
     
 while(1)
 {
  flag1=0;
  flag3=0;                                   //主程序监控T1
  LED0=0;
  LED0=1;
  flag2=0;                                 //看门狗(喂狗)
  _nop_();                                //指令冗余,是程序拉入正轨
  _nop_();
  if(flag1==1) while(1);             //死循环
  flag3=1;                                //主程序监控T1,置一表示程序没跑飞
 }
 
 }
 void init()                              //用于对中断的工作方式、初值的初始
 {                                           //化,这里用于测试使用定时器默认值
  TMOD=0X11;                     //设置T1,T0的工作方式为方式一
 PT1=1;                                //设置定时器T1为最高优先级(看门狗)  
 IT0=1;                                 //设置外部中断INT0为下降沿触发
 EX0=1;                               //允许外部中断0
 ET0=1;                               //定时器中断允许
 ET1=1;
 EA=1;                                //开总中断 
 TR0=1;                             //启动定时器
 TR1=1;
 }
 void intt0() interrupt 1
 {
  flag1=1;                         //用于模拟干扰
 }
 void timer0() interrupt 2
 {
   LED1=0;                        //实现闪烁
 LED1=1;
 if(flag3==0)                      //在主程序末应该置位,主程序控制T0
 {
 
  reset();                            //复位程序
                                         //其实可以用goto语句的
 } 
 if(flag2>3)     //T0控制T1
 {
    reset();                        //复位程序
                                        //其实可以用goto语句的
 }
 
 }
 void timer1() interrupt 4
 {
    LED2=0;                      //实现闪烁,T1控制程序模块
 LED2=1;
 
 }
void reset()
{
 #pragma asm
 CLR EA
 NOP                               //指令冗余,是程序拉入正轨
 NOP
 MOV A,#0
 MOV DPTR,#err
 PUSH DPL                    //8051系统采用大端存储系统   
 PUSH DPH                   //即高字节堆栈的高地址放低位
 NOP                             //指令冗余,是程序拉入正轨
 NOP
    RETI                         //低地址放高位,PUSH 后RETI弹出PC值使程序跳到err标号处
err:                                //同时,清除一次中断激活标志
 PUSH Acc  
 PUSH Acc
 NOP                             //指令冗余,是程序拉入正轨
 NOP
 RETI                            ////复位同时,又清除一次中断激活标志
 #pragma endasm

}
//编程总结:
/**************记录成长点滴,为自己的梦想而努力************/
//调试程序的时候,由于平时不注意啊,把外部中断0的关键标识符
//误写为外部中断函数的函数名即int0();结果,调试显示"code-ad
//dress expected"和"attempt define an already define",经改
//变函数明后改为intt0(),这两个错误消失了,可是还有两个"exp
//ression type does not match instruction",呵呵,按照以往的
//调试方法是双击调试信息利用注释符,屏蔽掉语句(例如://i=0;
//),再调试程序,如果再次DEBUG没有错误提示,则%90的可能是此
//部分语句有错误表,如果出现错误,则有可能是除此部分的语句出
//现错误,此时就要用"排除法或插入法"(我自己的专业术语)!!
//《所谓》的《插入法》是:在你认为是正常的程序中插入一些冗余
//的语句(这些语句最好是有助于你调试程序的语句,比如i=1;那么
//你可以根据i是否等于1来判断程序的运行状态(此种方法,经本人
//在之前写C语言和8086汇编语言程序时总结出来的,后来用到写51程
//序上同样适用))<<排除法>>亦即刚才我说的注释屏蔽语句法,所以
//此法又称为<<屏蔽法>>C51中可使用"//","/**/",在A51中则用";"对
//程序进行调试,当然,在keil4中(更高的版本,其兼容了三种注释方
//式)三种注释都可以用,呵呵!!
//双击"expression type does not match instruction"后,指示出是
//"PUSH A"这条语句出错了,这时候我用<<屏蔽法>>屏蔽所以的出错的语
//句结果编译通过,可是当我不屏蔽这些语句的时候编译会出错,这是为
//什么呢?提示的大概意思就是类型不匹配,经思量,A51中"PUSH,POP"要用
//直接寻址的,而PUSH A为寄存器寻址,所以程序出错,寄存器A的直接寻址
//为Acc,所以程序改为"PUSH Acc" 后,问题解决了!!!呵呵,编程是蛮有意思
//的哦,其中的乐趣,当事ren最有感觉!!!
/**************************************************************/
//哎呀,程序虽编译通过,可是,硬件调试的时候达不到自己的理想效果
//当我按下键触发"int0"中断后,LED2和LED0正常闪烁,可是LED1却灭了
//这说明主程序和T1中断程序时正常运行的,而T0定时器不能正常运行,这是
//为什么呢?想了很久,终于有头绪了,"难道T0的定时中断被屏蔽了?"
//yes,我的猜想正确,,,因为当两个定时器的中断标志都被激活的时候,那么对应的
//需要两条堆栈数据弹出指令,而要完成这个功能只能用"RETI"指令,,呵呵,,
//经过修改后:还是不行,后来,看了网上的一个看门狗的介绍说,复位时要关总中断
//呵呵,果真动手去调试了,,OK,,呵呵

=================================================================================================================

源程序结束鸟!!!!

   不希望“批评指责”,因为这是菜鸟之作,哈哈~~~~~~~~~~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值