电子时钟
预备知识:
数码管:
内部接线
C语言程序:
一、电子时钟
(一) 设计目的
通过电子时钟综合设计,使学生学会利用8051定时器时间计时处理功能,了解按键扫描及控制LED数码管显示原理,掌握单片机和按键以及LED数码管硬件电路设计及控制程序的设计方法。思考按键消除抖动、LED动态显示与静态显示的特点,从而提高学生解决实际问题的能力。
(二) 设计任务及要求
利用实验平台上4个LED数码管, 设计带有闹铃功能的数字时钟,要求:
1. 在4位数码管上显示当前时间。显示格式“时时分分”
2. 由LED闪动做秒显示。
3. 利用按键可对时间及闹玲进行设置,并可显示闹玲时间。当闹玲时间到蜂鸣器发出声响,按停止键使可使闹玲声停止。
(三)我采用的是TB-22766板子,单片机类型是STC89C52RC
(四)软件设计思想:
采用语言:C语言,主要中断:内部T0中断为唯一的中断,主程序大体分为两部分:无按键被按下时的显示,有按键被按下时,输入定时时间或者书输入当前时间,然后的显示软件,最后是一个蜂鸣器的控制程序。前面是三个子程序:两个按键扫描和一个延时小程序。
按键的扫描程序设置:
N
Y
N
具体的C语言程序:
/*---------------------------------------------------------------------------------------------------------------------
=======================================
基于JD51开发板的电子闹钟程序
=======================================
************************************程序功能说明************************************************************************
1、基础功能为计时,并显示当前时间。
2、秒表功能,按下key1键进入秒表模式,再次按下key3开始计时,再次按下key1停止,按下key1再次开始计时,按key4跳出秒表程序。
3、调时功能,按下key2进入调时模式,key3调小时,key4调分钟,key2确定并退出。
4、闹钟功能,按下key3进入闹钟设定模式,key3调小时,key4调分钟,key2确定并退出,当设定时间到达是,响铃,key3可以退出响铃。
5、观看当前具体时刻,按key4进入,观看当前秒数,约12s后自动退出。
Planed by LD.
************************************************************************************************************************/
#include "reg52.h"
//#include "delay.c"
#define uchar unsigned char
sbit CE573=P2^5; //
sbit BUZZER=P2^4;
sbit KEY1=P3^3;
sbit KEY2=P3^2;
sbit KEY3=P3^4;
sbit KEY4=P3^5;
sbit KEY5=P3^7;
code unsigned char digseg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
// 0 1 2 3 4 5 6 7 8 9 A b C d E F
code unsigned char segsel[]={0xfe,0xfd,0xfb,0xf7};
//数码管段选
int sum=0;
int s=30; //当前时间 秒
int mi=0; //当前时间 分
int h=0; //当前时间 时
int a;
int b;
int k;
int x,y,z,x1,x2;
int swt=1;
int swt2=1;
int min=1; //闹钟分
int hour=0; //闹钟时
int m=1; //设定初始参数
unsigned char beat;
code unsigned song[]={0x82,0x01,0x81,0x94,0x84,0xB4,0xA4,0x04,0x82,0x01,0x81,0x94,0x84,0xC4,0xB4,0x04,0x82,0x01,0x81,0xF4,0xD4,0xB4,
0xA4,0x94,0xE2,0x01,0xE1,0xD4,0xB4,0xC4,0xB4,0x04,0x82,0x01,0x81,0x94,0x84,0xB4,0xA4,0x04,0x82,0x01,0x81,0x94,
0x84,0xC4,0xB4,0x04,0x82,0x01,0x81,0xF4,0xD4,0xB4,0xA4,0x94,0xE2,0x01,0xE1,0xD4,0xB4,0xC4,0xB4,0x04,0x00};
code int note[]={0x0000,0xFB03,0xFB8E,0xFC0B,0xFC43,0xFCAB,0xFD08,0xFD32,0xFD81,0xFDC7,0xFE05,0xFE21,0xFE55,0xFE83,0xFE99,0xFEC0};
unsigned char hi_note,low_note;
void delay();
void initmpu(void) //初始化程序,确定计数器工作方式,装填工作数,确定确定终端模式。
{
TMOD=0x11; //定时器0和1 都以方式1计数
TL0=0xff;
TH0=0xdb;
TL1=0xFF;
TH1=0xDB;
PCON=0x00;
IE=0x8f; //开放所有中断
}
void Delay(int m)//延时程序
{
while(--m);
}
void Delay1(int m)//延时程序 用来播放音乐
{ int kk,jj;
for(;m>0;m--)
{ for(kk=180;kk>0;kk--)
for(jj=125;jj>0;jj--);}
}
void test_led(void)//测试led灯
{
int i;
P1=0x7F;
Delay(40000);
for(i=0;i<7;i++)
{
P1=P1>>1;
Delay(40000);
}
P1=0xFF;
Delay(40000);
P1=0x00;
Delay(40000);
P1=0xFF;
Delay(40000);
P1=0x00;
Delay(40000);
P1=0xFF;
}
void prt(int hour,int min)//数码管显示子程序
{
int a,b,c,d;
a=hour/10;
b=hour%10;
c=min/10;
d=min%10;
{//P2=0xfe;
P2=segsel[0];
P0=digseg[a];
Delay(100);
P2=segsel[1];
P0=digseg[b];
Delay(100);
P2=segsel[2];
P0=digseg[c];
Delay(100);
P2=segsel[3];
P0=digseg[d];
Delay(100);
}
}
void test_digseg(void)//测试数码管
{
char i,j;
CE573=1;
for(i=0;i<16;)
{
for(j=0;j<4;j++)
{
P2=segsel[j];
P0=digseg[i];
i++;
Delay(40000);
}
}
P2=0xF0; // 4只数码管同时开启
P0=0xFF;
Delay(40000);
P0=0x00;
Delay(40000);
P0=0xFF;
Delay(40000);
P0=0x00;
Delay(40000);
P0=0xFF;
}
void test_beep(char n) //测试蜂鸣器
{
char i;
for(i=0;i
{
BUZZER=0;
Delay(9000);
BUZZER=1;
Delay(9000);
}
}
char check_K3(void) // 按键去抖
{
if(KEY3==0)
{
Delay(2000);
{
if(KEY3==0)
{
return 1;
}
}
}
return 0;
}
char check_K4(void)//按键去抖
{
if(KEY4==0)
{
Delay(2000);
{
if(KEY4==0)
{
return 1;
}
}
}
return 0;
}
char key1_flag=0;
char key2_flag=0;
void ext_int0() interrupt 0 //外部中断0服务程序
{
EA = 0;
Delay(4000);
key1_flag=1;
EA = 1;
}
void ext_int1() interrupt 2 //外部中断1服务程序
{
EA = 0;
Delay(4000);
key2_flag=1;
EA = 1;
}
void time() interrupt 1//计时器0计数器中断程序,用于确定当前时间
{
EA=0;
x1++;
TR0=0;
swt=1;
TL0=0xff; //计数一百就是一秒
TH0=0xdb;
TR0=1;
if(x1==100)
{x1=0;
s++;
if(P1==0x7f) //LED闪烁表示一秒
P1=0xff;
else
P1=0x7f;
}
if(s==60)
{
s=0;
m=1;
mi++;
}
if(mi==60)
{
mi=0;
h++;
}
if(h==24)
h=0;
EA=1;
}
void time2() interrupt 3//计数器1中断程序,用于播放音乐
{
TR1=0;
TL1=low_note;
TH1=hi_note;
TR1=1;
BUZZER=~BUZZER;
}
void singing()
{
// unsigned char beat,temp;
unsigned char temp;
int ii=0;
while(1)
{
prt(h,mi); //显示当前时间
temp=song[ii]; // 读出乐谱的一个byte
if (temp==0)
{ // 如果是0就表示音乐结束
TR1=0; // 停止计时计数器1
return; // 返回
}
beat=temp&0x0f; //取出低阶的4位,这是拍子
temp=(temp>>4)&0x0f; //取出高阶4位当成音符的频率
if (temp==0)
TR1=0; //如果拍子是0就表示休止符
else {
hi_note=note[temp]>>8; //根据音符的频率得到Timer1计数值
low_note=note[temp]&0x00FF;
TR1=1; //启动计时计数器1
}
Delay1(beat); // 延迟拍子的时间
TR1=0; //计时器1停止计数
BUZZER=1;
ii++;
if(key2_flag) //按2键退出闹铃
{
key2_flag=0;
P2=0xff;
m=0;
TR1=0;
BUZZER=1;
break;
}
}
}
main()//主程序
{
initmpu();
test_beep(4);
test_led();
test_digseg();
P0=0XBF;
TR0=1; //计时器0开始工作
while(1) // 不断刷新程序
{
prt(h,mi); //显示当前时间
if(key1_flag) //以中断方式响应按键,秒表
{
key1_flag=0; //去除外部中断1标志位
P2=0xff;
test_beep(1); //驱动蜂鸣器
a=0;
b=0;
while(1) //不断刷新程序
{
prt(0,0);
if(check_K3())
{
P2=0xff;
break; //key3再次按下,开始计时
}
}
test_beep(1);
while(1)
{
if(swt&&swt2)
{
swt=0;
a++;
if(a==100)
{
a=0;
b++;
}
}
prt(b,a);
if(key1_flag==1)//key1再次按下停止计数
{
P2=0xff;
key1_flag=0;
test_beep(1);
swt2=0;
}
if(check_K3())//按下key3再次计数
{
P2=0xff;
key1_flag=0;
test_beep(1);
swt2=1;
}
if(check_K4())//按下key4跳出程序
{
P2=0xff;
Delay(8000);
test_beep(1);
break;
}
if(key2_flag==1)
{
key2_flag=0;
a=0;
b=0;
P2=0xff;
test_beep(1);
}
}
}
else if(key2_flag)//调整当前时间
{
P2=0xff;
key2_flag=0;
test_beep(3);
while(1)
{
prt(h,mi);
if(check_K3()) //调时
{
h++;
P2=0xff;
test_beep(1);
if(h==24)
h=0;
Delay(10000);
}
if(check_K4()) //调分
{
mi++;
P2=0xff;
test_beep(1);
if(mi==60)
{
mi=0;
h++;
}
if(h==24)
h=0;
Delay(10000);
}
if(key2_flag) //再按2键 退出调时
{
P2=0xff;
key2_flag=0;
test_beep(3);
Delay(10000);
break;
}
}
}
else if(check_K3())//设置闹钟时间
{
P2=0xff;
test_beep(3);
while(1)
{
prt(hour,min); //显示当前闹铃时间
if(check_K3())
{
P2=0xff;
hour++;
test_beep(1);
if(hour==24)
hour=0;
Delay(10000);
}
else if(check_K4())
{
P2=0xff;
min++;
test_beep(1);
if(min==60)
{
min=0;
hour++;
}
if(hour==24)
hour=0;
Delay(10000);
}
if(key2_flag) //按2键退出
{
key2_flag=0;
P2=0xff;
test_beep(5);
Delay(10000);
break;
}
}
}
else if(check_K4())//观看当前秒单位
{
test_beep(1);
k=3000;
while(k--)
{
prt(0,s);
P1=0;
}
P1=0xff;
}
if((h==hour)&&(min==mi))//响铃
{
while(m)
{
singing();
}
}
}
}总结:虽然这个C语言程序比较容易理解,但是运行的速度对比汇编语言比较慢,汇编语言直接和内存打交道,所以比较直接,我们如果想更加深入地去理解其内存中数据变化,还需要深入学习汇编语言的知识,我明白现在只是一个起步,前方的路还很长,我会更加努力好好学习,丰富自己的知识,最后使得自己成长,这样我也就很快乐了,路漫漫其修远兮,吾将上下而求索!还有老师辛苦了,一期一会,祝您幸福!
本文来源:https://www.2haoxitong.net/k/doc/071b76465f0e7cd18425365e.html
文档为doc格式