当前位置:文档之家› 智能电子钟LCD显示仿真图和程序

智能电子钟LCD显示仿真图和程序

#include

#include

#define uint unsigned int

#define uchar unsigned char

#define Date P3 //数码管数据口

#define com P1

sbit DS1302_CLK = P1^7; //实时时钟时钟线引脚

sbit DS1302_IO = P2^6; //实时时钟数据线引脚

sbit DS1302_RST = P1^6; //实时时钟复位线引脚

sbit ACC0 = ACC^0;

sbit ACC7 = ACC^7;

uchar code table[]={0x3f,0x06,0x5b,0x4f

,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

char hide_sec,hide_min,hide_hour,hide_day,hide_week,

hide_month,hide_year; //秒,分,时到日,月,年位闪的计数

sbit Set = P2^0; //模式切换键

sbit Up = P2^1; //加法按钮

sbit Down = P2^2; //减法按钮

sbit out = P2^3; //立刻跳出调整模式按钮

sbit di=P2^4; //蜂鸣器

char done,count,temp,flag,up_flag,down_flag;

uchar TempBuffer[5],week_value[2];

void show_time(); //显示程序

/***********************

* 功能: 延时,延时时间大概为ms。

**********************/

void delayms(int x)

{int i,j;

for(i=110; i>0; i--)

for(j=x; j>0; j--);

}

void beep()

{

di=1;delayms(400); di=0;}

/*************************

*名称: 数码管显示

*************************/

xianshi(uchar shi1,uchar shi2,uchar fen1,uchar fen2,uchar miao1,uchar miao2) {

Date=table[shi1];com=0xfe;delayms(10);

Date=table[shi2];com=0xfd;delayms(10);

Date=table[fen1];com=0xfb;delayms(10);

Date=table[fen2];com=0xf7;delayms(10);

Date=table[miao1];com=0xef;delayms(10);

Date=table[miao2];com=0xdf;delayms(10);

}

/***********1602液晶显示部分子程序*********/

sbit LcdRs= P2^5;

sbit LcdRw= P2^6;

sbit LcdEn = P2^7;

sfr DBPort= 0x80;

//内部等待函数****************

unsigned char LCD_Wait(void)

{ LcdRs=0;

LcdRw=1; _nop_();

LcdEn=1; _nop_();

LcdEn=0;

return DBPort;

}

//向LCD写入命令或数据******************

#define LCD_COMMAND 0 // Command

#define LCD_DATA 1 // Data

#define LCD_CLEAR_SCREEN 0x01 // 清屏

#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input)

{LcdEn=0;LcdRs=style;LcdRw=0;

_nop_();DBPort=input; _nop_();//注意顺序

LcdEn=1; _nop_();//注意顺序

LcdEn=0; _nop_();LCD_Wait();

}

//设置显示模式***********************

#define LCD_SHOW 0x04 //显示开

#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR 0x02 //显示光标

#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动

#define LCD_NO_FLASH 0x00 //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)

{LCD_Write(LCD_COMMAND, 0x08|DisplayMode); }

//设置输入模式****************************

#define LCD_AC_UP 0x02

#define LCD_AC_DOWN 0x00 // default

#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //default

void LCD_SetInput(unsigned char InputMode)

{LCD_Write(LCD_COMMAND, 0x04|InputMode);}

//初始化LCD*************************

void LCD_Initial()

{ LcdEn=0;

LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);

LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏

LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}

//液晶字符输入的位置************************

void GotoXY(unsigned char x, unsigned char y)

{if(y==0)LCD_Write(LCD_COMMAND,0x80|x);

if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));

}//将字符输出到液晶显示

void Print(unsigned char *str)

{while(*str!='\0')

{LCD_Write(LCD_DATA,*str);str++;}}

/***********DS1302时钟部分子程序*********/

typedef struct __SYSTEMTIME__

{

unsigned char Second;

unsigned char Minute;

unsigned char Hour;

unsigned char Week;

unsigned char Day;

unsigned char Month;

unsigned char Year;

unsigned char DateString[11];

unsigned char TimeString[9];

}SYSTEMTIME; //定义的时间类型

SYSTEMTIME CurrentTime;

#define AM(X) X

#define PM(X) (X+12) // 转成24小时制

#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间

#define DS1302_MINUTE 0x82

#define DS1302_HOUR 0x84

#define DS1302_WEEK 0x8A

#define DS1302_DAY 0x86

#define DS1302_MONTH 0x88

#define DS1302_YEAR 0x8C

void DS1302InputByte(unsigned char d)

{ //实时时钟写入一字节(内部函数)

unsigned char i;ACC = d; for(i=8; i>0; i--)

{DS1302_IO = ACC0; //相当于汇编中的RRC

DS1302_CLK = 1; DS1302_CLK = 0; ACC = ACC >> 1; } } unsigned char DS1302OutputByte(void)

{ //实时时钟读取一字节(内部函数)

unsigned char i; for(i=8; i>0; i--)

{ ACC = ACC >>1; //相当于汇编中的RRC ACC7 = DS1302_IO; DS1302_CLK = 1;DS1302_CLK = 0; } return(ACC); }

void Write1302(unsigned char ucAddr, unsigned char ucDa)

{ DS1302_RST = 0;

DS1302_CLK = 0;

DS1302_RST = 1;

DS1302InputByte(ucAddr); // 地址,命令

DS1302InputByte(ucDa); // 写1Byte数据

DS1302_CLK = 1;

DS1302_RST = 0;

}

unsigned char Read1302(unsigned char ucAddr)

{ //读取DS1302某地址的数据

unsigned char ucData;

DS1302_RST = 0;

DS1302_CLK = 0;

DS1302_RST = 1;

DS1302InputByte(ucAddr|0x01); // 地址,命令

ucData = DS1302OutputByte(); // 读1Byte数据

DS1302_CLK = 1;

DS1302_RST = 0;

return(ucData);}

void DS1302_GetTime(SYSTEMTIME *Time)

{//获取时钟芯片的时钟数据到自定义的结构型数组

unsigned char ReadV alue;

ReadValue = Read1302(DS1302_SECOND);

Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_MINUTE);

Time->Minute = ((ReadV alue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_HOUR);

Time->Hour = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);

ReadValue = Read1302(DS1302_DAY);

Time->Day = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);

ReadValue = Read1302(DS1302_WEEK);

Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);

ReadValue = Read1302(DS1302_MONTH);

Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_YEAR);

Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F); }

void DateToStr(SYSTEMTIME *Time)

{ //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[] if(hide_year<2)

{ Time->DateString[0] = '2';

Time->DateString[1] = '0';

Time->DateString[2] = Time->Year/10 + '0';

Time->DateString[3] = Time->Year%10 + '0';}

else{ Time->DateString[0] = ' '; Time->DateString[1] = ' ';

Time->DateString[2] = ' '; Time->DateString[3] = ' ';}

Time->DateString[4] = '/';

if(hide_month<2)

{Time->DateString[5] = Time->Month/10 + '0';

Time->DateString[6] = Time->Month%10 + '0';}

else{ Time->DateString[5] = ' '; Time->DateString[6] = ' ';}

Time->DateString[7] = '/';

if(hide_day<2)

{Time->DateString[8] = Time->Day/10 + '0';

Time->DateString[9] = Time->Day%10 + '0';}

else{Time->DateString[8] = ' ';Time->DateString[9] = ' '; }

if(hide_week<2){

//星期的数据另外放到week_value[]数组里,,因为等一下要在最后显视

week_value[0] = Time->Week%10 + '0';

}

else { week_value[0] = ' ';}

week_value[1] = '\0';

Time->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符

}

void TimeToStr(SYSTEMTIME *Time)

{ if(hide_hour<2)

{ Time->TimeString[0] = Time->Hour/10 + '0';

Time->TimeString[1] = Time->Hour%10 + '0';}

else{ Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}

Time->TimeString[2] = ':';

if(hide_min<2){ Time->TimeString[3] = Time->Minute/10 + '0';

Time->TimeString[4] = Time->Minute%10 + '0';}

else {Time->TimeString[3] = ' ';Time->TimeString[4] = ' '; }

Time->TimeString[5] = ':';

if(hide_sec<2)

{Time->TimeString[6] = Time->Second/10 + '0';

Time->TimeString[7] = Time->Second%10 + '0';}

else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' '; }

Time->DateString[8] = '\0';}

void Initial_DS1302(void) //时钟芯片初始化

{ unsigned char Second=Read1302(DS1302_SECOND);

if(Second&0x80) //判断时钟芯片是否关闭

{Write1302(0x8e,0x00); //写入允许

Write1302(0x8c,0x07); //

Write1302(0x88,0x07);Write1302(0x86,0x25);

Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);

Write1302(0x80,0x55);Write1302(0x8e,0x80); //禁止写入

}

}

void Delay1ms(unsigned int count)

{unsigned int i,j;

for(i=0;i

for(j=0;j<20;j++);}

/*延时子程序*/

void mdelay(uint delay)

{ uint i;for(;delay>0;delay--){for(i=0;i<62;i++) //1ms延时.

{;}}}

void outkey() //跳出调整模式,返回默认显示

{ uchar Second;if(out==0) { mdelay(8); count=0;

hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;

Second=Read1302(DS1302_SECOND);

Write1302(0x8e,0x00); //写入允许

Write1302(0x80,Second&0x7f);

Write1302(0x8E,0x80); //禁止写入

done=0; while(out==0); }}

///////////////////////////////////////////////////////////////////////////////

void Upkey()//升序按键

{ Up=1;if(Up==0)

{

mdelay(8);

switch(count)

{case 1:

temp=Read1302(DS1302_SECOND); //读取秒数

temp=temp+1; //秒数加1

up_flag=1; //数据调整后更新标志

if((temp&0x7f)>0x59) //超过59秒,清零

temp=0; break;

case 2:

temp=Read1302(DS1302_MINUTE); //读取分数

temp=temp+1; //分数加1

up_flag=1;

if(temp>0x59) //超过59分,清零

temp=0;break;

case 3:

temp=Read1302(DS1302_HOUR); //读取小时数

temp=temp+1; //小时数加1

up_flag=1;

if(temp>0x23) //超过23小时,清零

temp=0; break;

case 4:

temp=Read1302(DS1302_WEEK); //读取星期数

temp=temp+1; //星期数加1

up_flag=1;

if(temp>0x7)

temp=1;

break;

case 5:

temp=Read1302(DS1302_DAY); //读取日数

temp=temp+1; //日数加1

up_flag=1;

if(temp>0x31)

temp=1;

break;

case 6:

temp=Read1302(DS1302_MONTH); //读取月数

temp=temp+1; //月数加1

up_flag=1;

if(temp>0x12)

temp=1;

break;

case 7:

temp=Read1302(DS1302_YEAR); //读取年数

temp=temp+1; //年数加1

up_flag=1;

if(temp>0x85)

temp=0;

break;

default:break;}

while(Up==0); }}

///////////////////////////////////////////////////////////////////////////////

void Downkey()//降序按键

{ Down=1;if(Down==0)

{ mdelay(8);

switch(count)

{case 1:

temp=Read1302(DS1302_SECOND); //读取秒数

temp=temp-1; //秒数减1

down_flag=1; //数据调整后更新标志

if(temp==0x7f) //小于0秒,返回59秒

temp=0x59;

break;

case 2:

temp=Read1302(DS1302_MINUTE); //读取分数

temp=temp-1; //分数减1

down_flag=1;

if(temp==-1)

temp=0x59; //小于0秒,返回59秒

break;

case 3:

temp=Read1302(DS1302_HOUR); //读取小时数

temp=temp-1; //小时数减1

down_flag=1;

if(temp==-1)

temp=0x23;

break;

case 4:

temp=Read1302(DS1302_WEEK); //读取星期数

temp=temp-1; //星期数减1

down_flag=1;

if(temp==0)

temp=0x7;;

break;

case 5:

temp=Read1302(DS1302_DAY); //读取日数

temp=temp-1; //日数减1

down_flag=1;

if(temp==0)

temp=31;

break;

case 6:

temp=Read1302(DS1302_MONTH); //读取月数

temp=temp-1; //月数减1

down_flag=1;

if(temp==0)

temp=12;

break;

case 7:

temp=Read1302(DS1302_YEAR); //读取年数

temp=temp-1; //年数减1

down_flag=1;

if(temp==-1)

temp=0x85;

break;

default:break;}while(Down==0); }}

void Setkey()//模式选择按键

{Set=1;if(Set==0)

{ mdelay(8); count=count+1; //Setkey按一次,count就加1 done=1; //进入调整模式

while(Set==0); }

}

void bell()

{

if (Set==1);while(Set==1); }

void keydone()//按键功能执行

{ uchar Second;

if(flag==0) //关闭时钟,停止计时

{ Write1302(0x8e,0x00); //写入允许

temp=Read1302(0x80);

Write1302(0x80,temp|0x80);

Write1302(0x8e,0x80); //禁止写入

flag=1; }

Setkey(); //扫描模式切换按键

switch(count)

{case 1:do //count=1,调整秒

{ outkey(); //扫描跳出按钮

Upkey(); //扫描加按钮

Downkey(); //扫描减按钮

if(up_flag==1||down_flag==1)

{ //数据更新,重新写入新的数据

Write1302(0x8e,0x00); //写入允许

Write1302(0x80,temp|0x80); //写入新的秒数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0; }

hide_sec++; //位闪计数

if(hide_sec>3)

hide_sec=0;

show_time(); //液晶显示数据

}while(count==2);break;

case 2:do //count=2,调整分

{ hide_sec=0;

outkey();

Upkey();

Downkey();

if(temp>0x60)

temp=0;

if(up_flag==1||down_flag==1)

{ Write1302(0x8e,0x00); //写入允许

Write1302(0x82,temp); //写入新的分数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0; }

hide_min++;

if(hide_min>3)

hide_min=0;

show_time();

}while(count==3);break;

case 3:do //count=3,调整小时{ hide_min=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{ Write1302(0x8e,0x00); //写入允许

Write1302(0x84,temp); //写入新的小时数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0; }

hide_hour++;

if(hide_hour>3)

hide_hour=0;

show_time();

}while(count==4);break;

case 4:do //count=4,调整星期{ hide_hour=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{ Write1302(0x8e,0x00); //写入允许

Write1302(0x8a,temp); //写入新的星期数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;}

hide_week++;

if(hide_week>3)

hide_week=0;

show_time();

}while(count==5);break;

case 5:do //count=5,调整日{hide_week=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{Write1302(0x8e,0x00); //写入允许

Write1302(0x86,temp); //写入新的日数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0; }

hide_day++;

if(hide_day>3)

hide_day=0;

show_time();

}while(count==6);break;

case 6:do //count=6,调整月{ hide_day=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{ Write1302(0x8e,0x00); //写入允许

Write1302(0x88,temp); //写入新的月数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0; }

hide_month++;

if(hide_month>3)

hide_month=0;

show_time();

}while(count==7);break;

case 7:do //count=7,调整年{ hide_month=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{ Write1302(0x8e,0x00); //写入允许

Write1302(0x8c,temp); //写入新的年数

Write1302(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0; }

hide_year++;

if(hide_year>3)

hide_year=0;

show_time();

}while(count==8);break;

case 8: count=0;hide_year=0;

//count8, 跳出调整模式,返回默认显示状态

Second=Read1302(DS1302_SECOND);

Write1302(0x8e,0x00); //写入允许

Write1302(0x80,Second&0x7f);

Write1302(0x8E,0x80) ;//禁止写入

done=0;

break; //count=7,开启中断,标志位置0并退出

default:break; }}

void show_time() //液晶显示程序

{

uchar a,b,c,d,e,f,i;

DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符GotoXY(0,1);

Print(CurrentTime.TimeString); //显示时间

GotoXY(0,0);

Print(CurrentTime.DateString); //显示日期

GotoXY(15,0);

Print(week_value); //显示星期

GotoXY(11,0);

Print("Week"); //在液晶上显示字母week

a=CurrentTime.TimeString[0]&0x0f;

b=CurrentTime.TimeString[1]&0x0f;

c=CurrentTime.TimeString[3]&0x0f;

d=CurrentTime.TimeString[4]&0x0f;

e=CurrentTime.TimeString[6]&0x0f;

f=CurrentTime.TimeString[7]&0x0f;

xianshi(a,b,c,d,e,f);

if(c==0&&d==0&&e==0&&f==0) //整点报时

{

i=a*10+b;

while(i--)

beep();

}

}

void main()

{ flag=1; //时钟停止标志

LCD_Initial(); //液晶初始化

Initial_DS1302(); //时钟芯片初始化

up_flag=0;

down_flag=0;

done=0; //进入默认液晶显示

while(1)

{

while(done==1) keydone(); //进入调整模式

while(out==0) bell(); //进入闹钟模式

while(done==0&&out==1)

{ show_time(); //液晶显示数据

flag=0; Setkey(); //扫描各功能键}}}

相关主题
文本预览
相关文档 最新文档