PCF8563实时时钟芯片51单片机简单例程
做时钟显示如果用单片机做,会产生很大的累积误差,本程序采用时钟芯片PCF8563 一:芯片主要电气特性: 1)大工作电压范围:1.0~5.5V 2)400KHz 的 I2C 总线接口(VDD=1.8~5.5V 时)。 时钟频率最大400KH 3)i2C 总线从地址:读,0A3H;写,0A2H . 二:管脚 电路接线图: 单片机和PCF8563通信采用IIC协议,单片机读取时钟芯片内寄存器数据或者时钟芯片输出时间信息给单片机. 本程序知识简单的显示时间,也没有加入芯片损坏延时判断应答子函数.,只是了解芯片使用方法 IIC总线和LCD1602函数包属于标准代码。 IIC协议子函数包 #include <reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit SDA=P2^2; //SDA口设置 sbit SCL=P2^3; //SCL口设置 void delay() //略微延时 6us约>4.7us { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } void iic_start() //启动信号 { SDA=1; SCL=1; delay(); SDA=0; delay(); SCL=0; } void iic_stop() //停止信号 { SDA=0; SCL=1; delay(); SDA=1; delay(); SCL=0; } void iic_ack() //应答信号 { uchar i=0; SCL=1; delay(); while((SDA==1)&&(i<255)) i++; SCL=0; delay(); } void iic_send_byte(uchar bat) //发送数据 { uchar i,temp; temp=bat; for(i=0;i<=7;i++) { temp=temp<<1; SCL=0; SDA=CY; delay(); SCL=1; delay(); } SCL=0; delay(); SDA=1; delay(); } uchar iic_rev() //接受数据 { uchar temp,i; SCL=0; delay(); SDA=1; for(i=0;i<=7;i++) { SCL=1; delay(); temp=(temp<<1)|SDA; SCL=0; delay(); } delay(); return temp; } void iic_send_add_byte(uchar add,uchar bat) //向某个地址发送某数据 { iic_start(); iic_send_byte(0xa2); iic_ack(); iic_send_byte(add); iic_ack(); iic_send_byte(bat); iic_ack(); iic_stop(); } uchar iic_rec_add_byte(uchar add) //从某个地址读出数据 { uchar temp; iic_start(); iic_send_byte(0xa2); iic_ack(); iic_send_byte(add); iic_ack(); iic_start(); iic_send_byte(0xa3); iic_ack(); temp=iic_rev(); iic_stop(); return temp; } LCD1602函数包: **********************************/ #define LCD1602_DATAPINS P0 sbit LCD1602_E=P2^7; sbit LCD1602_RW=P2^5; sbit LCD1602_RS=P2^6; void Delay1us(uint a) { uint b,c; for(c=a;c>0;c--) for(b=110;b>0;b--); } void LCD1602_WriteCom(uchar com) //写入命令 { LCD1602_E=0; LCD1602_RS=0; LCD1602_RW=0; LCD1602_DATAPINS=com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改 Delay1us(10); LCD1602_E=1; Delay1us(10); LCD1602_E=0; Delay1us(10); LCD1602_DATAPINS=com<<4; Delay1us(10); LCD1602_E=1; Delay1us(10); LCD1602_E=0; } void LCD1602_WriteData(uchar dat) //写入数据 { LCD1602_E=0; LCD1602_RS=1; LCD1602_RW=0; LCD1602_DATAPINS=dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改 Delay1us(10); LCD1602_E=1; Delay1us(10); LCD1602_E=0; LCD1602_DATAPINS=dat<<4; Delay1us(10); LCD1602_E=1; Delay1us(10); LCD1602_E=0; } void LCD1602_Init() //LCD初始化子程序 { LCD1602_WriteCom(0x32); //将8位总线转为4位总线 LCD1602_WriteCom(0x28); //在四位线下的初始化 LCD1602_WriteCom(0x0c); //开显示不显示光标 LCD1602_WriteCom(0x06); //写一个指针加1 LCD1602_WriteCom(0x01); //清屏 LCD1602_WriteCom(0x80); //设置数据指针起点 } //----- 主函数--------- #include <reg52.h> #include "lcd.h" #include "iic.h" //-----------延时用于稳定------------- void delay_kk(uint k) { while(k--); } //------------------------------BCD码讲解--- 比如十六进制数0x56 如果代表BCD码,则其就是代表10进制的56 但是在计算机里面如果用于计算他就是86(十进制),所以后面例出BCD转10进制子函数 PCF8563显示的数都是BCD码 //-----------时间预设定值--------- void time_init() { iic_send_add_byte(0x02,0x50); //0秒 iic_send_add_byte(0x03,0x59); //0分钟 iic_send_add_byte(0x04,0x23); //0小时 iic_send_add_byte(0x05,0x26); //26号 iic_send_add_byte(0x07,0x05); //5月 20世纪的 iic_send_add_byte(0x08,0x14); //2014年 } //----------------PCF8563初始化----------------- void pcf_init() { iic_send_add_byte(0x00,0x00); //启动时钟 } //----------------BCD转10进制----------- uchar bcd_dec(uchar bat) { uchar temp1,temp2,tol; temp1=bat&0x0f; temp2=(bat&0xf0)>>4; tol=temp2*10+temp1; return tol; } //------------LCD1602显示:年,月,日,小时,分钟,秒, void display_time(uchar sec,min,hour,dat,moom,year) { LCD1602_WriteCom(0x80); LCD1602_WriteData('_'); LCD1602_WriteData('2'); LCD1602_WriteData('0'); LCD1602_WriteData(year/10+48); LCD1602_WriteData(year%10+48); LCD1602_WriteData('/'); LCD1602_WriteData(moom+48); LCD1602_WriteData('/'); LCD1602_WriteData(dat/10+48); LCD1602_WriteData(dat%10+48); LCD1602_WriteCom(0xc4); LCD1602_WriteData(hour/10+48); LCD1602_WriteData(hour%10+48); LCD1602_WriteData(':'); LCD1602_WriteData(min/10+48); LCD1602_WriteData(min%10+48); LCD1602_WriteData(':'); LCD1602_WriteData(sec/10+48); LCD1602_WriteData(sec%10+48); } void main() { uchar sec,min,hour,dat,moom,year,sec1,min1,hour1,dat1,moom1,year1; //PCF8563读出的变量和代转换成的十进制变量 LCD1602_Init(); iic_send_add_byte(0x00,0x20); // 关闭时钟 delay_kk(1000); time_init(); //时钟芯片初始时间设置 pcf_init(); delay_kk(1000); while(1) { sec=0x7f&iic_rec_add_byte(0x02); //读取秒 min=0x7f&iic_rec_add_byte(0x03); //读取分钟 hour=0x3f&iic_rec_add_byte(0x04); //读取小时 dat=0x3f&iic_rec_add_byte(0x05); //读取天数 moom=0x1f&iic_rec_add_byte(0x07); //读取月 year=0xff&iic_rec_add_byte(0x08); //读取年 sec1=bcd_dec(sec); //将读取的BCD码秒转换成十进制秒以便运算 min1=bcd_dec(min); hour1=bcd_dec(hour); dat1=bcd_dec(dat); moom1=bcd_dec(moom); year1=bcd_dec(year); display_time(sec1,min1,hour1,dat1,moom1,year1); //LCD1602显示时间 } } |