本人自己设计一个闹钟,其中采用了DS12C887时钟芯片,经过查看资料与看这款IC资料,自认为可以顺利的使用,可等到我实践的时候,就发现怎么也不能读出DS12C887你的实时时钟数据,特求助于高手,还望指教,现我将程序写在下面:
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table1[]={"20 - - MON "};//显示日期
uchar code table2[]={" : : T:20C "};//显示温度与时间
uchar code table3[]={"0123456789"};
sbit key1=P2^3;//按键S1,功能键,进入设置键
sbit key2=P2^4;//按键S2,增加键
sbit key3=P2^5;//按键S3,减小键
sbit key4=P2^6;//按键S4,保存与查看闹钟设置键
sbit scl=P2^0;//串行时钟输入
sbit sda=P2^1;//串行数据输入/输出端
sbit ds=P2^7;//温度传感器
sbit lcd_rs=P3^3;//数据/命令选择/INT1输入接DS12C887IRQ外部中断输入
sbit lcd_en=P3^2;//片选信号
sbit bz=P3^4;//报警输出
sbit dscs=P2^2;//芯片片选端/DS12C887
sbit dsas=P3^5;//地址选通输入端/DS12C887
sbit dsrw=P3^1;//写输入允许端/DS12C887
sbit dsds=P3^0;//读输入允许端/DS12C887
bit flag1,flag2;//定义两个位变量
uchar miao,fen,fen1,fen2,shi,year,year0,year1,year2,year3,month,day,week;//定义关于时间的变量
uchar amiao,amiao0,amiao1,afen,afen0,afen1,ashi,ashi0,ashi1;
uchar num,num0,num1=0,num2=0,num3=0,num4=0;//后面加0为个位,后面加1为十位
void write_ds(uchar add,uchar date);
uchar read_ds(uchar add3);
void set_time();
void read_alarm();
//*************************************
//函数名称:delayms(uint xms)延时1ms函数。
//入口参数:xms
//出口参数:无
//*************************************
void delayms(uint xms)//延时函数,X毫秒延时
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void di()//蜂鸣器报警,叫一声,做按键声用
{
bz=0;
delayms(100);
bz=1;
}
//*************************************
//函数名称:write_cmd(uchar lcd_cmd)写命令函数
//入口参数:lcd_cmd
//出口参数:无
//*************************************
void write_cmd(uchar lcd_cmd)//写液晶命令函数
{
lcd_rs=0;
P1=lcd_cmd;
delayms(3);
lcd_en=1;
delayms(3);
lcd_en=0;
}
//*************************************
//函数名称:write_data(uchar lcd_data)写数据函数
//入口参数:data
//出口参数:无
//*************************************
void write_data(uchar lcd_data)//写液晶数据函数
{
lcd_rs=1;
lcd_en=0;
P1=lcd_data;
delayms(3);
lcd_en=1;
delayms(3);
lcd_en=0;
}
//*************************************
//函数名称:lcd与ds1c887与24c64与18b20初始化函数。
//入口参数:无
//出口参数:无
//*************************************
void lcdinit()
{
write_ds(0x0A,0X20);//打开振荡器
write_ds(0x0B,0x26);//设置24小时模式,数据二进制格式,开启闹铃中断
set_time();//设置上电默认时间
write_cmd(0x38);//基本指令操作
write_cmd(0x0e);//开显示,关光标,不闪烁
write_cmd(0x01);//清屏
write_cmd(0x06);//光标右移设置
write_cmd(0x80);
delayms(1);
for(num=0;num<16;num++)
{
write_data(table1[num]);//写入液晶固定部门的第一行
delayms(1);
}
write_cmd(0x80+0x40);
delayms(1);
for(num0=0;num0<15;num0++)
{
write_data(table2[num0]);//写入液晶固定部门的第二行
delayms(1);
}
}
void write_sfm(uchar add1,uchar date1)
{
uchar s1,g1;
s1=date1/10;
g1=date1%10;
write_cmd(0x80+0x40+add1);//第二行显示
write_data(table3[s1]);
write_data(table3[g1]);
}
void write_nyr(uchar add2,uchar date2)
{
uchar s2,g2;
s2=date2/10;
g2=date2%10;
write_cmd(0x80+add2);//第一行显示
write_data(table3[s2]);
write_data(table3[g2]);
}
void write_ds(uchar add,uchar date3)
{//给12c887写函数
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;//写地址
delayms(3);
dsas=0;
dsrw=0;
P0=date3;//写数据
delayms(3);
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add3)
{//读12C887函数
uchar date111;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add3;//写地址
dsas=0;
dsds=0;
P0=0xff;
date111=P0;//在读数据
delayms(1);
dsds=1;
dsas=1;
dscs=1;
return date111;
}
void set_time()
{//首次上电初始化时间函数,全部设置为0
write_ds(0,0);
write_ds(1,0);
write_ds(2,0);
write_ds(3,0);
write_ds(4,0);
write_ds(5,0);
write_ds(6,0);
write_ds(7,0);
write_ds(8,0);
write_ds(9,0);
}
void read_alarm()
{//读取闹钟值
amiao=read_ds(1);
afen=read_ds(3);
ashi=read_ds(5);
}
//*************************************
//函数名称:keyscan()键扫描函数。
//入口参数:无
//出口参数:???????待写入
//*************************************
void keyscan()//键扫描程序
{
if(flag1==1)//取消报警,按任意键取消报警,flag1为中断函数置1
{
if((key1==0)||(key2==0)||(key3==0)||(key4==0))
{
delayms(5);
if((key1==0)||(key2==0)||(key3==0)||(key4==0))
{
while(!(key1&&key2&&key3&&key4));di();
flag1=0;//清除闹钟报警标志
}
}
}
if(key1==0)//按键S1扫描,设置键,光标闪烁定位
{
delayms(5);
if(key1==0)
{
num1++;//记录按下次数
flag2=1;
if(num1==14)
{
num1=1;
}
while(!key1);di();
switch(num1)
{
case 1: write_cmd(0x80+0x40+10);//小时的十位,写地址指针
write_cmd(0x0f);//光标闪烁,写命令
break;
case 2: write_cmd(0x80+0x41);//小时的个位
write_cmd(0x0f);
break;
case 3: write_cmd(0x80+0x43);//分钟的十位
write_cmd(0x0f);
break;
case 4: write_cmd(0x80+0x44);//分钟的个位
write_cmd(0x0f);
break;
case 5: write_cmd(0x80+0x00);//年的千位
write_cmd(0x0f);
break;
case 6: write_cmd(0x80+0x01);//年的百位
write_cmd(0x0f);
break;
case 7: write_cmd(0x80+0x02);//年的十位
write_cmd(0x0f);
break;
case 8: write_cmd(0x80+0x03);//年的个位
write_cmd(0x0f);
break;
case 9: write_cmd(0x80+0x05);//月的十位
write_cmd(0x0f);
break;
case 10:write_cmd(0x80+0x06);//月的个位
write_cmd(0x0f);
break;
case 11:write_cmd(0x80+0x08);//日的十位
write_cmd(0x0f);
break;
case 12:write_cmd(0x80+0x09);//日的个位
write_cmd(0x0f);
break;
}
}
}
if(num1!=0)
{
if(key2==0)//按键S2扫描,增加键
{
delayms(5);
if(key2==0)
{
while(!key2);di();
switch(num1)
{
case 1:shi++;//小时的十位
if(shi>23)shi=0;
write_cmd(0x80+0x40+0);
write_data(table3[shi]);
break;
case 2:fen1++;//分钟的十位
if(fen1>6)fen1=0;
write_cmd(0x80+0x40+3);
write_data(table3[fen1]);
break;
case 3:fen2++;//分钟的个位
if(fen2>9)fen2=0;
write_cmd(0x80+0x40+4);
write_data(table3[fen2]);
break;
case 4:year3++;//年的千位
if(year3>9)year3=0;
write_cmd(0x80+0x00+1);
write_data(table3[year3]);
break;
case 5:year2++;//年的百位
if(year2>9)year2=0;
write_cmd(0x80+0x00+2);
write_data(table3[year2]);
break;
case 6:year1++;//年的十位
if(year1>9)year1=0;
write_cmd(0x80+0x00+3);
write_data(table3[year1]);
break;
case 7:year0++;//年的个位
if(year0>9)year0=0;
write_cmd(0x80+0x00+4);
write_data(table3[year0]);
break;
case 8:month++;
if(month>12)month=1;
write_cmd(0x80+0x00+6);
write_data(table3[month]);
break;
case 9:day++;
if(day>31)day=1;
write_cmd(0x80+0x00+9);
write_data(table3[day]);
break;
}
}
}
if(num1!=0)
{
if(key3==0)//按键S3扫描,减少键
{
delayms(5);
if(key3==0)
{
while(!key3);di();
switch(num1)
{
case 1:shi--;//小时的十位
if(shi<0)shi=23;
write_cmd(0x80+0x40+0);
write_data(table3[shi]);
break;
case 2:fen1--;//分钟的十位
if(fen1<0)fen1=9;
write_cmd(0x80+0x40+3);
write_data(table3[fen1]);
break;
case 3:fen2--;//分钟的个位
if(fen2<0)fen2=9;
write_cmd(0x80+0x40+4);
write_data(table3[fen2]);
break;
case 4:year3--;//年的千位
if(year3<0)year3=9;
write_cmd(0x80+0x00+1);
write_data(table3[year3]);
break;
case 5:year2--;//年的百位
if(year2<0)year2=9;
write_cmd(0x80+0x00+2);
write_data(table3[year2]);
break;
case 6:year1--;//年的十位
if(year1<0)year1=9;
write_cmd(0x80+0x00+3);
write_data(table3[year1]);
break;
case 7:year0--;//年的个位
if(year0<0)year0=9;
write_cmd(0x80+0x00+4);
write_data(table3[year0]);
break;
case 8:month--;
if(month<0)month=12;
write_cmd(0x80+0x00+6);
write_data(table3[month]);
break;
case 9:day--;
if(day<0)day=31;
write_cmd(0x80+0x00+9);
write_data(table3[day]);
break;
}
}
}
if(key4==0)//按键S4扫描,保存与查看闹钟交叉切换
{
delayms(5);
if(key4==0)
{
flag2=~flag2;
while(!key4);di();
if(flag2==0)
{//退出闹钟设置时保存数据
flag2=0;
write_cmd(0x0c);
write_ds(1,miao);
write_ds(3,fen);
write_ds(5,shi);
}
else
{//进入闹钟设置查看时间
read_alarm();
miao=amiao;
fen=afen;
shi=ashi;
write_cmd(0x01);//清屏
write_cmd(0x80+0x40);
write_data('R');
write_data('i');
write_data(':');
write_cmd(0x80+0x40+2);
write_sfm(4,shi);
write_data(':');
write_cmd(0x80+0x40+4);
write_sfm(7,fen);
write_data(':');
write_cmd(0x80+0x40+7);
write_sfm(10,amiao);
}
}
}
}
}
}
void main()
{
lcdinit();
write_ds(0,miao);
delayms(1);
write_ds(2,fen);
delayms(1);
write_ds(4,shi);
delayms(1);
write_ds(6,week);
delayms(1);
write_ds(7,day);
delayms(1);
write_ds(8,month);
delayms(1);
write_ds(9,year);
di();
while(1)
{
//keyscan();
year=read_ds(9);//读取12C887
delayms(3);
month=read_ds(8);
delayms(3);
day=read_ds(7);
delayms(3);
week=read_ds(6);
delayms(3);
shi=read_ds(4);
delayms(3);
fen=read_ds(2);
delayms(3);
miao=read_ds(0x0a);
delayms(3);
write_nyr(2,year);//送液晶显示
delayms(1);
write_nyr(5,month);
delayms(1);
write_nyr(8,day);
delayms(1);
write_sfm(0,shi);
delayms(1);
write_sfm(3,fen);
delayms(1);
write_sfm(6,miao);
delayms(1);
}
}
经本人反复查看,但就是未能发现问题,程序中keyscan()程序还未用到,只单单用了DS12C887的读取程序于LCD显示程序,自认为正确,可显示去全部为0,我可能是专了牛角了,还望大侠指教。程序经C51检查也无错误,实在是让我郁闷。
LCD显示如下
上排6个0是带表年月日
下排6个0是代表时分秒
|
|