历史上的今天
今天是:2024年12月25日(星期三)
2020年12月25日 | 用pcf8563做时钟
2020-12-25 来源:51hei

//---库函数声明及相关定义---//
#include #include #define uchar unsigned char #define uint unsigned int sbit SDA=P3^1; //数据 sbit SCL=P3^0; //时钟 #define LCDIO P1 //1602数据口 sbit rs=P2^0; //1602数据命令选择引脚 sbit rd=P2^1; //读写选择抖? sbit lcden=P2^2; //1602选通引脚 uchar code table[]={" 2010-11-29 MON"}; uchar code table1[]={" 15:45:00 "}; uchar code table2[]= "SUNMONTUEWESTHUFRISAT"; uchar g8563_Store[8]; /*时间交换区,全局变量声明*/ uchar code c8563_Store[8]={0x50,0x59,0x23,0x31,0x05,0x07,0x88,0x20}; /*写入时间初值:世纪,08年 7月 星期一 13日 07:59:00*/ sbit menu=P0^0;//菜单 sbit add=P0^1;//加一 sbit dec=P0^2;//减一 uchar second,minute,hour,day,month,year,week,count=0; void delay1602(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void write_com(uchar com)//1602写命令子程序 { rs=0;//RS是数据命令选择短,高电平写数据,低电平写命令 rd=0;//RD是读写选择短,高电平读,低电平写 lcden=0;//1602选通端,高电平选通,低电平禁止 P1=com; delay1602(5); lcden=1; delay1602(5); lcden=0; } void write_date(uchar date)//1602写数据子程序 { rs=1; //RS是数据命令选择短,高电平写数据,低电平写命令 rd=0; //RD是读写选择短,高电平读,低电平写 lcden=0; //1602选通端,高电平选通,低电平禁止 P1=date; delay1602(5); lcden=1; delay1602(5); lcden=0; } void init() { uchar num; lcden=0; write_com(0x38); //0011 1000B,功能模式设置,设置为8为数据口,两行显示,5*7点阵 write_com(0x0c); //0000 1011B,显示开及光标设置,关显示,显示光标,光标闪烁 write_com(0x06); //0000 0110B,显示光标移动设置,读或写一个字符,地址指针减一且光标减一,写一个字符屏幕显示不移动 write_com(0x01); //0000 0001B,显示清屏,数据指针和所有显示清屏 write_com(0x80); //1000 000B,关闭显示 delay1602(5); write_com(0x80); //1000 000B,设置为2行显示,写入第一行字符的地址,第一行地址是00-2F for(num=0;num<15;num++) { write_date(table[num]); //写入第一行数据 delay1602(5); } write_com(0x80+0x40); //1100 0000B,设置为2行显示,写入第二行字符的地址,第而行地址是40-67 for(num=0;num<15;num++) //写入第二行数据 { write_date(table1[num]);//写入第二行数据 delay1602(5); } } /******************************************** 内部函数,延时1 ********************************************/ void Delay() { // {P10=1;_nop_();P10=0;} _nop_(); _nop_(); /*根据晶振频率制定延时时间*/ } /******************************************** 内部函数,I2C开始 ********************************************/ void Start() { EA=0; SDA=1; SCL=1; Delay(); SDA=0; Delay(); SCL=0; } /******************************************** 内部函数,I2C结束 ********************************************/ void Stop() { SDA=0; SCL=0; Delay(); SCL=1; Delay(); SDA=1; Delay(); EA=1; } /******************************************** 内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读书据,ack=1; ********************************************/ void WriteACK(uchar ack) { SDA=ack; Delay(); SCL=1; Delay(); SCL=0; } /******************************************** 内部函数,等待ACK ********************************************/ void WaitACK() { uchar errtime=20; SDA=1; Delay(); /*读ACK*/ SCL=1; Delay(); while(SDA) { errtime--; if(!errtime) Stop(); } SCL=0; Delay(); } /******************************************** 内部函数.输出数据字节 入口:B=数据 ********************************************/ void writebyte(uchar wdata) { uchar i; for(i=0;i<8;i++) { if(wdata&0x80) SDA=1; else SDA=0; wdata<<=1; SCL=1; Delay(); SCL=0; } WaitACK(); //I2C器件或通讯出错,将会退出I2C通讯 } /******************************************** 内部函数.输入数据 出口:B ********************************************/ uchar Readbyte() { uchar i,bytedata; SDA=1; for(i=0;i<8;i++) { SCL=1; bytedata<<=1; bytedata|=SDA; SCL=0; Delay(); } return(bytedata); } /******************************************** 输出数据->pcf8563 ********************************************/ void writeData(uchar address,uchar mdata) { Start(); writebyte(0xa2); /*写命令*/ writebyte(address); /*写地址*/ writebyte(mdata); /*写数据*/ Stop(); } /******************************************** 输入数据<-pcf8563 ********************************************/ uchar ReadData(uchar address) /*单字节*/ { uchar rdata; Start(); writebyte(0xa2); /*写命令*/ writebyte(address); /*写地址*/ Start(); writebyte(0xa3); /*读命令*/ rdata=Readbyte(); WriteACK(1); Stop(); return(rdata); } void ReadData1(uchar address,uchar count,uchar * buff) /*多字节*/ { uchar i; Start(); writebyte(0xa2); /*写命令*/ writebyte(address); /*写地址*/ Start(); writebyte(0xa3); /*读命令*/ for(i=0;i buff[i]=Readbyte(); if(i WriteACK(1); Stop(); } /******************************************** 内部函数,读入时间到内部缓冲区 ********************************************/ void P8563_Read() { uchar time[7],century; ReadData1(0x02,0x07,time); century=time[5]; g8563_Store[0]=time[0]&0x7f; /*秒*/ g8563_Store[1]=time[1]&0x7f; /*分*/ g8563_Store[2]=time[2]&0x3f; /*小时*/ g8563_Store[3]=time[3]&0x3f; /*日*/ g8563_Store[4]=time[4]&0x07; /*星期*/ g8563_Store[5]=time[5]&0x1f; /*月*/ g8563_Store[6]=time[6]&0xff; /*年*/ g8563_Store[7]=century&0x80; /*去世纪,00为2000,80为1900*/ if(g8563_Store[7]==0x00)g8563_Store[7]=20; if(g8563_Store[7]==0x80)g8563_Store[7]=19; } /******************************************** 读入时间到内部缓冲区----外部调用 ********************************************/ void P8563_gettime() { P8563_Read(); if(g8563_Store[0]==0) P8563_Read(); /*如果为秒=0,为防止时间变化,再读一次*/ } /******************************************** 写时间修改值 ********************************************/ void P8563_settime() { writeData(2,g8563_Store[0]);//秒 writeData(3,g8563_Store[1]);//分 writeData(4,g8563_Store[2]);//时 writeData(5,g8563_Store[3]);//日 writeData(6,g8563_Store[4]);//星期 if(g8563_Store[7]==0x20)g8563_Store[5]=(g8563_Store[5]&0x3F);//判断世纪 if(g8563_Store[7]==0x19)g8563_Store[5]=(g8563_Store[5]|0x80);//判断世纪 writeData(7,g8563_Store[5]);//月 writeData(8,g8563_Store[6]);//年 } /******************************************** P8563的初始化 ********************************************/ void P8563_init() { uchar i; if((ReadData(0xa)&0x3f)!=0x8) /*检查是否第一次启动,是则初始化时间*/ { for(i=0;i<8;i++) g8563_Store[i]=c8563_Store[i]; /*初始化时间*/ P8563_settime(); writeData(0x0,0x00); writeData(0xa,0x8); /*8:00报警*/ writeData(0x1,0x12); /*报警有效*/ writeData(0xd,0xf0); } } void DisplaySecond(uchar x) //写入1602秒 { uchar i,j; i=x/10; j=x%10; write_com(0xc7); //写1602的命令字,设置秒的数据地址为47H write_date(0x30+i); //写入秒的低位 write_date(0x30+j); //写入秒的高位 } void DisplayMinute(uchar x) //写入1602分 { uchar i,j; i=x/10;
史海拾趣




