AVRM16的PCF8563源码
扫描二维码
随时随地手机看文章
#include #include #include #include #include "pcf8563.h" #include "lcd.h" #include "keyboard.h" //时钟芯片数据接口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发送开始位 { DDRA|=0x03; //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出 DATE_CLK_set; //将时钟端口(SCL)设为高 DATE_DT_set; //将数据端口(SDA)设为高 delayus(2); DATE_DT_clr; //将数据端口(SDA)设为低 delayus(2); DATE_DT_set; } // *********************************************** // // *** This routine will send the I2C Stop Bit *** // // *********************************************** // void I2C_Stop (void) //I2C发送停止位 { DDRA|=0x03; //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出 DATE_DT_clr; //将数据端口(SDA)设为低 DATE_CLK_set; //将时钟端口(SCL)设为高 delayus(2); DATE_DT_set; //将数据端口(SDA)设为高 delayus(2); } // *********************************************************************** // // *** 发送完毕检查校验位,有校验位返回1,无返回0 *** // // *********************************************************************** // unsigned char I2C_Ackn(void) { unsigned char errtime=255; //DATE_CLK_clr; // 将时钟端口(SCL)设为低 DDRA|=0x02; DDRA&=0xFE; // 设置数据口(SDA)为输入 delayus(2); while(PINA&0x01) { errtime--; if (!errtime) //errtime=0,没接收到 { I2C_Stop(); return 0x00; } } DATE_CLK_set; delayus(2); DATE_CLK_clr; // 将时钟端口(SCL)设为低 delayus(2); return 0x01; //true } // ******************************************************** // // *** This routine will write a byte to the I2C device *** // // ******************************************************** // void Write_I2C_Byte(unsigned char byte) //写一个字节到I2C设备 { unsigned char i; DDRA|=0x03; //将PA0数据端口(SDA)设为输出 for (i = 0; i < 8; i++) //传送8位数据 { DATE_CLK_clr; //将时钟端口(SCL)设为低 if((byte & 0x80)) DATE_DT_set; // 设置 SDA 位 else DATE_DT_clr; // 清除 SDA 位 delayus(2); DATE_CLK_set; //将时钟端口(SCL)设为高 asm("nop"); byte = byte << 1; //将输出数据左移一位 } DATE_CLK_clr; // 校验标志位 (每传送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设备的数据 { unsigned char i,buff = 0; delayus(2); DDRA|=0x02; //PA1为时钟,输出 DDRA&=0xfe; //设置数据口(SDA)为输入 for (i = 0; i < 8; i++) { DATE_CLK_clr; // 将时钟端口(SCL)设为低 delayus(2); DATE_CLK_set; //将时钟端口(SCL)设为高 delayus(2); // 在 SDA 位上读取数据 if ( PINA&=0x01 ) buff++; buff = (buff << 1); delayus(2); } DDRA|=0x03; //设为输出,发送校验位 DATE_DT_clr; delayus(2); DATE_CLK_set; delayus(2); DATE_CLK_clr; //将时钟端口(SCL)设为高 //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) //获得当前秒数 { 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(); } //设置时间 (**年/**月/**日 **时:**分) 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]); //设置年 SetPCF8563(7,numb[2]); //设置月 SetPCF8563(5,numb[4]); //设置日 SetPCF8563(4,numb[6]); //设置时 SetPCF8563(3,numb[8]); //设置分 } //显示时间函数,屏幕第一行显示 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)); }