//实验5
#include "myclock.h"
//分别记录LED上的数字
unsigned char a[8]={0};
//当前显示的LED中内容在数组a中的偏移
unsigned char offset = 0;
//用于关闭高位0的显示
unsigned char flag = 3;
//表示计时器是否开始计时,0表示未开始,非0表示开始
unsigned char begin = 0;
//表示蜂鸣器是否工作,0表示不工作,非0表示工作
unsigned char sounding = 0;
//定时器1的计数器
unsigned char t1count = 0;
void main()
{
//设置定时器工作方式
TMOD = 0x11;
//设置外部中断1为跳沿触发
IT1 = 1;
//允许定时器中断和外部中断1
enable_int();
//启动定时器T0
runT0();
//等待中断
while(1);
}
//实现1ms刷新显示
void refresh() interrupt 1
{
//重置定时器T0
runT0();
//如果开始工作,则显示数字加1
if(begin)
{
inc_a();
//每过1秒,蜂鸣器响
if(sounding)
{
SOUND_OUT = 0;
t1count = 0;
runT1();
sounding = !sounding;
}
}
//显示数据
display();
++offset;
if(offset == 8)
offset = 0;
}
//INT按钮被按下时的中断处理函数
void press() interrupt 2
{
//切换机器工作状态
begin = !begin;
}
//实现持续200ms的蜂鸣
void sound() interrupt 3
{
//T1第4次溢出,关闭蜂鸣器
if(t1count == 3)
{
//蜂鸣器停止工作
SOUND_OUT = 1;
//T1停止工作
TR1 = 0;
}
else//否则T1溢出次数加1,重新启动T1
{
runT1();
++t1count;
}
}
//将数组中的一位显示在数码管上
void display()
{
unsigned char num = a[offset];
num = get_num(num);
//高位多余的0不显示
if(offset>flag)
num = 0;
//显示小数点
else if(offset == 3)
num |= NUM_DP;
//输出数据
dat_in(num);
//选择数码管
NUMLEDxOPEN(offset);
return;
}
//将十进制数转换成相对应的数码管输入
unsigned char get_num(unsigned char num)
{
switch(num)
{
case 0:return NUM_0;
case 1:return NUM_1;
case 2:return NUM_2;
case 3:return NUM_3;
case 4:return NUM_4;
case 5:return NUM_5;
case 6:return NUM_6;
case 7:return NUM_7;
case 8:return NUM_8;
case 9:return NUM_9;
default:return 0;
}
return 0;
}
//输出数据
void dat_in(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;++i)
{
SCK = 0;
if( (dat & 0x80) != 0)
SER = 1;
else
SER = 0;
dat <<= 1;
SCK = 1;
}
RCK = 1;
RCK = 0;
}
//计时数组数据加1
void inc_a()
{
unsigned char i;
++a[0];
for(i=1;i<8;++i)
{
if(a[i-1] == 10)
{
a[i-1] = 0;
++a[i];
//用于关闭高位多余0的显示
if(i>flag)
flag = i;
//每过1s打开蜂鸣器
if(i == 3)
sounding = !sounding;
}
}
if(flag<3)
flag = 3;
}
//选择打开的数码管
void NUMLEDxOPEN(unsigned char i)
{
switch(i)
{
case 0:NUMLED8OPEN();break;
case 1:NUMLED7OPEN();break;
case 2:NUMLED6OPEN();break;
case 3:NUMLED5OPEN();break;
case 4:NUMLED4OPEN();break;
case 5:NUMLED3OPEN();break;
case 6:NUMLED2OPEN();break;
case 7:NUMLED1OPEN();break;
}
}
//允许定时器中断和外部中断1,并设置中断优先级
void enable_int()
{
//允许定时器中断
ET0 = 1;
ET1 = 1;
//允许外部中断1
EX1 = 1;
//打开中断允许总开关
EA = 1;
//设置外部中断1的优先级高于T0,T1中断
PX1 = 1;
PT0 = 0;
PT1 = 0;
}
//启动定时器T0,定时时间为1ms
void runT0()
{
TL0 = 0x66;
TH0 = 0xFC;
TR0 = 1;
}
//启动定时器T1,定时时间为50ms
void runT1()
{
TL1 = 0xFE;
TH1 = 0x4B;
TR1 = 1;
}