/********************************************************
**這個程序是時鐘程序用lcm12832作為顯示.
**p1口作為鍵盤輸入p1.0=增加鍵;p11為選擇鍵
**時鐘顯示格式為:“時:分:秒”字體為16*16點陣
**修改方式為兩鍵式選擇鍵合修改鍵
**還可顯示萬年歷:“年:月:日”
**需要子函數(shù):
** 1、hex->bcd子函數(shù)hex_bcd()
** 2、顯示子函數(shù)display()
** 3、鍵盤子函數(shù)key()
** 4、時鐘子函數(shù)time()
** 5、日歷子函數(shù)day()
** 6、顯示控制子函數(shù)discommond()
** 7、定時器中斷0 time0()
** 8、初始化子函數(shù) begin().
** 9、初始屏顯display_begin().
** 10、時間屏顯display_time().
** 11、潤年判斷l(xiāng)eapf().
**現(xiàn)有問題:鍵盤修改程序還未完成
** 程序不夠精簡
*********************************************************/
#include<reg51.h>
#define time_th 0x3c; // time0 :50ms 12m
#define time_tl 0xba;
unsigned char data msecond=0;
bit data second_flag=0,day_flag=0,leap=0,display_flag=0,ku_flag;
unsigned char day_temp;
struct time_str{
unsigned char hour;
unsigned char minute;
unsigned char second;
}time_now;
struct day_str{
unsigned int year;
unsigned char month;
unsigned char day;
}day_now;
//顯示緩沖區(qū)
unsigned char data display_bcd[13];
//每月天數(shù)表
unsigned char code day_num[]=
{31,28,31,30,31,30,31,31,30,31,30,31};
//時間顯示位置表
unsigned char code time_loc[][1]=
{0,2,0,3,0,4,0,5,0,8,0,9,0,12,0,13
,16,4,16,5,16,8,16,9,16,12,16,13};
//漢字顯示位置表
//指定位置顯示“年,月,日,時,分,秒”
unsigned char code zhi_loc[]=
{0x06,0x01,0x0a,0x01,0x0e,0x01,0x06,0x10,0x0a,0x10,0x0e,0x10};
/********************************************************************
**字庫開始
**********************************************************************/
unsigned char code shi[]={
/*-- 文字: 年 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=16x16 --*/
0x08,0x00,0x0f,0xfc,0x10,0x80,0x10,0x80,0x20,0x80,0x4f,0xf8,0x88,0x80,0x08,0x80,
0x08,0x80,0x08,0x80,0xff,0xfe,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,
/*-- 文字: 月 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=16x16 --*/
0x07,0xf0,0x04,0x10,0x04,0x10,0x04,0x10,0x07,0xf0,0x04,0x10,0x04,0x10,0x04,0x10,
0x07,0xf0,0x04,0x10,0x08,0x10,0x08,0x10,0x10,0x10,0x20,0x50,0x40,0x20,0x00,0x00,
/*-- 文字: 日 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=16x16 --*/
0x00,0x00,0x1f,0xf0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1f,0xf0,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1f,0xf0,0x10,0x10,0x00,0x00,0x00,0x00,
/*-- 文字: 時 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=16x16 --*/
0x00,0x10,0x00,0x10,0x7c,0x10,0x44,0x10,0x47,0xfe,0x44,0x10,0x7c,0x10,0x45,0x10,
0x44,0x90,0x44,0x90,0x7c,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x50,0x00,0x20,
/*-- 文字: 分 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=16x16 --*/
0x08,0x80,0x0c,0x80,0x08,0x40,0x10,0x20,0x10,0x30,0x20,0x18,0x40,0x0e,0x9f,0xe4,
0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x08,0x20,0x10,0xa0,0x20,0x40,0x40,0x00,
/*-- 文字: 秒 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=16x16 --*/
0x0c,0x20,0xf0,0x20,0x10,0x20,0x11,0x28,0xfd,0xa4,0x11,0x22,0x32,0x22,0x3a,0x20,
0x54,0x22,0x54,0x22,0x90,0x04,0x10,0x08,0x10,0x10,0x10,0x60,0x11,0x80,0x16,0x00};
unsigned char code num[]={
/*-- 文字: 0 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,
/*-- 文字: 1 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00,
/*-- 文字: 2 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,
/*-- 文字: 3 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x3c,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
/*-- 文字: 4 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x04,0x0c,0x14,0x24,0x24,0x44,0x44,0x7e,0x04,0x04,0x1e,0x00,0x00,
/*-- 文字: 5 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x7e,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
/*-- 文字: 6 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x1c,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00,
/*-- 文字: 7 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x7e,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
/*-- 文字: 8 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3c,0x00,0x00,
/*-- 文字: 9 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1a,0x02,0x02,0x24,0x38,0x00,0x00,
/*-- 文字: 0 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xe7,0xdb,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xdb,0xe7,0xff,0xff,
/*-- 文字: 1 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xef,0x8f,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0x83,0xff,0xff,
/*-- 文字: 2 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xc3,0xbd,0xbd,0xbd,0xfb,0xfb,0xf7,0xef,0xdf,0xbd,0x81,0xff,0xff,
/*-- 文字: 3 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xc3,0xbd,0xbd,0xfb,0xe7,0xfb,0xfd,0xfd,0xbd,0xbb,0xc7,0xff,0xff,
/*-- 文字: 4 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xfb,0xf3,0xeb,0xdb,0xdb,0xbb,0xbb,0x81,0xfb,0xfb,0xe1,0xff,0xff,
/*-- 文字: 5 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0x81,0xbf,0xbf,0xbf,0xa7,0x9b,0xfd,0xfd,0xbd,0xbb,0xc7,0xff,0xff,
/*-- 文字: 6 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xe3,0xdb,0xbf,0xbf,0xa7,0x9b,0xbd,0xbd,0xbd,0xdb,0xe7,0xff,0xff,
/*-- 文字: 7 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0x81,0xbb,0xbb,0xf7,0xf7,0xef,0xef,0xef,0xef,0xef,0xef,0xff,0xff,
/*-- 文字: 8 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xc3,0xbd,0xbd,0xbd,0xdb,0xe7,0xdb,0xbd,0xbd,0xbd,0xc3,0xff,0xff,
/*-- 文字: 9 --*/
/*-- 宋體12; 此字體下對應的點陣為:寬x高=8x16 --*/
0xff,0xff,0xff,0xe7,0xdb,0xbd,0xbd,0xbd,0xd9,0xe5,0xfd,0xfd,0xdb,0xc7,0xff,0xff,
};
unsigned char code ku[]={
/*-- 調(diào)入了一幅圖像:這是哭的的圖像 --*/
/*-- 寬度x高度=16x16 --*/
0x03,0xc0,0x0c,0x30,0x10,0x08,0x20,0x04,0x40,0x02,0x52,0x4a,0x8c,0x31,0x80,0x01,
0x80,0x01,0x81,0x81,0x42,0x42,0x44,0x22,0x20,0x04,0x10,0x08,0x0c,0x30,0x03,0xc0,
/*-- 調(diào)入了一幅圖像:這是笑的的圖像 --*/
/*-- 寬度x高度=16x16 --*/
0x03,0xc0,0x0c,0x30,0x10,0x08,0x20,0x04,0x40,0x02,0x40,0x02,0x8c,0x31,0x92,0x49,
0x80,0x01,0x80,0x01,0x44,0x22,0x42,0x42,0x21,0x84,0x10,0x08,0x0c,0x30,0x03,0xc0
};
/*****************************************************************************
**字庫結束
******************************************************************************/
void day();
void time();
void begin();
void display(unsigned char *cpoint,unsigned char x_line,unsigned char y_line,unsigned char s_l);
unsigned char hex_bcd(unsigned char hex);
void display_begin();
void display_time(struct time_str time,struct day_str day);
bit leapf(unsigned int year);
void main()
{
begin();
display_begin();
while (1)
{
while (1)
{
time();
day();
if (display_flag)
{
display_flag=0;
display_time(time_now,day_now);
}
if (display_flag)
continue;
if((day_now.month==2)&leap)
{
leap=0;
day_temp=29;
}
}
}
}
/******************************************************
**time()子函數(shù)
**參數(shù):second_flay
**
******************************************************/
void time(){
if(second_flag){
display_flag=1;
second_flag=0;
// day_flag=1;
time_now.second++;
if(time_now.second==60){
time_now.second=0;
time_now.minute++;
if(time_now.minute==60){
time_now.minute=0;
time_now.hour++;
if(time_now.hour==24){
time_now.hour=0;
day_flag=1;
}
}
}
}
}
/*********************************************************
**day()子函數(shù)
**參數(shù):day_flag日標志;leap潤年標志
**
**********************************************************/
void day(){
if(day_flag){
day_flag=0;
day_now.day++;
if(day_now.day==day_temp+1){
day_now.month++;
if((day_now.month==2)&leap){
leap=0;
day_temp=29;
}
else day_temp=day_num[day_now.month-1];
day_now.day=1;
if(day_now.month==13){
day_now.month=1;
day_temp=day_num[day_now.month-1];
day_now.year++;
leap=leapf(day_now.year);
}
}
}
}
/****************************************************************
**begin()子函數(shù)系統(tǒng)參數(shù)初始化
**
****************************************************************/
void begin(){
//定時器0初始化
tmod=0x21; //50ms int 12m
th0=0x3c;
tl0=0xba;
tr0=1;
ie=0x92;
scon|=0x40;
//狀態(tài)標志位初始化
//參量初始化
time_now.second=0;
time_now.minute=0;
time_now.hour=0;
day_now.year=1980;
day_now.month=6;
day_now.day=27;
leap=leapf(day_now.year);
day_temp=day_num[day_now.month-1];
}
/****************************************************************
**display()子函數(shù)
**參數(shù)說明:*cpoint:要顯示的字符地址指針
** x_line:橫軸坐標(1-16)
** y_line:縱軸坐標(1-16)
** s_l: 1為8*16字體;2為16*16字體
**返回值:無
****************************************************************/
void display(unsigned char *cpoint,unsigned char x_line,unsigned char y_line,unsigned char s_l){
unsigned char xdata *xpoint;
unsigned char i,j;
xpoint=0x8000+x_line+y_line*16;
for(i=0;i<16;i++){
for(j=0;j<s_l;j++){
*xpoint=*cpoint;
cpoint++;
xpoint++;
}
xpoint=xpoint+16-s_l;
}
}
/****************************************************************
**display_begin()子函數(shù)顯示屏幕的初始值如:
** —————————
** | 1980年09月05日|
** | 23時03分09秒|
** —————————
**調(diào)用函數(shù):display()
** display_time()
**
****************************************************************/
//指定位置顯示“年,月,日,時,分,秒”
//unsigned char code zhi_loc[]=
//{0x06,0x01,0x0a,0x01,0x0e,0x01,0x06,0x10,0x0a,0x10,0x0e,0x10};
void display_begin(){
unsigned char x_display,y_display,i,j=0;
unsigned char code *p_display;
p_display=&shi;
for (i=0;i<6;i++){
x_display=zhi_loc[j];
j++;
y_display=zhi_loc[j];
j++;
display(p_display,x_display,y_display,2);
p_display=p_display+32;
}
//指定位置顯示時間
display_time(time_now,day_now);
}
/****************************************************************
** display_time()顯示時間子函數(shù)
** 參數(shù):struct time_str time
** struct day_str day
** 返回值:無
** 調(diào)用函數(shù):display()
** hex_bcd()
****************************************************************/
void display_time(struct time_str time,struct day_str day){
unsigned char temp,temp1,temp_year,temp_x,temp_y;
unsigned char *temp_p;
//顯示哭笑符
if (ku_flag)temp_p=(&ku)+32;
else temp_p=&ku;
temp_x=0;
temp_y=16;
ku_flag=!ku_flag;
display(temp_p,temp_x,temp_y,2);
//顯示秒
temp=time.second;
temp=hex_bcd(temp);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=13;
temp_y=16;
display(temp_p,temp_x,temp_y,1);
temp_x=12;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
//顯示分
temp=time.minute;
temp=hex_bcd(temp);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=9;
temp_y=16;
display(temp_p,temp_x,temp_y,1);
temp_x=8;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
//顯示時
temp=time.hour;
temp=hex_bcd(temp);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=5;
temp_y=16;
display(temp_p,temp_x,temp_y,1);
temp_x=4;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
//顯示日
temp=day.day;
temp=hex_bcd(temp);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=13;
temp_y=0;
display(temp_p,temp_x,temp_y,1);
temp_x=12;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
//顯示月
temp=day.month;
temp=hex_bcd(temp);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=9;
temp_y=0;
display(temp_p,temp_x,temp_y,1);
temp_x=8;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
//顯示年
temp_year=day.year/100;
temp=day.year%100;
temp=hex_bcd(temp);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=5;
temp_y=0;
display(temp_p,temp_x,temp_y,1);
temp_x=4;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
//顯示年高位
temp=hex_bcd(temp_year);
temp1=temp>>4;
temp=temp&0xf;
temp_p=(&num)+16*temp;
temp_x=3;
temp_y=0;
display(temp_p,temp_x,temp_y,1);
temp_x=2;
temp_p=(&num)+16*temp1;
display(temp_p,temp_x,temp_y,1);
}
/****************************************************************
**潤年判斷l(xiāng)eap()子函數(shù)
**參數(shù):unsigned int year
**返回字:潤年標志leap0為非潤年
**內(nèi)部變量:bit leap1
****************************************************************/
bit leapf(unsigned int year){
bit bdata leap1;
if(year%4==0){
if(year%100==0){
if(year%400==0){
leap1=1;
}
else leap1=0;
}
else leap1=1;
}
else leap1=0;
return(leap1);
}
/****************************************************************
**hex_bcd()子函數(shù)
**參數(shù):hex需要轉換的單字節(jié)16進制數(shù)
**返回字:轉換完成的單字節(jié)bcd碼,高4位為高位低4位為低位
**內(nèi)部變量:bcd,temp為無符號字符型
****************************************************************/
unsigned char hex_bcd(unsigned char hex){
unsigned char bcd,temp;
bcd=hex%10;
temp=hex/10;
temp=temp<<4;
bcd=bcd|temp;
return (bcd);
}
/****************************************************************
** key()鍵盤子函數(shù)
** 鍵盤為兩鍵式一個鍵
** 參數(shù):
****************************************************************/
/****************************************************************
** time0()定時器0中斷子函數(shù),產(chǎn)生50ms中斷
**
****************************************************************/
void time0() interrupt 1 using 1{
th0=0x3c; //time0 50ms interrupt
tl0=0xba;
tr0=1;
msecond++;
if (msecond==20){
second_flag=1;
msecond=0;
}
}