51单片机C语言简单程序问题请教:

输入:“jq1”,输出:“jq1kg”“dcf1”。
要求:(1) jq1按下后,jq1kg=0延时1ms后dcf1=0。
(2) jq1松开后,jq1kg=1延时6.53s后dcf1=1。
(3) 如果jq1松开后还不到6.53s又按下,则回到第一步的状态。
(4) jq1在任何时候按下都回到第一步状态。
下面是我写的程序,虽然可以做到jq1在任何时候按下都回到第一步状态,但是jq1松开后有的时候还不到6.53s,dcf1就=1了,希望能帮我把程序改一下。或者重新写一个也行。谢谢了。
/***************************************************************************************************/
#include "at89x51.h"
//IN
#define jq1 P1_0
//OUT
#define jq1kg P0_0
#define dcf1 P2_0

bit t_flag,t1_flag;
int m,n,nut;
unsigned char num;

/*****************延***时***程****序*************************************************/

void delay(int x)//1MS延时程序
{
unsigned char a,b,c;
for(c=x;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);

}
/****************定**时**器**初**始**化********************************************/
void T0init() // 定时器中断计数 初始化
{
TMOD=0X01;
TH0=(65536-65535)/256;
TL0=(65536-65535)%256;
ET0=1;
EA=1;
}

/*****************自***动***程****序*************************************************/
void auto_sub()
{
T0init();
if(jq1==0)
{
t1_flag=0;
jq1kg=0;
delay(1);
dcf1=0;
while(jq1==1&&t1_flag==0)
{ jq1kg=1; TR0=1;
if(t_flag==1&&jq1==1)
{
dcf1=1;
TR0=0;
t_flag=0;
t1_flag=1;
}
}
}

}

/*************主***程***序**********************************************/
void main()
{
while(1)
{
if(jq1==0)
auto_sub();
}
}

/*************定***时***器***中***断***计***数*********************/
void T0server() interrupt 1 //定时器中断计数
{
TH0=(65536-65535)/256; //定时65.3ms给高八位
TL0=(65536-65535)%256; //定时65.3ms给低八位
num++;
if(num==100) //65.3ms*100=6.53s
{
num=0;
t_flag=1; //时间到了的标志位
}
}

由于看不到硬件电路,以下以推测为前提。
首次:没有看到按键去抖动程序。这是不合理的,按键的识别是需要去抖动的。机械式按键,或者说机械式的开关都需要去抖动的程序。通过硬件的方法当然可以去抖动,但是如果想程序稳定可靠,这个还是不能少的。
其次:定时器初始化程序缺少相关的变量的初始化,num可能没有被清零。如果按键抖动被程序认为是多次真正的按键,这就很可怕了。比如某一次抖动启动了定时器,可是不符合下一条if语句,程序直接跳出了。但是下一次符合if语句的情况发生时,num已经不是0了。这次的结果就有可能造成了你所描述的情况。
总的来说,想法的大思路是可以的,但是要注意细节。比如:定时器初始化位置不对,这条语句不应该在这个位置,它应该在按键按下处理的语句之后,前面加判断while(XXX),括号内的请自己思考。定时器的寄存器赋值不应该存在计算,这会给你的延时时间计算造成很大的麻烦。其他的细节就不多说了。
这样过的程序写法对于初学者来说,是可以的。但是如果你想把这个东西做好,做到稳定可靠的运行,不能这样写。这样的程序,只能是“有时候好用”,换个说法就是“有时候不好用”。具体该怎么做,就是你需要去学习的。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-12-06
稍做改动如下,试试看:
void auto_sub()
{
T0init();
if(jq1 == 0) {
t1_flag = 0;
jq1kg = 0;
delay(1);
dcf1 = 0;
while (jq1 == 0); //等待jq1释放
TR0 = 1;
jq1kg = 1;
while (t_flag == 0 && jq1 == 1); //等待时间到或者jq1按下
if (t_flag == 1) { //如果是时间到了
dcf1 = 1;
TR0 = 0;
t_flag = 0;
t1_flag = 1;
}
//如果不是时间到了,那就是jq1按下,结束本函数
}
}
相似回答