题 目: 电子时钟(LCD)显示
班 级: 0310405班 学 号:
学生姓名: 张 金 龙
指导老师: 高 林
2013年 6 月 17 日
一、 实验内容:
以AT89C51单片机为核心的时钟,在LCD显示器上显示当前的时间: 使用字符型LCD显示器显示当前时间。 显示格式为“时时:分分:秒秒”。
用4个功能键操作来设置当前时间,4个功能键接在~引脚上。 功能键K1~K4功能如下。 K1—进入设置现在的时间。 K2—设置小时。 K3—设置分钟。 K4—确认完成设置。
程序执行后工作指示灯LED闪动,表示程序开始执行,LCD显示“00:00:00”,然后开始计时。
二、实验电路及功能说明
1) 单片机主控制模块
以AT89C51单片机为核心进行一系列控制。 2) 时钟显示模块
用1602为LCD显示模块,把对应的引脚和最小系统上的引脚相连,连接后用初始化程序对其进行简单的功能测试。测试成功后即可为实验所用,如图:
3) 时间调整电路
用4个功能键操作来设置当前时间,4个功能键接在~引脚上。 功能键K1~K4功能如下。K1—进入设置现在的时间。 K2—设置小时。K3—设置分钟。
K4—确认完成设置。如图:
三、实验程序流程图:
主程序:
时 钟 主 程 序 流 程 子程序:
保护现场 设置计数初1S到 (40H)+1 N (40H)=10 (46H)+1 N (46H)=4 N (47H)=2 0 (0) (47H) (46H)+1 (46H) 0 (40H) (41H)+1 (41H)=5 0 (41H) N 恢复现场 (43H)+1 N 返回 (43H)=10 (46H)=10 0 (43H) (44H)+1 N (44H)=5 0 (44H) 0 (46H) (47)+1 中 断 服 务 流 程 图 四、实验结果分析
实验结果及分析:单片机的晶振可以根据要求设定。6MHZ为和现实时间显示相同。实验采用12MHZ晶振采用方式1定时,选取50ms采用20次中断达到一秒,采用查表方式控制LCD显示。当烧入程序后开始运行,根据初始值设定可以观察到显示的时间,这里为了更明显观察显示数据变化把起始值设为 23:59:50 运行后显示
,K1为进入现在设置时间,当按下K1后显示, 和实验要求相比较,实现了按下K1进入现在时间设
置,按下K4确认完成时间设置的功能;不同之处: 当进入时间设置时在按下K1设置小时,再次按下K1是设置分钟。增加功能:进入时间设置并选择设置位置后K2键位数字增加功能,K3键为数字减小功能。根据仿真结果能够确定编程正确,基本实现了所有功能,而且有所改进。
五、心得体会
每次做单片机实验都会有不同的等收获,而这次的实验让我感觉收获更大。这次的实验让我巩固了以往所学,而且锻炼了自己发现问题解决问题的能力。在编程过程,发现自己对C语言很生疏,很多技巧和函数运用都不会,通过参考资料和询问同学终于让我完成了程序,并实现了程序的功能。这不仅提高了自己动手能力,也培养了自己的思考能力。
这次在编程过程中学到了很多新东西,特别是LCD的显示,在设定的显示字符后,正确编译后显示各种设定值,LCD显示16位字符,在最初编程时编译正确但是LCD上的显示字符有缺失,显示不完整,经过不断调试发现空格同样占据字符,只有所有字符不超过16位且位置正确时才能完整正确显示。时间的显示需要每一个显示的位子有定义,而且要给“:”留下特定位子。同时编程时发现还可以显示其他如日期。但本实验不需要且很难完成最终没实现。
在仿真过程中发现许多模型不知道名称,最后搜索了一份Proteus 元件库,里边有很多元件模型的名称。最后搭建成功了仿真模型,并且运行成功。
在这里要感谢老师在以往实验过程中不厌其烦的帮助自己解决所遇到的问题和传授一些知识和小窍门。让我对单片机有机会加深了解,体会到了单片机的强大,学到了很多,感谢。
六、程序清单
#include <> #include <>
#define uchar unsigned char #define uint unsigned int
#define DelayNOP() {_nop_();_nop_();_nop_();_nop_();} sbit K1 =P1^0; 表示修改分
uchar MilliSecond,Hour =23,Minute=59, Second =50; //延时函数 void DelayMS(uint x) {
uchar i; while(x--)
for(i=0;i<120;i++); }
//LCD忙状态检测 bit LCD_Busy_Check()
{
bit result;
RS = 0;RW = 1;E = 1;DelayNOP();result = (bit)(P0 & 0x80);E = 0; return result; } //写LCD命令
void LCD_Write_Command(uchar cmd) {
while(LCD_Busy_Check());//判断LCD是否忙碌
RS = 0;RW = 0;E = 0;_nop_();_nop_();P0 = cmd; DelayNOP(); E = 1;DelayNOP();E = 0; } //设置LCD显示位置 void LCD_Set_Pos(uchar pos) {
LCD_Write_Command(pos | 0x80); }
//写LCD数据
void LCD_Write_Data(uchar dat) {
while(LCD_Busy_Check());//判断LCD是否忙碌
RS = 1;RW = 0;E = 0; P0 = dat; DelayNOP(); E = 1;DelayNOP();E = 0; } //LCD初始化 void LCD_Initialize() {
LCD_Write_Command(0x38);DelayMS(1); LCD_Write_Command(0x0c);DelayMS(1); LCD_Write_Command(0x06);DelayMS(1); LCD_Write_Command(0x01);DelayMS(1); }
// 显示函数,在LCD指定的行上显示字符串 void Display_String(uchar*str,uchar LineNo) { uchar k;
LCD_Set_Pos(LineNo);
for(k=0;k<16;k++) LCD_Write_Data(str[k]); }
//时分秒显示
void Display_HMS(uchar h,m,s) {
if(Settime) HMS_String[3] = '>';//显示修改标志 else HMS_String[3] = ' '; //不显示修改标志
HMS_String[4] = h/10 + '0'; //时十位 HMS_String[5] = h/10 + '0'; HMS_String[5] = h%10 + '0'; //时个位 HMS_String[5] = h%10 + '0'; HMS_String[7] = m/10 + '0'; //分 HMS_String[8] = m/10 + '0'; HMS_String[8] = m%10 + '0'; //分 HMS_String[8] = m%10 + '0'; HMS_String[10]= s/10 + '0'; //秒 HMS_String[11]= s/10 + '0';
HMS_String[11]= s%10 + '0'; //秒 HMS_String[11]= s%10 + '0'; Display_String(HMS_String,0x40); }
//设置时间
void Change_Time() {
Settime=0;
if(K1==0) //按下k1键即进入修改状态 { TR0 = 0;
Display_String(Str2,0x00); //第一行提示修改时间 Settime = 1; }
while (Settime) {
if(K1 == 0) //确定调整小时还是分钟 {
while(K1 == 0)
Change_H_or_M = !Change_H_or_M; }
else if(K2 == 0) //增加 {
while(K2 == 0); if(Change_H_or_M==1) {
if(++Hour == 24) Hour = 0; } else
{if(++Minute == 60) Minute = 0;} }
else if(K3 == 0) //减少 {
while(K3 == 0); if(Change_H_or_M == 1)
{if(--Hour == 0xff) Hour = 23;} else
{if(--Minute == 0xff) Minute = 59;} }
else if(K4 == 0) //确定 {
while(K4 == 0);
Display_String(Str1,0x00); //第一行还原显示str1 Settime = 0; TR0 = 1;
}
Display_HMS(Hour,Minute,Second);
} //外层While在这里结束 }
//定时器0中断
void Time0() interrupt 1 {
TH0 = (65536 -50000)/256;
TL0 = (65536 -50000)%256; // if(++MilliSecond == 20) //50*20=1s {
MilliSecond = 0;
if(++Second == 60) { Second = 0; if(++Minute == 60)
{ Minute = 0; if(++Hour == 24) { Hour = 0;Minute = 0;Second = 0; }
重新装入50MS定时 } } } } //主函数 void main() {
TMOD = 0x01;
TH0 = (65536-50000)/256; TL0 = (65536-50000)%256; IE = 0x82; SPK = 0;
LCD_Initialize();
Display_String(Str1,0x00); // TR0 = 1; P1 = 0xFF; while(1) {
Display_HMS(Hour,Minute,Second); // DelayMS(500);
Change_Time(); //}
第一行显示 第二行显示时分秒 显示过程中允许修改时间 }
因篇幅问题不能全部显示,请点此查看更多更全内容