|
我买的51单片机,想写一个程序,让他计时,并在还剩30秒时和结束时提醒(蜂鸣器响,是有源蜂鸣器),
但是在还剩30秒时,不想,在结束时能响,请问这是为什么啊?
下面是源程序,都是比较简单的语言,蜂鸣器部分用红色标出。
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
//申明变量和位口
sbit K1=P3^4; //对应按钮K1
sbit K2=P3^5; //对应按钮K2
sbit dula=P2^6; //段选申明
sbit wela=P2^7; //位选申明
sbit beep=P2^3; //蜂鸣器申明
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0~9,A~F的16进制
void delayms(unsigned int xms); //延时函数申明
unsigned char numt0=0,miao=0,fen=0,lunci=0; // 计数变量
unsigned char CK1=0,CK2=0; //串口接收变量(全局)
//延时函数
void delayms(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=112;j>0;j--);
}
//计时器初始化函数
void init()
{
//********计时器**********
TMOD=0x21; //模式设置,00100001,可见采用的是定时器0,工作与模式1(M1=0,M0=1)。
TR0=0; //不打开定时器
TH0=(65536-46080)/256;// 由于晶振为11.0592,故所记次数应为46080,计时器每隔50000微秒发起一次中断。
TL0=(65536-46080)%256;//46080的来历,为50000*11.0592/12
ET0=1; //开定时器0中断
EA=1; //开总中断
//***************串口通信**********************
TMOD=0X21; ////模式设置,00100001,可见采用的是定时器1,工作与模式1(M1=0,M0=1)
SCON=0X50; //设置为工作方式1
PCON=0X00; //0x00不加倍 0x80加倍
TH1=0XFD; //计数器初始值设置,注意波特率是4800的
TL1=0XF3D;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
//数码管显示函数
void display(uchar fen1,uchar miao1)
{
//*******分钟操作*********
unsigned char fenshi,fenge;
unsigned char miaoshi,miaoge;
fenshi=fen1/10;
fenge=fen1%10;
dula=1; //秒钟十位赋值
P0=table[fenshi];
dula=0;
P0=0xff;
wela=1;
P0=0xF7;
wela=0;
delayms(5);
dula=1; //分钟十位赋值
P0=table[fenge];
dula=0;
P0=0xff;
wela=1;
P0=0xEF;
wela=0;
delayms(5);
//********中间的一个横线*****
dula=1;
P0=0x40;
dula=0; //打开段选位 .....秒钟个位赋值......关闭闭段选位
P0=0xff; //送段选数据前关闭所有所有显示,防止打开位选锁存器
wela=1;
P0=0xFB;
wela=0; //打开段选位 、赋值、关闭闭段选位
delayms(5);
//*******秒钟操作*********
miaoshi = miao1/10;
miaoge = miao1%10; //参数处理
dula=1;
P0=table[miaoshi];
dula=0; //打开段选位 .....秒钟个位赋值......关闭闭段选位
P0=0xff; //送段选数据前关闭所有所有显示,防止打开位选锁存器
wela=1;
P0=0xFE;
wela=0; //打开段选位 、赋值、关闭闭段选位
delayms(5);
dula=1; //秒钟十位赋值
P0=table[miaoge];
dula=0;
P0=0xff;
wela=1;
P0=0xFD;
wela=0;
delayms(5);
}
//判断按键函数
unsigned char keyscan()
{
unsigned char keyValue = 0; //保存键值
if (K1==0) //检测按键K1是否按下
{
delayms(10); //消除抖动
if (K1==0) //再次检测按键是否按下
{
TR0=~TR0; //启动或开始计时器******一开始时,这个按键按下去后才会启动
while(!K1); //等待按键释放
}
}
if (K2==0) //检测按键K1是否按下
{
delayms(10); //消除抖动
if (K2==0) //再次检测按键是否按下
{
miao=0;
fen=0; //清零
lunci=0; //清零同时,判别变量清零
while(!K2); //等待按键释放
}
}
return keyValue; //将读取到键值的值返回
}
//开始次一轮函数
void NextTurn ( unsigned char fenstop)
{
unsigned char m1;
m1=fenstop;
if(m1==CK1) //当计时满CK1分钟时开始下一轮次
{
if (lunci==0) //再次检测按键是否按下
{
miao=0;
fen=0; //清零
lunci=1; //计次符号加1
}
}
}
//定时停止函数
void stop ( unsigned char fenstop)
{
unsigned char m1;
m1=fenstop;
if(m1==CK2) //当计时满CK2分钟时计时停止(第二次记满时)
{
if (lunci==1) //再次检测按键是否按下
{
TR0=0; //计时器停止
lunci=0; //判别变量清零
}
}
}
//蜂鸣器函数---提醒
void FengMing1(unsigned char CK11,unsigned char CK22) //蜂鸣器为无源蜂鸣器,需要变频才能发声
{
if((fen==CK11-1)&&(lunci==0)||(fen==CK22-1)&&(lunci==1)) //4分钟的时候响
{
if((miao>30)&&(miao<33)) //分钟的时候响
beep = 0;
else
beep= 1;
}
}
//蜂鸣器函数---终止
void FengMing2(unsigned char CK11,unsigned char CK22) //蜂鸣器为无源蜂鸣器,需要变频才能发声
{
if((fen==CK11-1)&&(lunci==0)||(fen==CK22-1)&&(lunci==1)) //4分钟的时候响
{
if((miao>56)&&(miao<59)) //4分钟的时候响
beep = 0;
else
beep = 1;
}
}
//主函数
void main()
{
init();//初始化函数
while(1)
{
keyscan();
display(miao,fen); //传递给秒表
NextTurn(fen);
stop(fen); //调用停止函数
FengMing1(CK1,CK2); //调用蜂鸣器提醒函数
FengMing2(CK1,CK2); //调用蜂鸣器提醒函数
}
}
//计时器中断函数
void time0() interrupt 1
{
TH0=(65536-46080)/256;// 由于晶振为11.0592,故所记次数应为46080,计时器每隔50000微秒发起一次中断。
TL0=(65536-46080)%256;//46080的来历,为50000*11.0592/12
numt0++;
if(numt0==20) //如果到了20次,说明1秒时间到
{
numt0=0; //然后把num清0重新再计20次
miao++;
if(miao==60)
{
miao=0;
fen++; //分钟计时器开始计时
if(fen==60)
fen=0;
}
}
}
//串口中断函数
void Usart() interrupt 4
{
unsigned char receiveData;
receiveData=SBUF; //出去接收到的数据
CK1=receiveData/16; //赋值给全局变量
CK2=receiveData%16;
if ((CK1*16+CK2)==receiveData)
SBUF=6; //将接收到的数据放入到发送寄存器
RI = 0; //清除接收中断标志位
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
|
|