|
/************************************************************************************************
屏是12864的;DS1302的时钟。时钟能正常走,关键在于我修改了时间了,重写的时钟数据,读不进去啊!
如果不用KEY,或者在KEY里面将重写数据那全改成变量竟能读进去,所以读应该没有问题吧。。。。
昨天晚上通宵思考,今天晚上又思考,好打击信心啊,在此请求各路高手帮帮小生。的确没有办法了,才在此求救!!
程序有点乱,麻烦各位耐心看看。希望指出问题!!!!我暂时删了调日期的代码,勉得更乱
************************************************************************************************/
程序能正常运行,按键能显示加减后的数,但退出修改时间后,却不能显示补修改后的数,也就是说当你在进入KEY的时候,时钟内部跟本没有停,依然在走,当退出KEY时,显示DS1302一直在走的数!!!我试着把主函数中的if全部注释后,下进去,依然在走!!!这也就是说我跟本无法控制时间。怎么的?难不成要中断,可是我不知道这个中断如果加在这个程序里面。。。。。我好困啊,二个晚上没有睡了。高手们,帮帮我吧!!!!!网上的程序看了很多,可是我的问题依然无法解决!!!
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define lcd P0
sbit rs=P2^0;
sbit rw=P2^1;
sbit e=P2^2;
sbit sck=P1^0;
sbit io=P1^1;
sbit rst=P1^2;
sbit key1=P3^1;
sbit key2=P3^2;
sbit key3=P3^3;
uchar code table[]={
"2010年04月19日MO"
" 00时00分00秒 "
};
char sec,min,hour,date,mon,day,year;
uchar s1num,s2num;
uchar flag1,flag2;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*******************************************************
1 2 8 6 4
*******************************************************/
void write_com(uchar com)//写指令
{
rs=0;
rw=0;
e=1;
lcd=com;
delay(5);
e=0;
}
void write_date(uchar dat)//写数据
{
rs=1;
rw=0;
e=1;
lcd=dat;
delay(5);
e=0;
}
void init_lcd1(uchar code *chn)//首屏显示
{
uchar i,j;
write_com(0x30);
write_com(0x30);
for(i=0;i<2;i++)
{
for(j=0;j<16;j++)
{
write_date(chn[i*16+j]);
}
}
}
void write_xq(uchar day1)//星期-将数字转换成字母
{
write_com(0x80+7);
if(day1==1)
{
write_date(0x4d);
write_date(0x4f);
}
if(day1==2)
{
write_date(0x54);
write_date(0x55);
}
if(day1==3)
{
write_date(0x57);
write_date(0x45);
}
if(day1==4)
{
write_date(0x54);
write_date(0x48);
}
if(day1==5)
{
write_date(0x46);
write_date(0x52);
}
if(day1==6)
{
write_date(0x53);
write_date(0x41);
}
if(day1==7)
{
write_date(0x53);
write_date(0x55);
}
}
void clrram()//清屏
{
write_com(0x30);
write_com(0x01);
}
void init_lcd()//初始化LCD并显首屏
{
e=0;
write_com(0x30);
write_com(0x30);
write_com(0x0c);
write_com(0x01);
write_com(0x06);
init_lcd1(table);
}
/*******************************************************
DS 1302
*******************************************************/
void write_byte(uchar dat)//写一个字节
{
uchar i;
for(i=0;i<8;i++)
{
io=dat&0x01;
sck=0;
sck=1;
dat>>=1;
}
}
uchar read_byte()//读一个字节
{
uchar i;
uchar temp=0x00;
for(i=0;i<8;i++)
{
if(io)
temp=temp|0x80;
sck=1;
sck=0;
temp>>=1;
}
return(temp);
}
void write_ds1302(uchar add,uchar dat)//写
{
rst=0;
sck=0;
rst=1;
write_byte(add);
write_byte(dat);
sck=1;
rst=0;
}
uchar read_ds1302(uchar add)//读
{
uchar inf;
rst=0;
sck=0;
rst=1;
write_byte(add);
inf=read_byte();
sck=1;
rst=0;
return(inf);
}
void protect_ds1302(bit flags)//写保护 1为关,0为开
{
if(flags)
write_ds1302(0x8e,0x00);
else
write_ds1302(0x8e,0x80);
}
void init_ds1302(uchar sec,uchar min,uchar hour,uchar date,uchar mon,uchar day,uchar year)//初始化及十进制转BCD
{
protect_ds1302(1);
write_ds1302(0x80,((sec/10)<<4|(sec%10)));
write_ds1302(0x82,((min/10)<<4|(min%10)));
write_ds1302(0x84,((hour/10)<<4|(hour%10)));
write_ds1302(0x86,((date/10)<<4|(date%10)));
write_ds1302(0x88,((mon/10)<<4|(mon%10)));
write_ds1302(0x8a,((day/10)<<4|(day%10)));
write_ds1302(0x8c,((year/10)<<4|(year%10)));
protect_ds1302(0);
}
uchar bcd_shi(uchar dat)//BCD转十进制
{
uchar temp;
temp=((dat>>4)&0x0f)*10+(dat&0x0f);
return(temp);
}
void ds1302_read()//读出DS1302数据
{
sec=bcd_shi(read_ds1302(0x81));
min=bcd_shi(read_ds1302(0x83));
hour=bcd_shi(read_ds1302(0x85));
date=bcd_shi(read_ds1302(0x87));
mon=bcd_shi(read_ds1302(0x89));
day=bcd_shi(read_ds1302(0x8b));
year=bcd_shi(read_ds1302(0x8d));
}
void write_sfm(uchar add,uchar dat)//将时分秒写入LCD
{
uchar shi,ge;
shi=dat/10;
ge=dat%10;
write_com(0x88+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_disp()//给地址,显示在LCD上
{
write_sfm(5,sec);
write_sfm(3,min);
write_sfm(1,hour);
write_nyr(5,date);
write_nyr(3,mon);
write_xq(day);
write_nyr(1,year);
}
////////////////////////////////////////////////////////////
/*****************************************************************************************************************************************
按键调时,当key1按下时,s1num++, 1为秒地址,2为分,3为时,4为退出并令flag1=0允许退出后进行主函数中的if语句!问题就出在这儿,往下看!
****************************************************************************************************************************************/
void key_time1()
{
if(key1==0)
{
delay(5);
if(key1==0)
{
s1num++;
flag1=1;
//进行调时前,先把LCD现显的数读出来,不然按下时会乱跳数字,这个问题我想了好久才解决了
sec=bcd_shi(read_ds1302(0x81));
min=bcd_shi(read_ds1302(0x83));
hour=bcd_shi(read_ds1302(0x85));
date=bcd_shi(read_ds1302(0x87));
mon=bcd_shi(read_ds1302(0x89));
day=bcd_shi(read_ds1302(0x8b));
year=bcd_shi(read_ds1302(0x8d));
while(!key1);
if(s1num==1)
{
write_com(0x88+5);
write_com(0x0f);
}
if(s1num==2)
{
write_com(0x88+3);
}
if(s1num==3)
{
write_com(0x88+1);
}
if(s1num==4)
{
s1num=0;
write_com(0x0c);
flag1=0; //s1num为4时退出keyscan,下次循环将进入主函数if语句,
sck=0;
rst=0;
rst=1;
/*********************************问题就在这儿,下面这五行代码!!!当按键退出时,我要把我修改后的数重新读给DS1302,可是为什么不成功呢??
当我把括号中的变量名换成数字的时候,却能成功显示,怎么的?是不认别sec..吗?还是不允许读,或者是这样读不进去???
write_ds1302(0x8e,0x00);
write_ds1302(0x80,((sec/10)<<4|(sec%10)));
write_ds1302(0x82,((min/10)<<4|(min%10)));
write_ds1302(0x84,((hour/10)<<4|(hour%10)));
write_ds1302(0x8e,0x80);
}
}
}
}
void key_time2()//加
{
if(key2==0)
{
delay(5);
if(key2==0)
{
while(!key2);
if(s1num==1)
{
sec++;
if(sec==60)
{
sec=0;
}
write_sfm(5,sec);
write_com(0x88+5);//光标置位
// write_sfm(5,miao);
}
if(s1num==2)
{
min++;
if(min==60)
{
min=0;
}
write_sfm(3,min);
write_com(0x88+3);
}
if(s1num==3)
{
hour++;
if(hour==24)
{
hour=0;
}
write_sfm(1,hour);
write_com(0x88+1);
}
}
}
}
void key_time3()//减
{
if(key3==0)
{
delay(5);
if(key3==0)
{
while(!key3);
if(s1num==1)
{
sec--;
if(sec==-1)
{
sec=59;
}
write_sfm(5,sec);
write_com(0x88+5);
}
if(s1num==2)
{
min--;
if(min==-1)
{
min=59;
}
write_sfm(3,min);
write_com(0x88+3);
}
if(s1num==3)
{
hour--;
if(hour==-1)
{
hour=23;
}
write_sfm(1,hour);
write_com(0x88+1);
}
}
}
}
void keyscan()
{
key_time1();
if(s1num!=0)
{
key_time2();
key_time3();
}
}
////////////////////////////////////////////////////////////////////////////
void main()
{
clrram();
init_lcd();
delay(5);
// init_ds1302(27,7,7,23,4,6,11);//复位后重显初始化,所以注释了这行
// delay(5);
while(1)
{
keyscan();
if(flag1==0)
{
ds1302_read();
write_disp();
}
}
}
程序能正常运行,按键能显示加减后的数,但退出修改时间后,却不能显示补修改后的数,也就是说当你在进入KEY的时候,时钟内部跟本没有停,依然在走,当退出KEY时,显示DS1302一直在走的数!!!我试着把主函数中的if全部注释后,下进去,依然在走!!!这也就是说我跟本无法控制时间。怎么的?难不成要中断,可是我不知道这个中断如果加在这个程序里面。。。。。我好困啊,二个晚上没有睡了。高手们,帮帮我吧!!!!! |
|