/******************************************************
时钟模块
时钟由FPC8563产生,程序如下:
作者:sjx 2008-7-27 QQ:307870154
*********************************************************/
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit scl1=P2^0;//定义数码管时钟线
sbit sda1=P2^1;//定义数码管数据线
sbit scl3=P2^4;//定义数码管时钟线
sbit sda3=P2^5;//定义数码管数据线
sbit scl4=P2^6;//定义数码管时钟线
sbit sda4=P2^7;//定义数码管数据线
sbit scl=P0^6;//定义8563 I2C的时钟线
sbit sda=P0^7; //定义8563 I2C的数据线
uchar a,miao,shi,fen,number, b;
uint day,week,month,year;
uchar code tab[]={0x11,0x7d,0x23,0x29,0x4d, // 0 1 2 3 4 //
0x89,0x81,0x3d,0x01,0x09, // 5 6 7 8 9 //
0x05,0xc1,0x93,0x61,0x83,0x87 }; // A B C D E F
void delay()
{ ;; }
//=========8563起始信号子程序===============
void start()
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
//==========8563终止信号子程序================
void stop()
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
//===========8563应答信号子程序====================
void respons()
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++; //若无应答,重新开始发送地址
scl=0;
delay();
}
//===========8563总线初始化子程序=======================
void init()
{
sda=1;
delay();
scl=1;
delay();
}
//===========写入1字节子程序======================
void write_byte(uchar date)
{
uchar i,temp;
temp=date; //写入数据date
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay();
sda=CY; //往数据线送date最高位,循环8次送完date
delay();
scl=1;
delay();
scl=0;
delay();
}
sda=1; //释放数据总线,以便读取应答信号
delay();
}
//===========读取1字节子程序============================
uchar read_byte()
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++) //读回时是一位一位的所以要读8次
{
scl=1; // scl置1数据才稳定才可以读取数据
delay();
k=(k<<1)|sda; //sda送过来的数据送到k的最底位,循环8次从最高位读完sda上的数据
scl=0;
delay();
}
return k; //程序执行完返回k的值
}
//============延时子程序=====================================
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
//===========写一8位数据子程序===================================
void write_add(uchar address,uchar date)
{
start(); //调用起始信号子程序,开始写入信号
write_byte(0xa2); //找芯片所在地址
respons(); //调用应答信号
write_byte(address);//找芯片内部存储器地址
respons();
write_byte(date);// 写入数据,写进芯片内部存储器
respons();
stop(); //调用终止信号子程序,终止信号写入
}
//===========读一8位数据子程序 ================================
uchar read_add(uchar address)
{
uchar date;
start(); //调用起始信号子程序
write_byte(0xa2); //取芯片地址
respons();
write_byte(address);//取芯片内部存储器地址
respons();
start(); //调用起始信号子程序,开始读取信号
write_byte(0xa3);//芯片读地址
respons();
date=read_byte();//把读取字节子程序的返回值给date
stop();
return date; // 程序执行完返回date的值
}
//===============写时间子程序=============
void write_8563(uchar w_miao,uchar w_fen,uchar w_shi,uchar w_day,uchar w_week,uchar w_month,uchar w_year)
{ init();
start();
write_add(0x00,0x00);
write_add(0x01,0x00);
write_add(0x02, w_miao);
delay1(100);
write_add(0x03,w_fen);
delay1(100);
write_add(0x4,w_shi);
delay1(100);
write_add(0x05,w_day);
delay1(100);
write_add(0x06,w_week);
delay1(100);
write_add(0x7,w_month);
delay1(100);
write_add(0x8,w_year);
delay1(100);
}
//===============读时间子程序============
void read_8563()
{
miao=read_add(0x02)&0x7f;//获取秒数据
miao=((miao&0xf0)>>4&0x0f)*10+(miao&0x0f);//BCD码转换成10进制数
if(miao>=60){miao=0;}
fen=read_add(0x03)&0x7f;//获取分钟
fen=((fen&0xf0)>>4&0x0f)*10+(fen&0x0f);//BCD码转换成10进制数
if(fen>=60){fen=0;}
shi=read_add(0x04)&0x3f;//获取小时
shi=((shi&0xf0)>>4&0x0f)*10+(shi&0x0f);//BCD码转换成10进制数
if(shi>=24){shi=0;}
day=read_add(0x05)&0x3f;//获取日数据
day=(( day&0xf0)>>4&0x0f)*10+( day&0x0f);//BCD码转换成10进制数
if( day>=31){ day=0;}
week=read_add(0x06)&0x07;//获取星期
if(week>6){week=0;}
month=read_add(0x07)&0x1f;//获取月
month=((month&0xf0)>>4&0x0f)*10+(month&0x0f);//BCD码转换成10进制数
if(month>=24){month=0;}
year=read_add(0x08)&0xff;//获取年
shi=((year&0xf0)>>4&0x0f)*10+(year&0x0f);//BCD码转换成10进制数
delay1(100);
}
/********************************************************
********************************************************/
//============数码管移位子程序===================
void shift1()
{
uchar i,t;
number=tab;
scl1=0;
for(i=0;i<8;i++)
{
t=number&0x80; //与、判断,0 1, 0x80为二进制数10000000
sda1=t; // 往数据线送最高位
scl1=1; //上跳
number=number<<1; //左移一位
scl1=0; //下跳
}
}
void shift3()
{
uchar i,t;
number=tab;
scl3=0;
for(i=0;i<8;i++)
{
t=number&0x80; //与、判断,0 1, 0x80为二进制数10000000
sda3=t; // 往数据线送最高位
scl3=1; //上跳
number=number<<1; //左移一位
scl3=0; //下跳
}
}
void shift4()
{
uchar i,t;
number=tab;
scl4=0;
for(i=0;i<8;i++)
{
t=number&0x80; //与、判断,0 1, 0x80为二进制数10000000
sda4=t; // 往数据线送最高位
scl4=1; //上跳
number=number<<1; //左移一位
scl4=0; //下跳
}
}
//============数码管显示程序========================
void dispaly()
{
b=miao%10;//秒个位
shift3();
b=miao/10;//秒十位
shift3();
b=fen%10;
shift4();
b=fen/10;
shift4();
b=shi%10;
shift4();
b=shi/10;
shift4();
b=week%10;//秒个位
shift1();
b=day%10;
shift1();
b=day/10;
shift1();
b=month%10;
shift1();
b=month/10;
shift1();
b=year%10; //年个位
shift1();
b=(year%100)/10;//年十位
shift1();
b=(year%1000)/100;//年百位
shift1();
b=year/1000;
shift1();
delay1(500);
}
//===========主程序=======================================================
void main()
{
init();
delay1(500);
write_8563(0x50,0x59,0x23,0x11,0x01,0x09,0x2008);//初始化秒 分 时,日,星期,月,年
delay1(500); //调用延时函数
while(1)
{
read_8563(); //读取秒 时 分
dispaly(); //显示秒 分 时
}
}
此程序显示读取年和小时那里出错了。单独读取时 分 秒是没有错 但是同时读取年月日星期时分秒时,读不出小时。而且年的千位也是一直读不出请高手帮忙改正谢拉
********************************************************/
/*内部函数,PCF8563 开始*/
void Start(void)
{
SDA_ON; //SET
delay_us(2);
SCL_ON;
delay_us(2);
SDA_OFF;
delay_us(2);
SCL_OFF;
return;
}
/*内部函数,PCF8563 结束*/
void Stop(void)
{
SDA_OFF;
SCL_OFF;
delay_us(2);
SCL_ON;
delay_us(2);
SDA_ON;
delay_us(2);
return;
}
/*内部函数,输出ACK=0*/
void WriteACK(void)
{
SDA_OFF;
delay_us(2);
SCL_ON;
delay_us(2);
SCL_OFF;
return;
}
/*内部函数,输出ACK=1*/
void writenoack(void)
{
SDA_ON;
delay_us(2);
SCL_ON;
delay_us(2);
SCL_OFF;
return;
}
// GPIO0->DIR |=(1<<9); //P0.9 (P09 28) DS_DA OUTPUT PCF8563 SCLK
// GPIO0->DIR |=(1<<10); //P0.10(P010 29) DS_RST OUTPUT PCF8563 SDA
/*内部函数,等待ACK*/
void WaitACK(void)
{ unsigned char errtime=20;
SDA_ON;
delay_us(2); /*读ACK*/
SCL_ON;
delay_us(2);
GPIO0->DIR&=~(1<<10);
delay_us(2);
while((GPIO0->DATA&(1<<10))==(1<<10))
{
if(errtime>0) {errtime--;}
else{LED_SHOW=0X55;}
//delay_us(2);
//if(!errtime) Stop();
}
SCL_OFF;
GPIO0->DIR |=(1<<10);
delay_us(2);
return;
}
// GPIO0->DIR |=(1<<9); //P0.9 (P09 28) DS_DA OUTPUT PCF8563 SCLK
// GPIO0->DIR |=(1<<10); //P0.10(P010 29) DS_RST OUTPUT PCF8563 SDA
/**内部函数.输出数据字节 入口:B=数据*/
void writebyte(unsigned char wdata)
{
unsigned char i;
SCL_OFF;
for(i=8;i>0;i--)
{
if(wdata&0x80!=0) {SDA_ON;}
else {SDA_OFF;}
wdata<<=1;
SCL_ON;
delay_us(2);
SCL_OFF;
}
WaitACK();
return;
}
// GPIO0->DIR |=(1<<9); //P0.9 (P09 28) DS_DA OUTPUT PCF8563 SCLK
// GPIO0->DIR |=(1<<10); //P0.10(P010 29) DS_RST OUTPUT PCF8563 SDA
/*内部函数.输入数据 出口:B*/
unsigned char Readbyte(void)
{
unsigned char i,bytedata;
//SDA_ON;
GPIO0->DIR&=~(1<<10);
delay_us(2);
for(i=0;i<8;i++)
{
SCL_ON;
bytedata<<=1;
if((GPIO0->DATA&(1<<10))==(1<<10)) {bytedata|=0X01;}
SCL_OFF;
delay_us(2);
}
GPIO0->DIR |=(1<<10);
delay_us(2);
return(bytedata);
}
/**输出数据->pcf8563*/
void writeData(unsigned char address,unsigned char mdata)
{
Start();
writebyte(0xa2); /*写命令*/
writebyte(address); /*写地址*/
writebyte(mdata); /*写数据*/
Stop();
return;
}
/*输入数据<-pcf8563*/
unsigned char ReadData(unsigned char address) /*单字节*/
{
unsigned char rdata;
Start();
writebyte(0xa2); /*写命令*/
writebyte(address); /*写地址*/
Start();
writebyte(0xa3); /*读命令*/
rdata=Readbyte();
writenoack();
Stop();
return(rdata);
}
/*
void ReadData1(unsigned char address,unsigned char count,unsigned char *buff) //多字节
{
unsigned char i;
Start();
writebyte(0xa2); //写命令
writebyte(address); //写地址
Start();
writebyte(0xa3); //读命令
for(i=0;i<count;i++)
{
time_get[i]=Readbyte();
if(i<count-1) WriteACK();
}
writenoack();
Stop();
return;
}
*/
void ReadData1(unsigned char address) //多字节
{
unsigned char i;
Start();
writebyte(0xa2); //写命令
writebyte(0X02); //写地址
LED_SHOW=0X01;
Start();
writebyte(0xa3); //读命令
for(i=0;i<6;i++)
{
time[i]=Readbyte();
WriteACK();
}
time[6]=Readbyte();
writenoack();
Stop();
return;
}
/*内部函数,读入时间到内部缓冲区*/
void P8563_Read(void)
{
ReadData1(0x02); //02-08
time_buf[0]=time[6]>>4&0x0F; //08H 年
time_buf[1]=time[6]&0x0F;
//if(time_buf[0]==0) {time_buf[0]=20;}
time_buf[2]=time[5]>>4&0x01; //07H 月
time_buf[3]=time[5]&0x0F;
//if(time_buf[2]==0) {time_buf[2]=20;}
time_buf[4]=time[4]&0x07; //06H 星期
time_buf[5]=time[3]>>4&0x03; //05H 日
time_buf[6]=time[3]&0x0F;
//if(time_buf[5]==0) {time_buf[5]=20;}
time_buf[7]=time[2]>>4&0x03; //04H 时
time_buf[8]=time[2]&0x0F;
//if(time_buf[7]==0) {time_buf[7]=20;}
time_buf[9]=time[1]>>4&0x03; //03H 分
time_buf[10]=time[1]&0x0F;
//if(time_buf[9]==0) {time_buf[9]=20;}
time_buf[11]=time[0]>>4&0x07; //02H 秒
time_buf[12]=time[0]&0x0F;
//if(time_buf[11]==0) {time_buf[11]=20;}
/*
time_buf[0]=time[0]&0x7f; //秒
time_buf[1]=time[1]&0x7f; //分
time_buf[2]=time[2]&0x3f; //小时
time_buf[3]=time[4]&0x07; //星期
*/
return;
}
/**写时间修改值*/
void P8563_settime(void)
{
unsigned char i;
time_buf[0]=1;time_buf[1]=5; //08H 年 //2015 1 1-11:59:00 星期四
time_buf[2]=0;time_buf[3]=1; //07H 月
time_buf[4]=4; //06H 星期四
time_buf[5]=0;time_buf[6]=1; //05H 日
time_buf[7]=1;time_buf[8]=1; //04H 时
time_buf[9]=5;time_buf[10]=9; //03H 分
time_buf[11]=0;time_buf[12]=0; //02H 秒
i=time_buf[11]*10+time_buf[12]; writeData(2,i); //02H 秒
i=time_buf[9]*10+time_buf[10]; writeData(3,i); //03H 分
i=time_buf[7]*10+time_buf[8]; writeData(4,i); //04H 时
i=time_buf[5]*10+time_buf[6]; writeData(5,i); //05H 日
i=time_buf[4]; writeData(6,i); //06H 星期四
i=time_buf[2]*10+time_buf[3]; writeData(7,i); //07H 月
i=time_buf[0]*10+time_buf[1]; writeData(8,i); //08H 年
return;
}
//volatile unsigned char time_buf[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
/* 0十年 年 2 月 4星期 5 日 7 小时 9 分钟 11 秒*/
//writeData(ADDRESS,DATA);
//Time and date registers
//02H: VL_seconds (0-59)
//03H: Minutes (0-59)
//04H: Hours (0-23)
//05H: Days (1-31)
//06H: Weekdays (0-6)
//07H: Century_months (1-12)
//08H: Years (0-99)
/**P8563的初始化-----外部调用*/
void P8563_init(void)
{
//unsigned char i;
if((ReadData(0x0a)&0x3f)!=0x8) //检查是否第一次启动,是则初始化时间
{
P8563_settime();
}
//else
// {
// }
return;
}
一周热门 更多>