#include #include #include #include #include "pcf8563.h" #include "lcd.h" #include "keyboard.h" //時鐘芯片數(shù)據(jù)接口PA0 #define DATE_DT_set asm("sbi 0x1B,0") #define DATE_DT_clr asm("cbi 0x1B,0") //時鐘芯片時鐘接口PA1 #define DATE_CLK_set asm("sbi 0x1B,1") #define DATE_CLK_clr asm("cbi 0x1B,1") unsigned char old_minute,new_minute; unsigned char number1[13]= { 0x30, //0 0x31, //1 0x32, //2 0x33, //3 0x34, //4 0x35, //5 0x36, //6 0x37, //7 0x38, //8 0x39, //9 0x20, //空格 0x2E, //. 0x3A //: }; void delayus(unsigned char i) { while(i) i--; } // ************************************************ // // *** This routine will send the I2C Start Bit *** // // ************************************************ // void I2C_Start (void) //I2C發(fā)送開始位 { DDRA|=0x03; //將PA0數(shù)據(jù)端口(SDA),PA1時鐘端口(SCL)設(shè)為輸出 DATE_CLK_set; //將時鐘端口(SCL)設(shè)為高 DATE_DT_set; //將數(shù)據(jù)端口(SDA)設(shè)為高 delayus(2); DATE_DT_clr; //將數(shù)據(jù)端口(SDA)設(shè)為低 delayus(2); DATE_DT_set; } // *********************************************** // // *** This routine will send the I2C Stop Bit *** // // *********************************************** // void I2C_Stop (void) //I2C發(fā)送停止位 { DDRA|=0x03; //將PA0數(shù)據(jù)端口(SDA),PA1時鐘端口(SCL)設(shè)為輸出 DATE_DT_clr; //將數(shù)據(jù)端口(SDA)設(shè)為低 DATE_CLK_set; //將時鐘端口(SCL)設(shè)為高 delayus(2); DATE_DT_set; //將數(shù)據(jù)端口(SDA)設(shè)為高 delayus(2); } // *********************************************************************** // // *** 發(fā)送完畢檢查校驗位,有校驗位返回1,無返回0 *** // // *********************************************************************** // unsigned char I2C_Ackn(void) { unsigned char errtime=255; //DATE_CLK_clr; // 將時鐘端口(SCL)設(shè)為低 DDRA|=0x02; DDRA&=0xFE; // 設(shè)置數(shù)據(jù)口(SDA)為輸入 delayus(2); while(PINA&0x01) { errtime--; if (!errtime) //errtime=0,沒接收到 { I2C_Stop(); return 0x00; } } DATE_CLK_set; delayus(2); DATE_CLK_clr; // 將時鐘端口(SCL)設(shè)為低 delayus(2); return 0x01; //true } // ******************************************************** // // *** This routine will write a byte to the I2C device *** // // ******************************************************** // void Write_I2C_Byte(unsigned char byte) //寫一個字節(jié)到I2C設(shè)備 { unsigned char i; DDRA|=0x03; //將PA0數(shù)據(jù)端口(SDA)設(shè)為輸出 for (i = 0; i < 8; i++) //傳送8位數(shù)據(jù) { DATE_CLK_clr; //將時鐘端口(SCL)設(shè)為低 if((byte & 0x80)) DATE_DT_set; // 設(shè)置 SDA 位 else DATE_DT_clr; // 清除 SDA 位 delayus(2); DATE_CLK_set; //將時鐘端口(SCL)設(shè)為高 asm("nop"); byte = byte << 1; //將輸出數(shù)據(jù)左移一位 } DATE_CLK_clr; // 校驗標(biāo)志位 (每傳送8位,有一校驗位) if (I2C_Ackn()==0) // Check for acknowledge from I2C device yonghudenglu(); //DATE_CLK_clr; } // ********************************************************* // // *** This routine will read a byte from the I2C device *** // // ********************************************************* // unsigned char Read_I2C_Byte(void) //讀取I2C設(shè)備的數(shù)據(jù) { unsigned char i,buff = 0; delayus(2); DDRA|=0x02; //PA1為時鐘,輸出 DDRA&=0xfe; //設(shè)置數(shù)據(jù)口(SDA)為輸入 for (i = 0; i < 8; i++) { DATE_CLK_clr; // 將時鐘端口(SCL)設(shè)為低 delayus(2); DATE_CLK_set; //將時鐘端口(SCL)設(shè)為高 delayus(2); // 在 SDA 位上讀取數(shù)據(jù) if ( PINA&=0x01 ) buff++; buff = (buff << 1); delayus(2); } DDRA|=0x03; //設(shè)為輸出,發(fā)送校驗位 DATE_DT_clr; delayus(2); DATE_CLK_set; delayus(2); DATE_CLK_clr; //將時鐘端口(SCL)設(shè)為高 //DATE_DT_clr; return buff; // 返回讀取值 } //讀8563寄存器 unsigned char rtc_read(unsigned char address) { unsigned char d; I2C_Start(); Write_I2C_Byte(0xa2); Write_I2C_Byte(address); I2C_Start(); Write_I2C_Byte(0xa3); d=Read_I2C_Byte(); d=d>>1; I2C_Stop(); //for(;;){} return d; } //////////////////////////////////////////////////////////////////////////////// //寫8563寄存器 void rtc_write(unsigned char address,unsigned char data1) { I2C_Start(); Write_I2C_Byte(0xa2); Write_I2C_Byte(address); Write_I2C_Byte(data1); I2C_Stop(); } //////////////////////////////////////////////////////////////////////////////// void rtc_start(void) { rtc_write(0,0); } //////////////////////////////////////////////////////////////////////////////// void rtc_stop(void) { rtc_write(0,0x20); } void GetPCF8563(unsigned char *time) { CLI(); *time=(rtc_read(2)&0x7f); //寄存器0x02為秒寄存器 *(time+1)=(rtc_read(3)&0x7f); //寄存器0x03為分寄存器 *(time+2)=(rtc_read(4)&0x3f); //寄存器0x04為時寄存器 *(time+3)=(rtc_read(5)&0x3f); //寄存器0x05為天寄存器 *(time+4)=(rtc_read(7)&0x1f); //寄存器0x07為月寄存器 *(time+5)=(rtc_read(8)); //寄存器0x08為年寄存器 SEI(); } unsigned char get_second(void) //獲得當(dāng)前秒數(shù) { unsigned i,j; i=(rtc_read(2)&0x7f); //寄存器0x02為秒寄存器 j=(i&0x0f)+(i>>4)*10; return j; } //////////////////////////////////////////////////////////////////////////////// void SetPCF8563(unsigned char adds,unsigned char data) { CLI(); rtc_stop(); rtc_write(adds,data); rtc_start(); SEI(); } //設(shè)置時間 (**年/**月/**日 **時:**分) void set8563(void) { unsigned char maini=0,mainj=0,numb[12],newkey; unsigned char sign=0; unsigned char *time; unsigned char displayn[12]; time=numb; while((mainj<10)||(sign==0)) { if(kbscan()!=0x20) { maini=kbscan(); while(kbscan()==maini) asm("nop"); if(maini<10) { numb[mainj]=maini; displayn[mainj]=number1[maini]; mainj++; } else if(maini==12) { if(mainj>0) mainj--; numb[mainj]=number1[10]; displayn[mainj]=number1[10]; } else if((mainj>=10)&&(maini==13)) { sign=1; } display(0x80,displayn[0],displayn[1]); display(0x81,0x2f,displayn[2]); display(0x82,displayn[3],0x2f); display(0x83,displayn[4],displayn[5]); display(0x84,0x20,0x20); display(0x85,displayn[6],displayn[7]); display(0x86,0x3a,displayn[8]); display(0x87,displayn[9],0x20); } } numb[0]=(numb[0]<<4)+(numb[1]&0x0F); //年 numb[2]=(numb[2]<<4)+(numb[3]&0x0F); //月 numb[4]=(numb[4]<<4)+(numb[5]&0x0F); //日 numb[6]=(numb[6]<<4)+(numb[7]&0x0F); //時 numb[8]=(numb[8]<<4)+(numb[9]&0x0F); //分 SetPCF8563(8,numb[0]); //設(shè)置年 SetPCF8563(7,numb[2]); //設(shè)置月 SetPCF8563(5,numb[4]); //設(shè)置日 SetPCF8563(4,numb[6]); //設(shè)置時 SetPCF8563(3,numb[8]); //設(shè)置分 } //顯示時間函數(shù),屏幕第一行顯示 void displaytime(unsigned char *time) { GetPCF8563(time); new_minute=*(time+1); if(new_minute!=old_minute) { display(0x80,0x30+(*(time+5)>>4),0x30+(*(time+5)&0x0F)); display(0x81,0x2f,0x30+(*(time+4)>>4)); display(0x82,0x30+(*(time+4)&0x0F),0x2f); display(0x83,0x30+(*(time+3)>>4),0x30+(*(time+3)&0x0F)); display(0x84,0x20,0x20); display(0x85,0x30+(*(time+2)>>4),0x30+(*(time+2)&0x0F)); display(0x86,0x3a,0x30+(*(time+1)>>4)); display(0x87,0x30+(*(time+1)&0x0F),0x20); old_minute=new_minute; } //display(0x98,0x30+(*time>>4),0x30+(*time&0x0F)); }