基于AT89C52单片机的电子时钟(LCD)的设计摘要:单片机因将其主要组成部分集成在一个芯片上而得名,就是把中 央 处理器、随机存储器、只读存储器、中断系统、定时器/计数器以及 I/O 接口电 路等部件集成在一个芯片上。 基于单片机设计的数字钟精确度较高, 因为在程序的执行过程中, 任何指 令都不影响定时器的正常计数,即便程序很长也不会影响中断的时间。数字钟是采用数字电路实现对日期、时、分、秒,数字显示的计时装置,由 于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远 超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表的报时功能。 数字钟已成为人们日常生活中的必需品,广泛应用于家庭、车站、码头、剧院、办公室等场所,给人们的生活、学习、工作带来极大的方便。 不仅如此,在现代化的进程中,也离不开电子钟的相关功能和原理,比如机械手 的控制、家务的自动化、定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自 动启用等,所有这些,都是以钟表数字化为基础的。而且是控制的核心部分。因 此,研究数字钟及扩大其应用,有着非常现实的意义。 本设计使用 12MHZ 晶振与单片机 AT89C52 相连接,以 AT89C52 芯片为核心, 采用动态扫描方式显示,通过使用该单片机,通过 4 个按键进行调时、复位等功能,在实现各功能时LCD进行相应显示。软件部分用 C 语言实现,分为显示、延迟、调时、复位等部分。通过软硬件结合达到最终目的。 关键词:电子时钟 AT89C52单片机 LCD1602显示屏 定时中断
第一章 设计任务与要求
1.1内容以AT89C52单片机为核心的时钟,在LCD显示器上显示当前的时间。 1.2要求l 使用字符型LCD显示器显示当前时间。 l 显示格式为“时时:分分:秒秒”。 l 用4个功能键操作来设置当前时间。 功能键K1~K4功能如下: l K1—进入设置现在的时间。 l K2—设置小时。 l K3—设置分钟。 l K4—确认完成设置。 程序执行后工作指示灯LED闪动,表示程序开始执行,LCD显示“00:00:00”,然后开始计时。 l 拓展功能:实现整时提示,在08:00---20:00进行提示3秒,在其他的时间段不会提示。 1.3单片机系统运行流程程序首先进行初始化,在主程序的循环程序中首先调用数据处理程 序,然后调用显示程序,在判断是否有按键按下。启动仿真,若按下按键1,可发现LED停止闪烁,按下按键2和按键3后,可改变时间,按下按键4后,时钟复位到修改时间。
附录:源代码#include<reg52.h> #define uchar unsigned char #define uint unsigned int #define KEY_IO P3 #define LCD_IO P0
sbit LCD_RS = P2^0; sbit LCD_RW = P2^1; sbit LCD_EN = P2^2;
sbit SPK = P1^2;//定义蜂鸣器 sbit LED = P2^4;//定义LED
bit new_s, modify = 0; char t0, sec = 50, min = 59, hour = 07;
char code LCD_line1[] = " a wonderful day "; char code LCD_line2[] = " Time: 00:00:00 "; char Timer_buf[] = "00:00:00";
void delay(uint z)//延时函数 { uint x, y; for(x = z; x > 0; x--) for(y = 100; y > 0; y--); }
void W_LCD_Com(uchar com) //写指令 { LCD_RS = 0; LCD_IO = com; //RS和RW都为低电平,写入指令 LCD_EN = 1; //用EN输入一个高脉冲 delay(5); LCD_EN = 0; }
void W_LCD_Dat(uchar dat) //写数据 { LCD_RS = 1; LCD_IO = dat; //RS为高电平和RW为低电平,写入数据 LCD_EN = 1; //用EN输入一个高脉冲 delay(5); LCD_EN = 0; }
void W_LCD_STR(uchar *s) //写字符串 { while(*s) W_LCD_Dat(*s++); }
void W_BUFF(void) //时、分、秒显示 { Timer_buf[7] = sec % 10 + 48; Timer_buf[6] = sec / 10 + 48;
Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;
Timer_buf[1] = hour % 10 + 48; Timer_buf[0] = hour / 10 + 48;
W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf); } uchar read_key(void) { uchar x1, x2; KEY_IO = 255; x1 = KEY_IO; if (x1 != 255) { delay(100); x2 = KEY_IO; if (x1 != x2) return 255; while(x2 != 255) x2 = KEY_IO; if (x1 == 0x7f) return 0; else if (x1 == 0xbf) return 1; else if (x1 == 0xdf) return 2; else if (x1 == 0xef) return 3; else if (x1 == 0xf7) return 4; } return 255; }
void Init() { LCD_RW = 0; W_LCD_Com(0x38); delay(50); W_LCD_Com(0x0c); W_LCD_Com(0x06); W_LCD_Com(0x01); W_LCD_Com(0x80); W_LCD_STR(LCD_line1); W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);
TMOD = 0x01; //T0定时方式1 TH0 = 0x4c; TR0 = 1; //启动T0 ET0 = 1; EA = 1; }
void main() { uint i, j; uchar Key; Init(); while(1) {
if (new_s) { //出现新的一秒,修改时间 new_s = 0; sec++; sec %= 60; if(!sec) { min++; min %= 60; if(!min) { hour++; hour %= 24;} } W_BUFF();
if (!min) {if(hour>=8&&hour<=20&&sec<=3)//当在08:00—20:00之间整点报时 for (i = 0; i < 200;i++) { SPK = 0; for (j = 0; j< 100; j++); SPK = 1; for (j = 0; j< 100; j++); } } }
Key = read_key(); //读按键 switch(Key) { case 0: modify = 1; break;//修改键 case 1: if(modify) {min++; min %= 60; W_BUFF(); break;} case 2: if(modify) {hour++; hour %= 24; W_BUFF();break;} case 3: modify = 0; break;//确认键 } } } void timer0(void) interrupt 1 //T0中断,50MS执行一次 { TH0 = 0x4c; t0++; t0 %= 20; if(t0 == 0) //20,一秒 {new_s = 1; LED = ~LED;} if(modify) LED = 0; }
|