本帖最后由 Leo_Tseng 于 2012-3-16 11:50 编辑
下面这个程序是用1602液晶,AT24C02芯片,定时器0实现数字时钟的功能,按下key1选择功能,按下key2数值加一,按下key3数值减一,用AT24C02实现存储功能,每次上电显示断电前的数值,下面这个程序key1,key2,key3功能已经实现,AT24C02存储功能也已经实现,时间也可以正常走了,而且在keil仿真中,各个功能都能实现,包括下面在板子上实现不了的功能:当时间为2012-12-31(为了简单,每个月设为31天) MON 23:59:12时,当秒走到60时,会变成2013-12-31 TUE 23:59:00,大家发现没,时跟分不会变,日期也不变,当我再从新把时间调成 23:59:12时,当秒走到60,变为00:59:00,再调一次,变为23:00:00,如果是小时那小于23那一切都正常,肿么回事?;可恨的是这些功能用keil调试时全部可以实现,现在我真不知道哪里出问题了,文章有点长啊,希望有耐心的大神能帮帮我,感激不尽了,奉上程序:(大家仔细看看中断那块吧,其他的显示啊存储,按键都已经没有问题的了)
#include
#include<timedelay.c>
extern void timedelay(int a);
***it rs=P2^4;
***it rw=P2^5;
***it en=P2^6;
***it key1=P3^0;
***it key2=P3^1;
***it key3=P3^2;
***it beep=P1^5;
***it scl=P1^1;
***it sda=P1^2;
***it wp=P1^0;
#define uchar unsigned char
uchar sec,min,hou,date,mon,year1,year2,num,flag,week,k,i;
uchar code table1[7][3]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
void delay()
{;;}
/////////////////////////////////////////////
//IIC总线AT24c02//
//初始化//
void init()
{
wp=0;
sda=1;
delay();
scl=1;
delay();
}
//起始信号//
void start()
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
//应答信号//
void response()
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<255)) i++;
scl=0;
delay();
}
//终止信号//
void stop()
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
//写一个字节//
void write_byte(uchar date)
{
uchar temp,i;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;//允许数据读写//
delay();
sda=CY;//读取数据//
delay();
scl=1;//scl置高电平,数据稳定//
delay();
}
scl=0;
delay();
sda=1;//不用的时候都要释放数据总线将sda置一//
delay();
}
//读一个字节//
uchar read_byte()
{
uchar k,i;
scl=0;
delay();
scl=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
return(k);
}
//写数据//
void write_add(uchar add,uchar date)
{
start();
write_byte(0xae);
response();
write_byte(add);
response();
write_byte(date);
response();
stop();
}
//度数据//
uchar read_add(uchar add)
{
uchar a;
start();
write_byte(0xae);
response();
write_byte(add);
response();
timedelay(5);
start();
write_byte(0xaf);
response();
a=read_byte();
//response();
stop();
return a;
}
///////////////////////////////////////////////
//液晶显示1602//
//写命令//
void write_com(uchar date1)
{
rs=0;//rs=0,写命令//
en=0;
P0=date1;//将数据送进总线//
timedelay(5);
en=1;//使能端给一高脉冲将数据送走//
timedelay(5);
en=0;//将使能端置低以完成高脉冲//
}
//写数据//
void write_byte1(uchar date2)
{
rs=1;//写数据命令//
en=0;
P0=date2;//将数据送往总线//
timedelay(5);
en=1;//将使能端至高,给一高脉冲,将数据送走//
timedelay(5);
en=0;//将使能端置低以完成高脉冲//
}
//将数字送进液晶显示//
void write_(uchar shu)
{
uchar sw,gw;
sw=shu/10;
gw=shu%10;
write_byte1(0x30+sw);//将十位送进液晶显示//
timedelay(5);
write_byte1(0x30+gw);//将个位送进液晶显示//
timedelay(5);
}
//初始化//
void init1()
{
en=0;
rw=0;
write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口//
write_com(0x0c);//设置开显示,不显示光标//
write_com(0x06);//写一个字符后地址指针加一//
write_com(0x01);//显示清零,数据指针清零//
}
void yejing()
{
write_com(0x80+0x45);//写显示“:”的地址//
write_byte1(':');//显示://
timedelay(5);
write_com(0x80+0x48);//写显示“:”的地址//
write_byte1(':'); //显示://
timedelay(5);
write_com(0x80+0x05);//显示——地址//
write_byte1('-');
timedelay(5);
write_com(0x80+0x08);
write_byte1('-');
timedelay(5);
}
void yejing2()
{
write_com(0x80+0x43);
write_(hou);
timedelay(5);
write_com(0x80+0x46);
write_(min);
timedelay(5);
write_com(0x80+0x49);
write_(sec);
timedelay(5);
write_com(0x80+0x0c);
for(i=0;i<3;i++)
{
write_byte1(table1[week]);//显示week//
timedelay(5);
}
write_com(0x80+0x01);
write_(year1);
timedelay(5);
write_com(0x80+0x03);
write_(year2);
timedelay(5);
write_com(0x80+0x06);
write_(mon);
timedelay(5);
write_com(0x80+0x09);
write_(date);
timedelay(5);
}
//////////////////////////////////
//定时器0//
//初始化//
void init2()
{
TMOD=0x01;
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
ET0=1;
TR0=1;
EA=1;
}
//中断函数//
void T0_time() interrupt 1
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
num++;
if(num==20)
{
num=0;
sec++;//每秒加一//
flag=3;//显示秒的标志
beep=1;//响铃
timedelay(5);
beep=0;
if(sec==60)
{
sec=0;
min++;
flag=2;//显示分的标志
if(min==60)
{
min=0;
hou++;
flag=1;//显示时的标志
if(hou==24)
{
hou=0;
date++;
week++;
if(week==7) week=0;
flag=4;//显示星期、日的标志
if(date==32)
{
date=1;
mon++;
flag=5;//显示月的标志
if(mon==13)
{
mon=1;
year2++;
flag=6;//显示年的标志
if(year2==100)
{
year2=0;
year1++;
flag=7;//显示年的标志
if(year1==100)
year1=0;
}
}
}
}
}
}
}
}
void T0_timeyejingxianshi()
{
if(flag==1)
{
write_com(0x80+0x43);//写显示时的地址
write_(hou); //显示时
write_add(3,hou);//将此时数据写进AT24C02
}
if(flag==2)
{
write_com(0x80+0x46);
write_(min);
write_add(2,min);
}
if(flag==3)
{
write_com(0x80+0x49);
write_(sec);
write_add(1,sec);
}
if(flag==4)
{
write_com(0x80+0x09);
write_(date);
write_add(4,date);
write_com(0x80+0x0c);
for(i=0;i<3;i++)
{
write_byte1(table1[week]);//显示week//
timedelay(5);
}
write_add(8,week);
}
if(flag==5)
{
write_com(0x80+0x06);
write_(mon);
write_add(5,mon);
}
if(flag==6)
{
write_com(0x80+0x03);
write_(year2);
write_add(6,year2);
}
if(flag==7)
{
write_com(0x80+0x01);
write_(year1);
write_add(7,year1);
}
}
///////////////////////////////////////
void keyscan()
{
if(key1==0)
{
timedelay(10);
if(key1==0)
{
k++;
if(k>9) k=0;
while(!key1);
TR0=0;
if(k==1)
{
write_com(0x80+0x49);//显示位置
write_com(0x0f);//闪烁光标
}
if(k==2)
{
write_com(0x80+0x46);
write_com(0x0f);
}
if(k==3)
{
write_com(0x80+0x43);
write_com(0x0f);
}
if(k==4)
{
write_com(0x80+0x0c);
write_com(0x0f);
}
if(k==5)
{
write_com(0x80+0x09);
write_com(0x0f);
}
if(k==6)
{
write_com(0x80+0x06);
write_com(0x0f);
}
if(k==7)
{
write_com(0x80+0x03);
write_com(0x0f);
}
if(k==8)
{
write_com(0x80+0x01);
write_com(0x0f);
}
if(k==9)
{
write_com(0x0c);
TR0=1;
}
}
}
if(key2==0)
{
timedelay(10);
if(key2==0)
{
while(!key2);
if(k==1)
{
sec++;
if(sec==60) sec=0;
write_com(0x80+0x49);
write_(sec);
write_add(1,sec);
}
if(k==2)
{
min++;
if(min==60) min=0;
write_com(0x80+0x46);
write_(min);
write_add(2,min);
}
if(k==3)
{
hou++;
if(hou==24) hou=0;
write_com(0x80+0x43);
write_(hou);
write_add(3,hou);
}
if(k==4)
{
week++;
if(week==7) week=0;
write_com(0x80+0x0c);
for(i=0;i<3;i++)
{
write_byte1(table1[week]);//显示week//
timedelay(5);
}
write_add(8,week);
}
if(k==5)
{
date++;
if(date==31) date=1;
write_com(0x80+0x09);
write_(date);
write_add(4,date);
}
if(k==6)
{
mon++;
if(mon==13) mon=1;
write_com(0x80+0x06);
write_(mon);
write_add(5,mon);
}
if(k==7)
{
year2++;
if(year2==100) year2=0;
write_com(0x80+0x03);
write_(year2);
write_add(6,year2);
}
if(k==8)
{
year1++;
if(year1==100) year1=0;
write_com(0x80+0x01);
write_(year1);
write_add(7,year1);
}
}
}
if(key3==0)
{
timedelay(10);
if(key3==0)
{
while(!key3);
if(k==1)
{
sec--;
if(sec==0) sec=59;//秒
write_com(0x80+0x49);
write_(sec);
write_add(1,sec);
}
if(k==2)
{
min--;
if(min==0) min=59;//分
write_com(0x80+0x46);
write_(min);
write_add(2,min);
}
if(k==3)
{
hou--;
if(hou<0) hou=23;//时
write_com(0x80+0x43);
write_(hou);
write_add(3,hou);
}
if(k==4)
{
week--;
if(week==0) week=6;
write_com(0x80+0x0c);
for(i=0;i<3;i++)
{
write_byte1(table1[week]);//显示week//
timedelay(5);
}
write_add(8,week);
}
if(k==5)
{
date--;
if(date<1) date=30;
write_com(0x80+0x09);
write_(date);
write_add(4,date);
}
if(k==6)
{
mon--;
if(mon<1) mon=12;
write_com(0x80+0x06);
write_(mon);
write_add(5,mon);
}
if(k==7)
{
year2--;
if(year2==0) year2=99;
write_com(0x80+0x03);
write_(year2);
write_add(6,year2);
}
if(k==8)
{
year1--;
if(year1==0) year1=99;
write_com(0x80+0x01);
write_(year1);
write_add(7,year1);
}
}
}
}
//////////////////////////////////////
void main()
{
init();
init1();
hou=read_add(3);//从AT24C02中读取数据时
if(hou>23) hou=0;//判断数据是否有效,即小于24
min=read_add(2);
if(min>=60) min=0;
sec=read_add(1);
if(sec>=60) sec=0;
year1=read_add(7);
if(year1>100) year1=20;
year2=read_add(6);
if(year2>100) year2=12;
mon=read_add(5);
if(mon>12) mon=1;
date=read_add(4);
if(date>30) date=1;
week=read_add(8);
if(week>6) week=0;
yejing2();
yejing();
init2();
while(1)
{
keyscan();
T0_timeyejingxianshi();
}
}
|