最近做了个红外线报警器,用开关S来代替红外传感器。要求用数码管记录报警次数,若没有外部中断,则10s后自动关闭蜂鸣器,但是中断可以关闭,但定时不管用为什么呢,这是我的程序
#include <reg51.h>
sbit INTO_1=P3^2; //外部中断
sbit LED_1 = P3^0;
sbit LED_2 = P1^2;
sbit BEEP= P1^7; //蜂鸣器
sbit BaoJing = P1^0; //报警器,低电平有效
//sbit Disdata = P2;
#define uint unsigned int
#define uchar unsigned char
#define Disdata P2 //数码管输入
uchar code dis_7[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//共阴LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
uchar flag=0; //外中断跳出循环标志
uchar t=0; //延时的辅助循环次数
uchar i=0; //记录报警次数的
/***********************************************************************/
void DelayMs() //蜂鸣器延时
{
uchar n=10;
while(n--);
}
void Delay(uint t)
{
uint n=500;
for(;t>0;t--)
{
for(;n>0;n--);
}
}
/********************************************************/
void play() //蜂鸣器运行,10s自动返回,靠定时器中断
{
flag=1;
t=0;
TMOD=0X01;
TH0=0X3c;
TL0=0XB0;
TR0=1;
BEEP=0;
while((flag==1)&&(t<200))
{
BEEP=~BEEP;
}
TR0=0;
}
void INT_TMR (void) interrupt 1 //定时器中断服务子程xu
{
TH0=0X3c;
TL0=0XB0;
t++;
if(200==t)
{
LED_1=1;
LED_2=1;
}
}
void INT_EXT(void) interrupt 0 //外中断服务子程序,管蜂鸣器,关LED 灯
{
LED_1=1;
LED_2=1;
flag=0;
}
void main()
{
EA=1;
ET0=1;
EX0=1;
Disdata = dis_7[0]; //初始化数码管
while(1)
{
//BaoJing = 0;
while(!BaoJing)
{
i++;
Disdata=dis_7[i];
LED_1=0;
LED_2=0;
play();
BaoJing=1;
}
Delay(10);
}
}
------解决思路----------------------
定时器只初始化一次,你怎么把定时器的初始化放到while循环里了,一直初始化定时器。。。
------解决思路----------------------
我没有用过这款单片机,具体timer的设置我不清楚。但是我还是有三个疑问?第一,为什么你的play函数都要初始化一次timer,这是必须的么?能不能将timer的初始化放到main开始处?第二, 定时中断的t++。要知道你并没有对t做判断,t会一直增加,到了255后又会从0开始增加,如此循环。所以,你的while((flag==1)&&(t<200))隔一段时间(你这里估计是2.5s)又会满足条件了;第三,就算程序其他地方能满足你的设想,BEEP在play退出后的电平是未知的啊!
------解决思路----------------------
你逻辑确实很混乱。通常的做法是,条件满足(你这里是有按键按下)就设置标志位(你的flag);条件不满足了(你这里10s已经满了,)清除标志位。main的主循环根据这个标志位来决定是否执行你的play函数。如果系统负荷比较重,在设置标记的时候打开定时器,清除标记的时候关闭定时器。