这,我忘了是什么时候写的程序了,好像是当初偶做学院的一个项目时遗留下来的小程序,当时,偶还不懂事,“乱搞”的一个程序,程序中,貌似很多错误哦,现在,由于偶要为电脑打扫卫生,虽然有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,,呵呵
=================================================================================================================
源程序结束鸟!!!!
不希望“批评指责”,因为这是菜鸟之作,哈哈~~~~~~~~~~~~~