基于DS1302的日历时钟 #include //包含单片机寄存器的头文件 #include //包含_nop_()函数定义的头文件 /*********************************************************************** 以下是DS1302芯片的操作程序 ************************************************************************/ unsigned char code digit[10]={"0123456789"}; //定义字符数组显示数字 sbit DATA=P1^1; //位定义1302芯片的接口,数据输出端定义在P1.1引脚 sbit RST=P1^2; //位定义1302芯片的接口,复位端口定义在P1.1引脚 sbit SCLK=P1^0; //位定义1302芯片的接口,时钟输出端口定义在P1.1引脚 /***************************************************** 函数功能:延时若干微秒 入口参数:n ***************************************************/ void delaynus(unsigned char n) { unsigned char i; for(i=0;i>=1; //将dat的各数据位右移1位,准备写入下一个数据位 } } /***************************************************** 函数功能:根据命令字,向1302写一个字节数据 入口参数:Cmd,储存命令字;dat,储存待写的数据 ***************************************************/ void WriteSet1302(unsigned char Cmd,unsigned char dat) { RST=0; //禁止数据传递 SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输 delaynus(2); //稍微等待,使硬件做好准备 Write1302(Cmd); //写入命令字 Write1302(dat); //写数据 SCLK=1; //将时钟电平置于已知状态 RST=0; //禁止数据传递 } /***************************************************** 函数功能:从1302读一个字节数据 入口参数:x ***************************************************/ unsigned char Read1302(void) { unsigned char i,dat; delaynus(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续读8个二进制位数据 { dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位 if(DATA==1) //如果读出的数据是1 dat|=0x80; //将1取出,写在dat的最高位 SCLK=1; //将SCLK置于高电平,为下降沿读出 delaynus(2); //稍微等待 SCLK=0; //拉低SCLK,形成脉冲下降沿 delaynus(2); //稍微等待 } return dat; //将读出的数据返回 } /***************************************************** 函数功能:根据命令字,从1302读取一个字节数据 入口参数:Cmd ***************************************************/ unsigned char ReadSet1302(unsigned char Cmd) { unsigned char dat; RST=0; //拉低RST SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输 Write1302(Cmd); //写入命令字 dat=Read1302(); //读出数据 SCLK=1; //将时钟电平置于已知状态 RST=0; //禁止数据传递 return dat; //将读出的数据返回 } /***************************************************** 函数功能: 1302进行初始化设置 ***************************************************/ void Init_DS1302(void) { WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令 WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x82,((0/10)<<4|(0%10))); //根据写分寄存器命令字,写入分的初始值 WriteSet1302(0x84,((12/10)<<4|(12%10))); //根据写小时寄存器命令字,写入小时的初始值 WriteSet1302(0x86,((16/10)<<4|(16%10))); //根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((11/10)<<4|(11%10))); //根据写月寄存器命令字,写入月的初始值 WriteSet1302(0x8c,((8/10)<<4|(8%10))); //根据写小时寄存器命令字,写入小时的初始值 } /******************************************************************************* 以下是对液晶模块的操作程序 *******************************************************************************/ sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚 sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚 sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚 sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚 /***************************************************** 函数功能:延时1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒 ***************************************************/ void delay1ms() { unsigned char i,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; } /***************************************************** 函数功能:延时若干毫秒 入口参数:n ***************************************************/ void delaynms(unsigned char n) { unsigned char i; for(i=0;i>4)*10 + (ReadValue&0x0F);//将读出数据转化 DisplaySecond(second); //显示秒 ReadValue = ReadSet1302(0x83); //从分寄存器读 minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayMinute(minute); //显示分 ReadValue = ReadSet1302(0x85); //从分寄存器读 hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayHour(hour); //显示小时 ReadValue = ReadSet1302(0x87); //从分寄存器读 day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayDay(day); //显示日 ReadValue = ReadSet1302(0x89); //从分寄存器读 month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayMonth(month); //显示月 ReadValue = ReadSet1302(0x8d); //从分寄存器读 year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayYear(year); //显示年 } }