液晶时钟程序单片机.docx
《液晶时钟程序单片机.docx》由会员分享,可在线阅读,更多相关《液晶时钟程序单片机.docx(20页珍藏版)》请在冰豆网上搜索。
液晶时钟程序单片机
1602液晶时钟程序
程序按郭天袢《新概念51单片机C语言教程》第十四章扩展显示年、月、日、星期调节功能。
1)时间显示在1602液晶上,并按秒实时更新
2)能调节按键调整时、分、秒、年、月、日和星期
3)每次按键按下时有短滴声响声
4)断电后下次上电会接着上次断电前的时间数继续运行
原理图如图
//原代码如下:
#include
//#include"24c02.h"
#defineucharunsignedchar
#defineuintunsignedint
#include"24c02.h"
sbitdula=P2^6;
sbitwela=P2^7;
sbitLCDEN=P3^4;
sbitLCDRS=P3^5;
sbits1=P3^0;//定义按键--功能键
sbits2=P3^1;//定义按键--增大键
sbits3=P3^2;//定义按键--减小键
sbitrd=P3^7;//按键公共脚
sbitbeep=P2^3;//定义蜂鸣器脚
ucharcount,s1_num;//定义中断次数计数变量功能键按键次数变量
ucharweek,day,month,year;//定义变量:
星期日月年
charmiao,shi,fen;//定义秒分时变量
ucharcodetable[]="2012-11-28Wed";
//voidwrite_week(charwe);//显示星期几函数
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddi()//蜂鸣器响一声函数
{
beep=0;
delay(100);
beep=1;
}
voidwrite_com(ucharcom)//液晶写命令函数
{
LCDRS=0;
P0=com;
delay(5);
LCDEN=1;
delay(5);
LCDEN=0;
}
voidwrite_date(uchardate)//液晶写数据函数
{
LCDRS=1;
P0=date;
delay(5);
LCDEN=1;
delay(5);
LCDEN=0;
}
voidwrite_week(charwe)//写星期几显示函数
{
write_com(0x80+12);
switch(we)
{
case1:
write_date('M');delay(5);//星期一Monday
write_date('o');delay(5);
write_date('n');delay(5);
break;
case2:
write_date('T');delay(5);//星期二Tuesday
write_date('u');delay(5);
write_date('e');delay(5);
break;
case3:
write_date('W');delay(5);//Wednesday
write_date('e');delay(5);
write_date('d');delay(5);
break;
case4:
write_date('T');delay(5);//Thursday
write_date('h');delay(5);
write_date('u');delay(5);
break;
case5:
write_date('F');delay(5);//星期五Friday
write_date('r');delay(5);
write_date('i');delay(5);
break;
case6:
write_date('S');delay(5);//星期六Saturday
write_date('a');delay(5);
write_date('t');delay(5);
break;
case7:
write_date('S');delay(5);//星期日Sunday
write_date('u');delay(5);
write_date('n');delay(5);
break;
default:
break;
}
}
voidwrite_sfm(ucharadd,uchardate)//写时分秒函数
{
ucharshiwei,gewei;
shiwei=date/10;
gewei=date%10;
write_com(0x80+0x40+add);//设置显示位置
write_date(0x30+shiwei);//加上0x30是因为数字变成字符串需要加上0x30,看ASCII码值与字符的关系
write_date(0x30+gewei);
}
voidwrite_year_month_day(ucharadd,ucharday)//写年月日数函数
{
ucharshi,ge;
shi=day/10;
ge=day%10;
write_com(0x80+add);//设置显示位置
write_date(0x30+shi);//加上0x30是因为数字变成字符串需要加上0x30,看ASCII码值与字符的关系
write_date(0x30+ge);
}
voidinit()//初始化函数
{
ucharnum;
rd=0;
beep=1;
dula=0;
wela=0;
LCDEN=0;//将使能端置0以完成高脉冲
fen=0;
miao=0;
shi=0;
count=0;//计数初始为0
init_24c02();
write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
write_com(0x0c);//设置开显示,不显示光标
write_com(0x06);//写一个字符后地址指针自动加1
write_com(0x01);//显示清0,数据指针清0
write_com(0x80);//设置显示初始坐标
for(num=0;num<15;num++)//显示年月日
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40+6);//写出时间显示部分的两个冒号
write_date(0x3a);
delay(5);
write_com(0x80+0x40+9);
write_date(0x3a);
delay(5);
miao=read_add
(1);//开机上电时读取24c02IIC的数据赋值
fen=read_add
(2);
shi=read_add(3);
week=read_add(4);//读取星期几
day=read_add(5);//读取多少日
month=read_add(6);
year=read_add(7);
write_sfm(10,miao);//分别送去液晶显示
write_sfm(7,fen);
write_sfm(4,shi);
write_week(week);//开机从24c02读取的星期几数从新写入液晶显示出来
write_year_month_day(9,day);
write_year_month_day(6,month);
write_year_month_day(3,year);
//定时器初始化
TMOD=0x01;//设置定时器0工作模式1
TH0=(65536-45876)/256;//定时器装初值
TL0=(65536-45876)%256;
EA=1;//开总中断
ET0=1;//打定时器0中断
TR0=1;//启动定时器0
}
voidkeyscan()//按键扫描函数
{
if(s1==0)
{
delay(5);
if(s1==0)
{
s1_num++;//功能键按下次数记录
while(!
s1);//按键释放确认
di();
if(s1_num==1)//只按一次按键时
{
TR0=0;//关闭定时器
write_com(0x80+0x40+11);
write_com(0x0f);//打开光标闪烁
}
if(s1_num==2)//第二次按下光标闪烁定位到分钟位置
{
write_com(0x80+0x40+8);
}
if(s1_num==3)//第三次按下光标闪烁定位到小时位置
{
write_com(0x80+0x40+5);
}
/**************************************
if(s1_num==4)//第三四次按下退出
{
s1_num=0;
write_com(0x0c);//取消光标闪栎
TR0=1;//启动定时器使时钟开始走
}
***************************************/
if(s1_num==4)//光标处星期
{
write_com(0x80+14);
}
if(s1_num==5)//光标处日
{
write_com(0x80+10);
}
if(s1_num==6)//光标处月
{
write_com(0x80+7);
}
if(s1_num==7)//光标处年
{
write_com(0x80+4);
}
if(s1_num==8)//当第八次按功能键时退出光标闪烁及开始计时
{
s1_num=0;
write_com(0x0c);//取消光标闪栎
TR0=1;//启动定时器使时钟开始走
}
}
}
if(s1_num!
=0)
{
if(s2==0)//增加键确认按下
{
delay(5);
if(s2==0)
{
while(!
s2);
di();
if(s1_num==1)
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+11);
write_add(1,miao);
}
if(s1_num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+8);
write_add(2,fen);
}
if(s1_num==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+5);
write_add(3,shi);
}
if(s1_num==4)//按四次功能键后光标至星期几处,可调节星期几
{
week++;
if(week==8)
week=1;
write_week(week);
write_com(0x80+14);//写一个字符后光标会移一位,所以要重新定义光标位置
write_add(4,week);
}
if(s1_num==5)//光标至显示日处,可调节多少日
{
day++;
if(day==32)
day=1;
write_year_month_day(9,day);
write_com(0x80+10);
write_add(5,day);
}
if(s1_num==6)//光标至显示月处调节月份
{
month++;
if(month==13)
month=1;
write_year_month_day(6,month);
write_com(0x80+7);
write_add(6,month);
}
if(s1_num==7)
{
year++;
if(year==100)
year=00;
write_year_month_day(3,year);
write_com(0x80+4);
write_add(7,year);
}
}
}
if(s3==0)//确认减小键被按下
{
delay(5);//按键防抖延时
if(s3==0)//确认减小键被按下
{
while(!
s3);
di();
if(s1_num==1)
{
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+11);
write_add(1,miao);
}
if(s1_num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+8);
write_add(2,fen);
}
if(s1_num==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+5);
write_add(3,shi);
}
if(s1_num==4)
{
week--;
if(week==0)
week=7;
write_week(week);
write_com(0x80+14);//写一个字符后光标会移一位,所以要重新定义光标位置
write_add(4,week);
}
if(s1_num==5)//光标至显示日处,可调节多少日
{
day--;
if(day==0)
day=31;
write_year_month_day(9,day);
write_com(0x80+10);//光标位置移回在显示多少日的个位
write_add(5,day);
}
if(s1_num==6)//光标至显示月处调节月份
{
month--;
if(month==0)
month=12;
write_year_month_day(6,month);
write_com(0x80+7);
write_add(6,month);
}
if(s1_num==7)
{
year--;
if(year==-1)
year=99;
write_year_month_day(3,year);
write_com(0x80+4);
write_add(7,year);
}
}
}
}
}
voidmain()
{
init();//首先初始化各数据
while
(1)
{
keyscan();//按键扫描函数
}
}
voidtimer0()interrupt1//定时器0中断服务程序
{
TH0=(65536-45876)/256;
TL0=(65536-45876)%256;
count++;//中断次数累加,计数
if(count==20)//50微秒乘以20等于1秒
{
count=0;
miao++;
if(miao==60)//秒加到60则进位分钟
{
miao=0;//同时秒数清0
fen++;
if(fen==60)//分钟加到60则进位小时
{
fen=0;//同时分钟清0
shi++;
if(shi==24)//小时加到24则小时清0
{
shi=0;
}
write_sfm(4,shi);//小时若变化则重新写入
write_add(3,shi);//写入24c02存储起来,小时数的写入地址为3
}
write_sfm(7,fen);//分钟若变化则重新写入
write_add(2,fen);
}
write_sfm(10,miao);//秒若变化则重新写入
write_add(1,miao);
}
}
/***********************************
24C02.h头文件,将以下源代码需存为
与保存的C代码根目录下。
***********************************/
/bitwrite=0;//写24c02的标志
//#defineucharunsignedchar
//#defineuintunsignedint
sbitsda=P2^0;
sbitscl=P2^1;
voiddelay0()
{;;}
voidstart()//开始信号
{
sda=1;
delay0();
scl=1;
delay0();
sda=0;
delay0();
}
voidstop()//停止信号
{
sda=0;
delay0();
scl=1;
delay0();
sda=1;
delay0();
}
voidrespons()//应答信号
{
uchari=0;
scl=1;
delay0();
while((sda==1)&&(i<250))i++;
scl=0;
delay0();
}
voidinit_24c02()//IIC初始化函数
{
sda=1;
delay0();
scl=1;
delay0();
}
voidwrite_byte(uchardate)//写一个字节函数
{
uchari,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay0();
sda=CY;
delay0();
scl=1;
delay0();
}
scl=0;
delay0();
sda=1;
delay0();
}
ucharread_byte()//读一个字节
{
uchari,k;
scl=0;
delay0();
sda=1;
for(i=0;i<8;i++)
{
scl=1;
delay0();
k=(k<<1)|sda;
scl=0;
delay0();
}
returnk;
}
voidwrite_add(ucharaddress,uchardate)//指定地址写一个字节
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
ucharread_add(ucharaddress)//指定地址读一个字节
{
uchardate;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
returndate;
}
选择功能键时光标闪烁时: