新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于單片機(jī)的液晶日歷時鐘

基于單片機(jī)的液晶日歷時鐘

作者: 時間:2016-11-18 來源:網(wǎng)絡(luò) 收藏
一、簡介

本設(shè)計利用單片機(jī)AT89S52和1602液晶,實現(xiàn)日歷(年月日)、星期和時間的顯示。具體效果為:

本文引用地址:http://m.butianyuan.cn/article/201611/315864.htm

2011-11-11 FRI

11:11:11

二、設(shè)計圖紙

1、電路原理

2、PCB圖

3、三維模型

三、相關(guān)程序

程序簡介:程序啟動后,先初始化液晶和兩個定時器,時鐘開始工作,再進(jìn)入掃描檢測調(diào)整時鐘函數(shù)中,根據(jù)是否有KEY1長按來決定是否調(diào)整時鐘。定時器T0用來產(chǎn)生時鐘計時,T1用來中斷顯示液晶,按鍵KEY1為多功能按鍵,在時鐘工作時,長按時進(jìn)入時鐘調(diào)整,依次調(diào)整年、月、日、星期、時、分,KEY2和KEY3分別為上下調(diào)整,每次調(diào)整完畢后短按KEY1返回,進(jìn)入下一個調(diào)整。

1、主程序文件

#include "reg51.h"
#include "adjust.h"
#include "lcm.h"
#include "key.h"
//定時器初始化函數(shù)
void Timer_Start()
{
TMOD=0x11;
TH1=0xfc;
TL1=0x18;
TH0=0xfc;
TL0=0x60;
EA=1;
ET1=1;
ET0=1;
TR1=1;
TR0=1;
}
//主函數(shù)
void main()
{
unsigned char Key_Code;
//初始化LCM
LCM_START();
//初始化定時器
Timer_Start();
while(1)
{
Key_Code=Key_Scan();
switch(Key_Code)
{
case Key_M:Adjust();break;
default:break;
}
}
}

2、延時程序文件

(1)頭文件

#ifndef __DELAY_H__
#define __DELAY_H__
extern void Delay_ms(unsigned int ms);
#endif

(2)程序文件

#include "delay.h"

//延時1毫秒函數(shù)
void Delay_ms(unsigned int ms)
{
unsigned char Temp;
while(ms--)
for(Temp=0;Temp<120;Temp++);
}

2、時鐘程序文件

(1)頭文件

#ifndef __CLOCK_H__
#define __CLOCK_H__
extern unsigned int Second_Count;
extern char Second;
extern char Minute;
extern char Hour;
extern char Day;
extern char Month;
extern int Year;
extern char Week;
extern char Month_Day[12];
extern bit Leap_Year(int Temp_Year);
#endif

(2)程序文件

#include "reg51.h"
//秒計數(shù)變量
unsigned int Second_Count=0;
//時分秒變量
char Second=53;
char Minute=20;
char Hour =5;
char Day =18;
char Month =4;
int Year =2011;
char Week =1;
//每月天數(shù)數(shù)組
char Month_Day[12]={31,28,31,30,31,30,31,31,30,31,30,31};

//閏年判斷函數(shù)
bit Leap_Year(int Temp_Year)
{
bit Temp;
if(((Temp_Year%4==0)&&(Temp_Year%100!=0))||(Temp_Year%400==0))
{
Temp=1;
}
else
{
Temp=0;
}
return Temp;
}
//定時器0中斷服務(wù)函數(shù)
void Timer0_Serve()interrupt 1
{
TH0=0xfc;
TL0=0x60;
Second_Count++;
if(Second_Count>1000)
{
Second_Count=0;
Second++;
if(Second>=60)
{
Second=0;
Minute++;
if(Minute>=60)
{
Minute=0;
Hour++;
if(Hour>=24)
{
Hour=0;
Week++;if(Week>=7)Week=0;
Day++;
if(Day>Month_Day[Month-1])
{
if((Month!=2)||(!Leap_Year(Year))||(Day>29))
{
Day=1;
Month++;
if(Month>12)
{
Month=1;
Year++;
}
}
}
}
}
}
}
}

3、液晶程序文件

(1)頭文件

#ifndef __LCM_SHOW_H__
#define __LCM_SHOW_H__
extern void LCM_START();
extern void LCM_CMD (unsigned char Temp_Data);
extern void LCM_DATA(unsigned char Temp_Data);
extern void LCM_POS (unsigned char Temp_Data);
#endif

(2)程序

#include "reg51.h"
#include "delay.h"
#include "intrins.h"
//LCM控制端口定義
sbit RS=P2^5;//數(shù)據(jù)/命令選擇端口
sbit RW=P2^6;//讀寫控制端口
sbit EN=P2^7;//使能端口

//定義商標(biāo)字符
char code Logo1[]="WELCOME TO";
char code Logo2[]="MY MCU WORKSHOP!";

//LCM狀態(tài)讀取函數(shù)
bit LCM_Status()
{
bit Temp_Status;
RS=0;
RW=1;
EN=1;
_nop_();
Temp_Status=(bit)(P0&0x80);
_nop_();
EN=0;
return Temp_Status;
}
//LCM寫初始化命令函數(shù)
void LCM_INIT(unsigned char Temp_Data)
{
RS=0;
RW=0;
EN=0;
_nop_();
P0=Temp_Data;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
}
//LCM寫命令函數(shù)
void LCM_CMD(unsigned char Temp_Data)
{
while(LCM_Status());
RS=0;
RW=0;
EN=0;
_nop_();
P0=Temp_Data;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
}
//LCM寫數(shù)據(jù)函數(shù)
void LCM_DATA(unsigned char Temp_Data)
{
while(LCM_Status());
RS=1;
RW=0;
EN=0;
_nop_();
P0=Temp_Data;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
}
//LCM顯示位置設(shè)定函數(shù)
void LCM_POS(unsigned char Temp_Data)
{
LCM_CMD(Temp_Data|0x80);
}
//LCM初始化函數(shù)
void LCM_START()
{
unsigned char Temp;
//寫初始化指令三次但不檢測忙信號
LCM_INIT(0x38);
Delay_ms(5);
LCM_INIT(0x38);
Delay_ms(5);
LCM_INIT(0x38);
Delay_ms(5);
//寫初始化命令字
LCM_CMD(0x38);
Delay_ms(1);
//寫清屏命令字
LCM_CMD(0x01);
Delay_ms(1);
//寫地址指針及光標(biāo)自動移位命令字
LCM_CMD(0x06);
Delay_ms(1);
//寫開顯示命令字
LCM_CMD(0x0c);
Delay_ms(1);

Temp=0;
//設(shè)定顯示位置為第行4列
LCM_POS(0x03);
Delay_ms(1);
//顯示Logo第一行
while(Logo1[Temp]!=