/********************************************************
项目名称:数字时钟
程序功能:实现时钟、闹钟等功能
设计团队:
创建时间:
硬件环境:
**********************************************************/
/*编译预处理*/
#include<stc15.h> //
#include<intrins.h>
/*宏定义*/
#define uint unsigned int //
#define uchar unsigned char
/*端口定义*/
sbit HC595_RCLK=P4^2;
sbit HC595_SRCLK=P4^1;
sbit HC595_SER=P4^0;
sbit key_up=P1^0; //四个独立按键的控制引脚
sbit key_left=P1^1;
sbit key_right=P1^2;
sbit key_down=P1^3;
sbit buzzer=P3^7;
sbit LED=P0^0;
/*外部变量的定义/数码管的段选和位选编码*/
uchar code led_duan[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,0x80 ,0x90,0xbf};
uchar code led_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar hour=21,min=11,sec=55; //外部变量定义了时分秒
uchar hour_clock=21,min_clock=12; //外部变量定义了闹钟的时分
uchar temp,display_mode; //temp用来记录进入中断的次数,display_mode记录显示模式
/*子函数申明*/
void system_init();
void send_HC595(uchar dat); //向74HC595发送数据函数
void display(uchar weima,uchar duanma); //数码管显示驱动函数
void delay_ms(uint t); //3ms延时子
void key_scan(); //扫描按键并修改对应的值
void display_scan();
/*主函数*/
void main()
{
system_init(); //调用初始化函数
buzzer=0;
while(1) //大循环的同时等待定时计数器中断
{
key_scan(); //调用按键扫描函数
display_scan(); //调用数码管显示函数
LED=0;
}
}
/*初始化函数*/
void system_init()
{
display_mode=0;temp=0;
P0M0=0;P0M1=0; // I/O口的初始化
P1M0=0;P1M1=0;
P3M0=0;P3M1=0;
P4M0=0;P4M1=0;
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x68; //设置定时初始值
TH0 = 0xC5; //设置定时初始值
TF0 = 0; //清除TF0标志
ET0=1;
EA=1;
TR0=1; //定时器0开始计时
}
/*向74HC595发送数据函数*/
void send_HC595(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
dat<<=1;
HC595_SER=CY;
HC595_SRCLK=1;
HC595_SRCLK=0;
}
}
//数码管显示函数
void display(uchar weima,uchar duanma)
{
send_HC595(led_wei[weima]);
send_HC595(led_duan[duanma]);
HC595_RCLK=1;
HC595_RCLK=0;
}
//数码管动态扫描驱动函数
void display_scan()
{
switch(display_mode)
{
case 0:{ //正常显示模式
display(0,hour/10) ;
delay_ms(2);
display(1,hour%10) ;
delay_ms(2);
display(2,10) ;
delay_ms(2);
display(3,min/10) ;
delay_ms(2);
display(4,min%10) ;
delay_ms(2);
display(5,10) ;
delay_ms(2);
display(6,sec/10) ;
delay_ms(2);
display(7,sec%10) ;
delay_ms(2);
}
case 1:{ //修改小时模式
if(temp<10)
{
display(0,hour/10) ;
delay_ms(2);
display(1,hour%10) ;
delay_ms(2);
}
display(2,10) ;
delay_ms(2);
display(3,min/10) ;
delay_ms(2);
display(4,min%10) ;
delay_ms(2);
display(5,10) ;
delay_ms(2);
display(6,sec/10) ;
delay_ms(2);
display(7,sec%10) ;
delay_ms(2);
}
case 2:{ //修改分钟模式
display(0,hour/10) ;
delay_ms(2);
display(1,hour%10) ;
delay_ms(2);
display(2,10) ;
delay_ms(2);
if(temp<10)
{
display(3,min/10) ;
delay_ms(2);
display(4,min%10) ;
delay_ms(2);
}
display(5,10) ;
delay_ms(2);
display(6,sec/10) ;
delay_ms(2);
display(7,sec%10) ;
delay_ms(2);
}
case 3:{ //修改闹钟小时模式
if(temp<10)
{
display(0,hour_clock/10) ;
delay_ms(2);
display(1,hour_clock%10) ;
delay_ms(2);
}
display(2,10) ;
delay_ms(2);
display(3,min_clock/10) ;
delay_ms(2);
display(4,min_clock%10) ;
delay_ms(2);
}
case 4:{ //修改闹钟分钟模式
display(0,hour_clock/10) ;
delay_ms(2);
display(1,hour_clock%10) ;
delay_ms(2);
display(2,10) ;
delay_ms(2);
if(temp<10)
{
display(3,min_clock/10) ;
delay_ms(2);
display(4,min_clock%10) ;
delay_ms(2);
}
}
}
}
void key_scan()
{
if(key_left==0)
{
display_scan(); //调用ms级延时函数,目的是消除抖动
if(key_left==0) //按键进行模式切换
{
display_mode++; //模式加1 ,在0-4之间循环
if (display_mode==5)
display_mode=0;
}
while(!key_left)
display_scan();//等待按键释放
}
if(display_mode!=0)
{
switch(display_mode)
{
case 1: //模式1--调时
{
if(key_up==0)
{
display_scan(); //延时去抖
if(key_up==0) //上键按下小时加一并判断溢出
{
if(hour<23) hour++;
else hour=0;
}
while(!key_up) display_scan(); //等待按键释放
}
if(key_down==0)
{
display_scan(); //延时去抖
if(key_down==0) //上键按下小时加一并判断溢出
{
if(hour>0) hour--;
else hour=23;
}
while(!key_down) display_scan(); //等待按键释放
}
} break;
case 2: {
if(key_up==0)
{
display_scan(); //延时去抖
if(key_up==0) //上键按下分钟加一并判断溢出
{
if(min<59) min++;
else min=0;
}
while(!key_up) display_scan(); //等待按键释放
}
if(key_down==0)
{
display_scan(); //延时去抖
if(key_down==0) //上键按下分钟加一并判断溢出
{
if(min>0) min--;
else hour=59;
}
while(!key_down) display_scan(); //等待按键释放
}
}break;
case 3:
{
if(key_up==0)
{
display_scan(); //延时去抖
if(key_up==0) //上键按下小时加一并判断溢出
{
if(hour_clock<23) hour_clock++;
else hour_clock=0;
}
while(!key_up) display_scan(); //等待按键释放
}
if(key_down==0)
{
display_scan(); //延时去抖
if(key_down==0) //上键按下小时加一并判断溢出
{
if(hour_clock>0) hour_clock--;
else hour_clock=23;
}
while(!key_down) display_scan(); //等待按键释放
}
} break;
case 4: {
if(key_up==0)
{
display_scan(); //延时去抖
if(key_up==0) //上键按下分钟加一并判断溢出
{
if(min_clock<59) min_clock++;
else min_clock=0;
}
while(!key_up) display_scan(); //等待按键释放
}
if(key_down==0)
{
display_scan(); //延时去抖
if(key_down==0) //上键按下分钟加一并判断溢出
{
if(min_clock>0) min_clock--;
else min_clock=59;
}
while(!key_down) display_scan(); //等待按键释放
}
}break;
}
}
}
void time0() interrupt 1 //定时器中断函数
{
temp++; //变量temp用来控制定时次数,配合定时器定时1s
if(temp==20)
{
temp=0;
sec++; //变量sec储存秒钟数据
}
if(sec==60)
{
sec=0;
min++; //判断秒钟、分钟和小时不溢出
}
if(min==60)
{
min=0;
hour++; //判断秒钟、分钟和小时不溢出
}
if(hour==24) hour=0;
//变量hour和min储存小时和分钟数据
//变量hour1和min1储存闹钟的小时和分钟数据,
if(((hour_clock==hour)&&(min_clock==min)&&(sec<5)) )
{
buzzer=1; //闹钟时间到了后满足条件控制蜂鸣器响
}
else
buzzer=0;
}
/*ms级延时子函数*/
void delay_ms(uint t) //@11.0592MHz
{
while(t--)
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);