📄 clock.c
字号:
/************************************************************************************/
/* 程序名:多功能时钟 */
/* 晶振: 12M 单片机型号:AT89S51 */
/* 作者: 邓波 李杰 苏昆 */
/* 功能描述:本开发板P0口接数码管的段选,P2口接数码管的位选,四个按键调节控制 */
/* 本程序具有时钟,闹钟,年月日功能,均可以调节,而且还能够整点报时功能 */
/* 说明:P3的4,5,6,7口连接键盘,有一列线接地。P1_0连接蜂鸣器。 */
/* 时间:2007年4月5号 */
/* 地点:湖南科大 */
/************************************************************************************/
#include<reg51.h>
#define _TH0_TL0_ (65536 - 50000)
#define HI (_TH0_TL0_ / 256) //给高8位赋值3C
#define LO (_TH0_TL0_ % 256) //给低8位赋值B0
#define M 20 //(1000/50)1秒要50个中断的累计
sbit P1_0=P1^0; //定义位变量
sbit P2_0 = P2 ^ 0;
sbit P2_1 = P2 ^ 1;
sbit P2_2 = P2 ^ 2;
sbit P2_3 = P2 ^ 3;
sbit P2_4 = P2 ^ 4;
sbit P2_5 = P2 ^ 5;
sbit P2_6 = P2 ^ 6;
sbit P2_7 = P2 ^ 7;
sbit P3_4 = P3 ^ 4;
sbit P3_5 = P3 ^ 5;
sbit P3_6 = P3 ^ 6;
sbit P3_7 = P3 ^ 7;
#define BEEP_on P1_0=0; //蜂鸣器蜂鸣,可以整点报时,可以闹钟
#define BEEP_off P1_0=1;
struct Time{
unsigned char hour;
unsigned char min;
unsigned char sec;
}clock={12,58,50};
struct calendar{
unsigned int year;
unsigned char month;
unsigned char day;
}rili={1997,04,03};
struct alarm{
unsigned char shi;
unsigned char fen;
unsigned char miao;
}naozhong={12,40,00};
unsigned char SEG_TAB1[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};//0-9数字
unsigned char SEG_TAB2[] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};//0.-9.数字
unsigned char Led[6];
unsigned char tt[8];
/*********************************************************************************************/
void Delay(unsigned char a) //延时程序
{
unsigned char j;
while(--a != 0)
{
for (j = 0; j < 125; j++);
}
}
/*********************************************************************************************/
void Disp1(void) //数码管显示时钟模块
{
P2_0 = 0; //第一个数码管显示时的十位
Led[0] = clock.hour / 10;
P0 = SEG_TAB1[Led[0]];
Delay(2);
P2_0= 1;
P2_1 = 0; //第2个数码管显示时的个位
Led[1] = clock.hour % 10;
P0 = SEG_TAB1[Led[1]];
Delay(2);
P2_1 = 1;
P2_2=0;P0=0xbf;Delay(4);P2_2=1;
P2_3= 0; //第4个数码管显示分的十位
Led[2] = clock.min / 10;
P0 = SEG_TAB1[Led[2]];
Delay(2);
P2_3= 1;
P2_4 = 0; //第5个数码管显示分的个位
Led[3] = clock.min % 10;
P0 = SEG_TAB1[Led[3]];
Delay(2);
P2_4 = 1;
P2_5=0;P0=0xbf;Delay(4);P2_5=1;
P2_6 = 0; //第7个数码管显示秒的十位
Led[4] = clock.sec / 10;
P0 = SEG_TAB1[Led[4]];
Delay(2);
P2_6 = 1;
P2_7 = 0; //第8个数码管显示秒的个位。
Led[5] = clock.sec % 10;
P0 = SEG_TAB1[Led[5]];
Delay(2);
P2_7= 1;
if(clock.sec==0&&clock.min==0) //增加整点报时功能,
{
BEEP_on;
Delay(100);
BEEP_off;
}
}
void Disp2(void) //数码管显示日历模块
{
P2_7=0; //后两个数码管显示日期
tt[0]=rili.day%10;
P0 = SEG_TAB1[tt[0]];
Delay(4);
P2_7=1;
P2_6=0;
tt[1]=rili.day/10;
P0 = SEG_TAB1[tt[1]];
Delay(4);
P2_6=1;
P2_5=0; //中间两个数码管显示月份
tt[2]=rili.month%10;
P0 = SEG_TAB2[tt[2]];
Delay(4);
P2_5=1;
P2_4=0;
tt[3]=rili.month/10;
P0 = SEG_TAB1[tt[3]];
Delay(4);
P2_4=1;
P2_3=0; //前四个数码管显示年
tt[4]=rili.year%10;
P0 = SEG_TAB2[tt[4]];
Delay(4);
P2_3=1;
P2_2=0;
tt[5]=rili.year/10%10;
P0 = SEG_TAB1[tt[5]];
Delay(4);
P2_2=1;
P2_1=0;
tt[6]=rili.year/100%10;
P0 = SEG_TAB1[tt[6]];
Delay(4);
P2_1=1;
P2_0=0;
tt[7]=rili.year/1000%10;
P0 = SEG_TAB1[tt[7]];
Delay(4);
P2_0=1;
}
void Disp3(void) //数码管显示闹钟模块
{
P2_0 = 0; //第一个数码管显示闹钟时的个位
Led[0] = naozhong.shi / 10;
P0 = SEG_TAB1[Led[0]];
Delay(3);
P2_0= 1;
P2_1 = 0;//第2个数码管显示闹钟时的十位
Led[1] = naozhong.shi % 10;
P0 = SEG_TAB1[Led[1]];
Delay(3);
P2_1 = 1;
P2_2=0;P0=0xbf;Delay(4);P2_2=1;
P2_3= 0;//第4个数码管显示闹钟分的个位
Led[2] = naozhong.fen / 10;
P0 = SEG_TAB1[Led[2]];
Delay(3);
P2_3= 1;
P2_4 = 0;//第5个数码管显示闹钟分的十位
Led[3] = naozhong.fen % 10;
P0 = SEG_TAB1[Led[3]];
Delay(3);
P2_4 = 1;
P2_5=0;P0=0xbf;Delay(5);P2_5=1;
P2_6 = 0;//第7个数码管显示闹钟秒的个位
Led[4] = naozhong.miao / 10;
P0 = SEG_TAB1[Led[4]];
Delay(3);
P2_6 = 1;
P2_7 = 0;//第8个数码管显示闹钟秒的十位。
Led[5] =naozhong.miao % 10;
P0 = SEG_TAB1[Led[5]];
Delay(3);
P2_7= 1;
}
/********************************************************************************************/
void IsrTimer0(void) interrupt 1 using 1 //定时器0中断服务程序
{
static unsigned char count = 0; //定义静态变量count
TR0 = 0; //以下调整出栈入栈的时间误差
TL0 += (_TH0_TL0_ + 9) % 256;
TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY;
TR0 = 1;
count++;
if(count == M) //1秒种时间到
{
count = 0;
clock.sec++;
if( clock.sec == 60) //1分钟时间到
{
clock.min++;
clock.sec = 0;
if( clock.min == 60) //1小时时间到
{
clock.hour++;
clock.min = 0;
if( clock.hour == 24) //24小时时间到
{
clock.hour = 0;
clock.min = 0;
clock.sec = 0;
rili.day++;
if(rili.day==31) //一天
{
rili.month++;
rili.day=0;
if(rili.month==13) //一月
{
rili.year++;
rili.month=0;
}
}
}
}
}
}
}
/**********************************************************************************/
int keypressed1() //键盘调节时间函数
{
if(P3_4 == 0)
{
Delay(50);
if(P3_4 == 0)
clock.sec ++;
}
if(P3_5 == 0)
{
Delay(50);
if(P3_5 == 0)
clock.min ++;
}
if(P3_6 == 0)
{
Delay(50);
if(P3_6 == 0)
clock.hour ++;
}
if(clock.sec ==60) clock.sec =0;
if(clock.min==60) clock.min =0;
if(clock.hour==24) clock.hour =0;
}
int keypressed2() //键盘调节日期函数
{
if(P3_4 == 0)
{
Delay(50);
if(P3_4 == 0)
rili.day ++;
}
if(P3_5 == 0)
{
Delay(50);
if(P3_5 == 0)
rili.month ++;
}
if(P3_6 == 0)
{
Delay(50);
if(P3_6 == 0)
rili.year ++;
}
if(rili.day ==31) rili.day =1;
if(rili.month==13) rili.month =1;
if(rili.year==2031) rili.year =1997;
}
int keypressed3() //键盘调节闹钟时间函数
{
if(P3_4 == 0)
{
Delay(50);
if(P3_4 == 0)
naozhong.miao++;
}
if(P3_5 == 0)
{
Delay(50);
if(P3_5 == 0)
naozhong.fen++;
}
if(P3_6 == 0)
{
Delay(50);
if(P3_6 == 0)
naozhong.shi++;
}
if(naozhong.miao==60) naozhong.miao=0;
if(naozhong.fen==60) naozhong.fen=0;
if(naozhong.shi==24) naozhong.shi=0;
}
/********************************************************************************/
void Timer0Init(void) //初始化定时器0程序
{
TMOD = 0x01; //设置模式1 定时器0 工作方式0
TH0 = HI; //给TH0,TL0赋初始值
TL0 = LO;
TR0 = 1; //启动定时器0
ET0 = 1; //定时器中断开
EA = 1; //总中断开
}
void main(void)
{
int j=0,r=0;
Timer0Init();
while(1)
{
if(P3_7 == 0)
{
Delay(20);
if(P3_7 == 0)
r++; //按键被按下次数
if(r==6) r=0;
if(r<2) j=0;
if(r>=2&&r<=3)j=1 ; //考虑到硬件不稳定,让每按两次才实现模块转换功能
if(r<6&&r>4)j=2;}
switch(j)
{
case 0:Disp1();
keypressed1();break;
case 1:Disp3();
keypressed3();break;
case 2:Disp2();
keypressed2();break;
default:break;
}
if(clock.sec==naozhong.miao&&clock.min==naozhong.fen&&clock.hour==naozhong.shi)
{ //闹钟和时钟时间相同,闹铃
BEEP_on;
Delay(100);
BEEP_off;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -