TM1638芯片+DS1302驱动共阴数码管时钟
单片机总结3数字时钟芯片DS1302

DS1302 数字时钟芯片总结人:孟令军时间:2014/5/14学习在于总结,学习贵于交流__欢迎交流QQ:1300780479自己总结拒绝繁琐的数据手册系列————DS1302 数字时钟芯片1)简介:DS1302 是DALLAS 公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31 字节静态RAM 通过简单的串行接口与单片机进行通信实时时钟/ 日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作可通过AM/PM 指示决定采用24 或12 小时格式DS1302 与单片机之间能简单地采用同步串行的方式进行通信仅需用到三个口线 1 RES 复位 2 I/O 数据线 3 SCLK 串行时钟时钟/RAM 的读/写数据以一个字节或多达31 个字节的字符组方式通信DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mWX1,X2时钟晶振32.768khzVCC电源正极GND电源负极SCLK时钟线RST复位脚I/O数据输入2)内部寄存器:它的内部含有许多寄存器。
具体图在下一页,我简单介绍(1)时钟,对于时钟要写入,且要读取并显示,写入的位置寄存器在哪?读出从哪读?这就是第一种寄存器下表左边是寄存器的位置(理解为地址吧)他们有特点,最后一位为1是read最后一位为0时为write秒,分,时,日,月,星期,年0x80>>一直加下表右边是填写格式。
(2)控制位(读写保护位)0x8e或0x8f 内容为0x80添加写保护0x00去除写保护注意:CH: 时钟停止位寄存器2 的第7 位12/24 小时标志CH=0 振荡器工作允许bit7=1,12 小时模式CH=1 振荡器停止bit7=0,24 小时模式WP: 写保护位寄存器2 的第5 位:AM/PM 定义WP=0 寄存器数据能够写入AP=1 下午模式WP=1 寄存器数据不能写入AP=0 上午模式WP=1 寄存器数据不能写入AP=0 上午模式TCS: 涓流充电选择DS: 二极管选择位TCS=1010 使能涓流充电DS=01 选择一个二极管TCS= 其它禁止涓流充电DS=10 选择两个二极管DS=00 或11, 即使TCS=1010, 充电功能也被禁止`3)程序书写clk时钟线,rst复位端,io数据线①写函数写一字节:Void ds1302_write_byte(uchar dat){uint i;for(i=0;i<8;i++)//分八次送数据{clk=0;io=dat&0x01;clk=1;dat>>=1;}}写数据函数void ds1302_write(uchar add,uchar dat){ //分别送地址及要对应送入的数据rst=0;_nop_();clk=0; _nop_(); //初期复位状态rst=1; _nop_(); //复位拉高开始传送信号ds1302_write_byte(uchar add);ds1302_write_byte(uchar dat);rst=0; _nop_();//释放io口及clk时钟线io=1;clk=1;写数据时序图读数据时序图②读函数void ds1302_read(uchar add){rst=0;_nop_();clk=0; _nop_(); //初期复位状态rst=1; _nop_(); //复位拉高开始传送信号ds1302_write_byte(uchar add);//先把地址传入再读取它的数据for(i=0;i<8;i++){clk=0;value=value>>1;clk=1;if(io)value|=0x80;clk=1;}sck=0;_nop_();clk=0;_nop_();io=1;clk=1;}②读取温度void readtemp ()❶先将保存在数组里的数据(秒分时星期月日年)分别转换为十六进制并储存在原数组。
DS1302时钟芯片资料

DS1302DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。
实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。
工作电压宽达2.5~5.5V。
采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。
下面是标准的接线电路图:DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h~8Dh,写时80h~8Ch)是存放秒、分,小时、日、月、年、周数据的,存放的数据格式为BCD码形式它的内部时间寄存器如下:将初始设置的时间、日期数据写入这几个寄存器,然后再不断地读取这几个寄存器来获取实时时间和日期。
这几个寄存器的说明如下:1、秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。
当初始上电时该位置为1,时钟振荡器停止,DS1302处于低功耗状态;只有将秒寄存器的该位置改写为0时,时钟才能开始运行。
2、控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置为0。
在任何的对时钟和RAM的写操作之前,WP位必须为0。
当WP位为1时,写保护位防止对任一寄存器的写操作。
也就是说在电路上电的初始态WP是1,这时是不能改写上面任何一个时间寄存器的,只有首先将WP改写为0,才能进行其它寄存器的写操作。
3、控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置为0。
在任何的对时钟和RAM的写操作之前,WP位必须为0。
当WP位为1时,写保护位防止对任一寄存器的写操作。
也就是说在电路上电的初始态WP是1,这时是不能改写上面任何一个时间寄存器的,只有首先将WP改写为0,才能进行其它寄存器的写操作。
下面来说说如果对DS1302进行读写:上面的电路图可以看出,除了电源和接地,DS1302只有三根线和单片机连接,SCLK、I/O 和RST(有的也写成CE),先看时序图:DS1302的数据读写是通过I/O串行进行的。
ds1302实时时钟程序说明

DS1302实时时钟在数码管上进行实时显示的程序
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit rst=P2^4;
sbit io=P2^0;
}
write_ds1302(0x8e,0x80); //进行写保护
}
void read_rtc()
{
uchar i;
for(i=0;i<7;i++)
{
time_data[i]=read_ds1302(read_add[i]);
}
}
void time_pros()
{
disp[0]=time_data[6]%16;//将BCD码(这里与十六进制没有区别)进行十位个位的分离
{
j=time_data[i]/10;//十位5
time_data[i]%=10;//各位8
time_data[i]=time_data[i]+j*16;
}
write_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++)
{
write_ds1302(write_add[i],time_data[i]);
disp[1]=time_data[6]/16;
disp[2]=17;
disp[3]=time_data[5]%16;
disp[4]=time_data[5]/16;
disp[5]=17;
DS1302时钟芯片实例讲解

Page 13
Page 14
驱动程序
Page 15
Page 4
DS1302的寄存器:
DS1302有关于日历、时间的寄存器共有12个。其中七个 寄存器(读时81H--8DH,写时80H--8CH),存放的数据 格式是BCD码形式。
Page 5
注意: 注意:
1)、小时寄存器(85H、84H)的位7用来定义DS1302 是运行12小时模式还是24小时模式。为高时是12小时模 式。在12小时模式时,位5为1是下午(PM)。在24小时 模式时,位5是第二个10小时位。 2)、秒寄存器(81H、80H)的位7定义为时钟暂停标志 (CH)。当CH=1时,时钟振荡器停止,DS1302为低能 耗状态,CH=0时,时钟正常运行。 3)、控制寄存器(8FH、8EH)位7为写保护位,其他7 位均置0。在任何对时钟和RAM写操作之前,WP位必须 置0。当WP=1时,写保护位防止对任意寄存器进行写操 作。
Page 11
小时寄存器 1 日寄存器 月寄存器 1 1
星期寄存器 1 年寄存器 1
寄存器名称
D 7 1
D6 RAM/C K 0 0 0 1 1 1 1
D D4 D3 D2 5 A A3 A2 A1 4 0 0 1 0 0 1 1 0 1 0 1 0 … 1 1 1DS1302时钟芯片实例讲解
11-嵌本班--赵晶
DS1302的简介:
Page 2
DS1302外部引脚分配及功能:
X1、X2:32.768KHz晶振接入引脚。 X1、X2:32.768KHz晶振接入引脚。 晶振接入引脚 GND: GND: 接 地。 CE:复位引脚,低电平有效, CE:复位引脚,低电平有效,操作时高电 平。 I/O:数据输入/输出引脚, I/O:数据输入/输出引脚,具有三态功 能。 SCLK:串行时钟输入引脚。 SCLK:串行时钟输入引脚。 Vcc1: 工作电源引脚。 Vcc1: 工作电源引脚。 Vcc2: 备用电源引脚。 Vcc2: 备用电源引脚。
DS1302时钟芯片

第十四讲时钟芯片DS1302DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM ,通过简单的串行接口与单片机进行通信。
实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。
时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。
DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:(1)RES 复位(2)I/O 数据线(3)SCLK 串行时钟。
时钟/RAM 的读/写数据以一个字节或多达31个字节的字符组方式通信。
DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mW。
DS1302由DS1202改进而来增加了以下的特性:双电源管脚用于主电源和备份电源供应,Vcc1为可编程涓流充电电源,附加七个字节存储器。
它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域下面。
将主要的性能指标作一综合:★实时时钟具有能计算2100 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力★ 31 8位暂存数据存储RAM★串行I/O口方式使得管脚数量最少★宽范围工作电压2.0 5.5V★工作电流2.0V时,小于300nA★读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式★ 8 脚DIP封装或可选的8脚SOIC封装根据表面装配★简单3线接口★与TTL兼容Vcc=5V★可选工业级温度范围-40---+85★双电源管用于主电源和备份电源供应以上是DS1302的一些全面的预览,以下为DS1302管脚图:1)VCC2:主用电源引脚2)X1、X2:DS1302外部晶振引脚3)GND:地4)RST:复位引脚5)I/O:串行数据引脚,数据输出或者输入都从这个引脚6)SCLK:串行时钟引脚7)VCC1:备用电源1)VCC 为主电源接5V,CX10 为滤波电容2)2、外接32.768K 的晶振3)3、 5、6、7 脚分别与控制器相联,注意外部4.7K 上拉电阻4)4、备用电源脚,注意是3.3V,DS1302 要求备用电源电压稍微低于主用电源下面讲讲DS1302 的具体操作。
分享一下调试DS1302时钟芯片的经验

分享一下调试DS1302时钟芯片的经验这几天,着手把以前用DS12C887 时钟芯片做的万年历,改成用DS1302 来做,以前写DS12C887 的代码时感觉蛮轻松,但是写DS1302 感觉有些棘手,在调试的过程中更是不顺的种种。
开始写代码,一开始用开发板做实验,用LCD1602 做显示,这个还是很轻松就搞定了(一天过去了)。
然后自己用DS1302 芯片焊了块板子,然后用杜邦线连接到开发板上面进行测试,不过LCD1602 什么都没有显示,(以为程序有问题不停改来改去花了很多时间,然后才确定肯定是硬件问题而不是软件问题,以为数据都没有写进DS1302 中),经过分析可能是开发板上面的某些芯片可能会对SPI 的数据传输造成一些影响(一天过去了)自己又焊了一块单片机的板子,把LCD1602 给放上去然后连接好DS1302,一上电时钟开始走了,顿时感觉轻松了,结果仔细一看,时间全部都是乱的,我又开始怀疑是程序问题,我开始修改程序,但是怎么样都没有结果(感觉很久没有写程序,放这10 多天的假已经没有感觉,感觉无从下手,很是郁闷),找不到问题只能又把LCD1602 放到开发板上面去做测试,一试还是可以在开发板上面正常工作,难道是芯片的问题,或者是和晶振没有接电容的关系,马上开始查资料,换芯片,结果还是一样,于是乎真的就傻眼了(一天过去了)第二天一开始就先在百度上面搜原因和解决方法,最后也没有收到一个解决的方法,我准备在进行一次测试,把LCD1602 从开发板上门取下来,然后放到自己做的单片机板子上面,一上电,上面都没有LCD1602 亮的不亮,一看引脚,原来插错了,于是就重新插,结果只有背光亮,屏幕没有反应了,试了几次看样子的果断被烧坏了(感觉太背时了)。
一想就气愤,调了这么久没有结果还把东西烧了,觉得不爽还想继续,。
DS1302实时时钟原理与应用

DS1302实时时钟原理与应用
1.原理:
DS1302实时时钟通过一个简单的三线接口与微控制器相连,这三根
线分别是:数据线、时钟线和复位线。
通过这三根线,微控制器可以向
DS1302写入和读取时钟和日期信息。
具体的通信协议可以通过发送特定
的命令字节来实现。
当写入数据时,数据线的电平可以提供有效数据,而
时钟线的上升沿控制数据的传输。
当读取数据时,数据线的电平会反映
DS1302存储器中的信息。
2.应用:
a.数字时钟和日期显示器:DS1302实时时钟可以用来驱动数字时钟
和日期显示器,供人们查看当前时间和日期。
b.考勤系统:DS1302实时时钟可以用来记录员工的考勤信息,如签
到和签退时间。
c.定时器:DS1302实时时钟可以用来控制各种定时器,如定时开关、定时器插座等。
d.定时报警器:使用DS1302实时时钟可以实现定时报警功能,如定
时提醒服药、定时关机等。
e.温度和湿度监测:结合温湿度传感器,DS1302实时时钟可以用来
记录环境的温度和湿度信息,并提供时间戳。
f.数据日志记录器:DS1302实时时钟可以用来记录各种传感器的数据,并提供时间戳,以便后续分析和处理。
总之,DS1302实时时钟是一种非常实用的集成电路,具有精确和可靠的时间计量功能。
它可以广泛应用于各种需要时间记录和计量的电子设备和系统中。
通过合理的设计和应用,我们可以充分发挥DS1302实时时钟的功能,提高系统的可靠性和稳定性。
DS1302是Dallas公司生产的一种实时时钟芯片

DS1302是Dallas公司生产的一种实时时钟芯片。
它通过串行方式与单片机进行数据传送,能够向单片机提供包括秒、分、时、日、月、年等在内的实时时间信息,并可对月末日期、闰年天数自动进行调整;它还拥有用于主电源和备份电源的双电源引脚,在主电源关闭的情况下,也能保持时钟的连续运行。
另外,它还能提供31字节的用于高速数据暂存的RAM。
鉴于上述特点,DS1302已在许多单片机系统中得到应用,为系统提供所需的实时时钟信息。
一、DS1302的主要特性1. 引脚排列500)this.width=500 border=0>图1 DS1302引脚排列图DS1302的引脚排列如图1所示,各引脚的功能如下:X1,X2——32768Hz晶振引脚端;RST——复位端;I/O——数据输入/输出端;SCLK——串行时钟端;GND——地;VCC2,VCC1——主电源与后备电源引脚端。
2. 主要功能DS1302时钟芯片内主要包括移位寄存器、控制逻辑电路、振荡器、实时时钟电路以及用于高速暂存的31字节RAM。
DS1302与单片机系统的数据传送依靠RST,I/O,SCLK三根端线即可完成。
其工作过程可概括为:首先系统RST引脚驱动至高电平,然后在作用于SCLK时钟脉冲的作用下,通过I/O引脚向DS1302输入地址/命令字节,随后再在SCLK时钟脉冲的配合下,从I/O引脚写入或读出相应的数据字节。
因此,其与单片机之间的数据传送是十分容易实现的。
二、时钟的产生及存在的问题(1) 在实际使用中,我们发现DS1302的工作情况不够稳定,主要表现在实时时间的传送有时会出现误差,有时甚至整个芯片停止工作。
我们对DS1302的工作电路进行了分析,其与单片机系统的连接如图2所示。
从图中可以看出,DS1302的外部电路十分简单,惟一外接的元件是32768Hz的晶振。
通过实验我们发现:当外接晶振电路振荡时,DS1302计时正确;当外接晶振电路停振时,DS1302计时停止。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、概述二、51单片机,TM1638芯片+DS1302驱动共阴数码管时钟,最后包括按键检测程序(是分开的。
)TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。
主要应用于冰箱、空调、家庭影院等产品的高段位显示屏驱动。
二、特性说明•采用功率CMOS 工艺•显示模式 10 段×8 位•键扫描(8×3bit)•辉度调节电路(占空比8 级可调)•串行接口(CLK,STB,DIO)•振荡方式:RC 振荡(450KHz+5%)•内置上电复位电路•采用SOP28封装三、、管脚定义:电路图数码管:程序代码:/*************** TM1638.H头文件*******************/#ifndef _TM1638_H#define _TM1638_H//引脚定义sbit DIO=P1^0;sbit CLK=P1^1;sbit STB=P1^2;//写一个8Bit数据void TM1638_Write(unsigned char DATA) //写数据函数{unsigned char i;for(i=0;i<8;i++){CLK=0;if(DATA&0X01)DIO=1;elseDIO=0;DATA>>=1;CLK=1;}}/*unsigned char TM1638_Read(void) //读数据函数{unsigned char i;unsigned char temp=0;DIO=1; //设置为输入for(i=0;i<8;i++){temp>>=1;CLK=0;if(DIO)temp|=0x80;CLK=1;}return temp;} */void Write_COM(unsigned char cmd) //发送命令字{STB=0;TM1638_Write(cmd); //写命令STB=1;}void Write_DATA(unsigned char add,unsigned char DA TA) //指定地址写入数据{Write_COM(0x44);STB=0;TM1638_Write(0xc0|add); //地址高位为1:11** ****,写地址TM1638_Write(DA TA);STB=1;}void init_TM1638(void){unsigned char i;Write_COM(0x8a);//亮度Write_COM(0x40); //写数据命令,写数据到显示寄存器STB=0;TM1638_Write(0xc0); //写地址命令for(i=0;i<16;i++)TM1638_Write(0x00);STB=1;}#endif/***************************DS1302.H头文件***************************/#ifndef DS1302_H#define DS1302_H#define uchar unsigned char#define uint unsigned int#include"DELAY.h"sbit acc0=ACC^0; //移位时的第0位sbit acc7=ACC^7; //移位时用的第7位uchar second,minute,hour,day,month,year,week,count=0;uchar ReadValue,num,time;sbit SCLK=P2^0;sbit DATA=P2^1;sbit RST=P2^2;void Write1302(uchar dat){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备delay1(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续写8个二进制位数据{DATA=dat&0x01; //取出dat的第0位数据写入1302delay(2); //稍微等待,使硬件做好准备SCLK=1; //上升沿写入数据delay1(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位}}void WriteSet1302(uchar Cmd,uchar dat){RST=0; //禁止数据传递SCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输delay1(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302(dat); //写数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递}uchar Read1302(void){uchar i,dat;delay(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据{dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位if(DATA==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位SCLK=1; //将SCLK置于高电平,为下降沿读出delay1(2); //稍微等待SCLK=0; //拉低SCLK,形成脉冲下降沿delay1(2); //稍微等待}return dat; //将读出的数据返回}uchar ReadSet1302(uchar Cmd){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输Write1302(Cmd); //写入命令字dat=Read1302(); //读出数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat; //将读出的数据返回}void Init_DS1302(void){WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值WriteSet1302(0x82,((41/10)<<4|(41%10))); //根据写分寄存器命令字,写入分的初始值WriteSet1302(0x84,((15/10)<<4|(15%10))); //根据写小时寄存器命令字,写入小时的初始值WriteSet1302(0x86,((29/10)<<4|(24%10))); //根据写日寄存器命令字,写入日的初始值WriteSet1302(0x88,((2/10)<<4|(2%10))); //根据写月寄存器命令字,写入月的初始值WriteSet1302(0x8c,((10/10)<<4|(11%10))); //nianWriteSet1302(0x8a,((0/10)<<4|(0%10)));WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令}#endif/***************显示头文件*******************************/#include"TM1638.h"uchar data DisBuffer[8]={0,0,0,0,0,0,0,0}; /*显示缓存区*/ //各个数码管显示的值uchar code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71 ,0x40,0xef};void display1638(uchar hour,uchar minute,uchar second){uchar i;DisBuffer[0]=hour/10;DisBuffer[1]=hour%10;DisBuffer[3]=minute/10;DisBuffer[4]=minute%10;DisBuffer[6]=second/10;DisBuffer[7]=second%10;DisBuffer[2]=16;DisBuffer[5]=16;for(i=0;i<8;i++){Write_DATA(i*2,tab[DisBuffer[i]]);}}void DisplayHour(newval){DisBuffer[0]=newval/10;DisBuffer[1]=newval%10;for(i=0;i<2;i++){Write_DATA(i*2,tab[DisBuffer[i]]);}}#endif/**********************************************************///下面是处理程序头文件,调试功能的实现,但是本人接调时的来源是//是鼠标芯片,所以这里都写上,各位可以根据自己是按键还是其他的,做修改/***********************************************/#ifndef CHULI_H#define CHULI_H#define uchar unsigned char#define uint unsigned int#include"DISPLAY.h"#include"DS1302.h"void read_date(void){ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = ReadSet1302(0x83);minute=((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = ReadSet1302(0x85);hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x87);day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x89);month=((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = ReadSet1302(0x8d);year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue=ReadSet1302(0x8b); //读星期week=ReadValue&0x07;display1638(hour,minute,second) ;}void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num){newval=ReadSet1302(newaddr); //读取当前时间newval=((newval&0x70)>>4)*10+(newval&0x0f); //将bcd码转换成十进制if(flag) //判断是加一还是减一{newval++;switch(s1num){ case 1: if(newval>99) newval=0;DisplayYear(newval);break;case 2: if(newval>12) newval=1;DisplayMonth(newval);break;case 3: if(newval>31) newval=1;DisplayDay(newval);break;case 4: if(newval>6) newval=0;DisplayWeek(newval);break;case 5: if(newval>23) newval=0;DisplayHour(newval);break;case 6: if(newval>59) newval=0;DisplayMinute(newval);break;case 7: if(newval>59) newval=0;DisplaySecond(newval);break;default:break;}}else{newval--;switch(s1num){ case 1: if(newval==0) newval=99;DisplayYear(newval);break;case 2: if(newval==0) newval=12;DisplayMonth(newval);break;case 3: if(newval==0) newval=31;DisplayDay(newval);break;case 4: if(newval<0) newval=6;DisplayWeek(newval);break;case 5: if(newval<0) newval=23;DisplayHour(newval);break;case 6: if(newval<0) newval=59;DisplayMinute(newval);break;case 7: if(newval<0) newval=59;DisplaySecond(newval);break;default:break;}}WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10)); //将新数据写入寄存器}void write_flsh(uchar com,uchar dat){ Write_DATA(com,tab[16]);delay(100);Write_DATA(com,tab[dat]);}void sp2_mouse(void){uchar miao,z,flag=0;rd=0;miao=ReadSet1302(0x81);second=miao;WriteSet1302(0x80,miao|0x80);while(1){ led=0;////////////////////////////////////////* if((move_x<4)&&(flag==0)){write_flash(0x02,1) ;if((mouse_data[0]&0x01)&&(flag==1)){while(mouse_data[0]&0x01);while(1){ write_flash(0x02,1) ;z=move_x;if(move_x>z){ delayms(10);turn_val(year,1,0x8d,1);}if(z>move_x){delayms(10);turn_val(year,0,0x8d,1);}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=3;z=move_x;break;}}}}///////////////////////////////////////////////////////if((move_x>=4)&&(move_x<6)&&(flag==0)){write_com(0x87);if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);while(1){ z=move_x;write_com(0x87);if(move_x>z){ delayms(10);turn_val(month,1,0x89,2);}if(z>move_x){delayms(10);turn_val(month,0,0x89,2);}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=5;z=move_x;break;}}}}/////////////////////////////////////////////////////////if((move_x>=6)&&(move_x<8)&&(flag==0)){write_com(0x8a);if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);while(1){z=move_x;write_com(0x8a);if(move_x>z){ delayms(10);turn_val(day,1,0x87,3);}if(z>move_x){ delayms(10);turn_val(day,0,0x87,3);}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=7;z=move_x;break;}}}}///////////////////////////////////////////////////////////if((move_x>=8)&&(move_x<10)&&(flag==0)){write_com(0x8e);if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);while(1){z=move_x;write_com(0x8e);if(move_x>z){ delayms(10);turn_val(week,1,0x8b,4);}if(z>move_x){delayms(10);turn_val(week,0,0x8b,4);}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=9;z=move_x;break;}}}} */////////////////////////////////////////////////////////////if((move_x>=10)&&(move_x<12)&&(flag==0)){write_flash(0x02,1) ;if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);while(1){z=move_x;write_flash(0x02,1) ;if(move_x>z){ delayms(10);turn_val(hour,1,0x85,5);}if(z>move_x){ delayms(10);turn_val(hour,0,0x85,5);}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=11;z=move_x;break;}}}}//////////////////////////////////////////////////////////////if((move_x>=12)&&(move_x<14)&&(flag==0)){write_com(0xc4) ;if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);while(1){z=move_x;write_com(0xc4) ;if(move_x>z){ delayms(10);turn_val(minute,1,0x83,6); //写入分寄存器}if(z>move_x){delayms(10);turn_val(minute,0,0x83,6); //写入分寄存器}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=13;z=move_x;break;}}}}////////////////////////////////////////////////////////////////if((move_x>=14)&&(flag==0)){write_com(0xc7);if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);while(1){z=move_x;write_com(0xc7);if(move_x>z){ delayms(10);turn_val(second,1,0x81,7);}if(z>move_x){delayms(10);turn_val(second,0,0x81,7);}if(mouse_data[0]&0x01){while(mouse_data[0]&0x01);flag=1;move_x=15;z=move_x;break;}}}}///////////////////////////////////////////////////////////////if((mouse_data[0]&0x01)&&(z!=move_x)){flag=0;while(mouse_data[0]&0x01);}//////////////////////////////////////////////////////////////if((mouse_data[0]&0x01)&&(flag==1)&&(z==move_x)){flag=0;delayms(300);miao=ReadSet1302(0x81);second=miao;WriteSet1302(0x80,second&0x7f);write_com(0x0c) ;WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,写入不保护指令break;}}}#endif/*********鼠标芯片*****/#ifndef PS2_H#define PS2_H#include"DELAY.h"sbit mouse_SDA=P3^4;//数据线P3_5 计数器0输入端口sbit mouse_CLK=P3^3;//时钟线P3_3 外部中断1输入端口sbit led=P3^6;bit pp=0;bit ACK=0;uchar bdata mouse_byte; //接收字节bdata-->可寻址的片内RAMsbit mouse_byte_bit0=mouse_byte^0;//mouse_byte第0位sbit mouse_byte_bit1=mouse_byte^1;//mouse_byte第1位sbit mouse_byte_bit2=mouse_byte^2;//mouse_byte第2位sbit mouse_byte_bit3=mouse_byte^3;//mouse_byte第3位sbit mouse_byte_bit4=mouse_byte^4;//mouse_byte第4位sbit mouse_byte_bit5=mouse_byte^5;//mouse_byte第5位sbit mouse_byte_bit6=mouse_byte^6;//mouse_byte第6位sbit mouse_byte_bit7=mouse_byte^7;//mouse_byte第7位uchar mouse_buffer[11];//接收位数据缓冲区uchar mouse_buffer_bit=0;//mouse_buffer[mouse_buffer_bit]uchar mouse_data[4];//接收鼠标数据缓冲区,分别存放:功能信息字节,x位移量,y位移量uchar mouse_data_bit=0;//mouse_data[mouse_data_bit]uchar move_x;//存放横坐标uint move_y;//存放纵坐标uchar move_z;extern uchar move_x;/*********************************************************************** 发送数据************************************************************************/void Init_ter(void){EA=1; //开放中断EX1=1;//允许外部中断1PX1=1;//设置中断优先级设外部中断1为最高优先级别}void host_to_mouse(uchar cmd){uchar i;EX1=0;mouse_CLK=0;delay100;delay100;ACC=cmd;pp=~P; //获得奇偶校验位mouse_SDA=0;mouse_CLK=1;for(i=0;i<8;i++){while(mouse_CLK==1);mouse_SDA=cmd&0x01;cmd>>=1;while(mouse_CLK==0);}while(mouse_CLK==1);mouse_SDA=pp; //发送奇偶校验位while(mouse_CLK==0);while(mouse_CLK==1);mouse_SDA=1;while(mouse_CLK==0);while(mouse_CLK==1);ACK=mouse_SDA; //接收应答位while(mouse_CLK==0);EX1=1;}void Init_mouse(void){host_to_mouse(0xf4);delayms(50);Init_ter();delayms(50);host_to_mouse(0xf3);delayms(50);host_to_mouse(0xc8);delayms(50);host_to_mouse(0xf3);delayms(50);host_to_mouse(0x64);delayms(50);host_to_mouse(0xf3);delayms(50);host_to_mouse(0x50);delayms(50);host_to_mouse(0xf2);delayms(200);mouse_data[0]=0;mouse_data[1]=0;mouse_data[2]=0;mouse_data[3]=0;move_x=10;move_y=0;move_z=0;}/*********************************************奇校检**********************************************/uchar Checkout(void){ACC=mouse_byte;if(~P==mouse_buffer[9])return 1;elsereturn 0;}/********************************************************* 数据分析及处理**********************************************************/ void data_analyse(void){//将收到的11位信号中截取8位数据放进mouse_bytemouse_byte_bit0=mouse_buffer[1];mouse_byte_bit1=mouse_buffer[2];mouse_byte_bit2=mouse_buffer[3];mouse_byte_bit3=mouse_buffer[4];mouse_byte_bit4=mouse_buffer[5];mouse_byte_bit5=mouse_buffer[6];mouse_byte_bit6=mouse_buffer[7];mouse_byte_bit7=mouse_buffer[8];if(Checkout())//如果校验正确{if(mouse_data_bit<4)mouse_data[mouse_data_bit++]=mouse_byte;if(mouse_data_bit==4){mouse_data_bit=0;if(mouse_data[0]&0x10)//如果"X sign bit"为1,表示鼠标向右左移{move_x-=(256-mouse_data[1]);//x坐标减if(move_x<=1)move_x=17;}else{move_x+=mouse_data[1];//x坐标加if(move_x>=17)move_x=2;}if(mouse_data[0]&0x20){move_y-=(256-mouse_data[2]);//y坐标减}else{move_y+=mouse_data[2];//y坐标加}if(mouse_data[3]&0x08){move_z-=(16-(mouse_data[3]&0x0f));}else{mouse_data[3]=mouse_data[3]&0x0f;move_z+=mouse_data[3]; //Z坐标加}}}}/**************************************************外部中断1***************************************************/void ReceiveData(void) interrupt 2{ led=0;if(mouse_buffer_bit<=10){while(mouse_CLK==0);//等待设备拉高时钟线mouse_buffer[mouse_buffer_bit++]=mouse_SDA;//接收数据}if(mouse_buffer_bit==10){data_analyse();//数据分析及处理mouse_buffer_bit=0;}}#endif////////////////////////////////主函数部分//////////////////////////////////////////////////// #include<reg51.h>#include"TM1638.h"#include"DS1302.h"#include"DELAY.h"#include"CHULI.h"#include"DISPLAY.h"void main(){delayms(500);init_TM1638();delayms(50);Init_DS1302(); //将1302初始化delay(500);while(1){read_date();delayms(50);}}/**********************************************/再来一个按键测试的程序:这个是另外的,与上面的无关;#ifndef _TM1638_H#define _TM1638_H#include <REGX51.H>#define DATA_COMMAND 0X40#define DISP_COMMAND 0x80#define ADDR_COMMAND 0XC0//引脚定义sbit DIO=P1^0;sbit CLK=P1^1;sbit STB=P1^2;unsigned char code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71 ,0x40};void TM1638_Write(unsigned char DATA) //写数据函数{unsigned char i;for(i=0;i<8;i++){CLK=0;if(DATA&0X01)DIO=1;elseDIO=0;DATA>>=1;CLK=1;}}unsigned char TM1638_Read(void) //读数据函数{unsigned char i;unsigned char temp=0;DIO=1; //设置为输入for(i=0;i<8;i++){temp>>=1;CLK=0;if(DIO)temp|=0x80;CLK=1;}return temp;}void Write_COM(unsigned char cmd) //发送命令字{STB=0;TM1638_Write(cmd);STB=1;}unsigned char Read_key(void){unsigned char c[4],i,key_value=0;STB=0;TM1638_Write(0x42); //读取键盘值for(i=0;i<4;i++)c[i]=TM1638_Read();STB=1; //4个字节数据合成一个字节for(i=0;i<4;i++)key_value|=c[i];for(i=0;i<4;i++)if(c[i]==key_value)break;return (i*8+key_value);}void Write_DATA(unsigned char add,unsigned char DA TA) //指定地址写入数据{Write_COM(0x44);STB=0;TM1638_Write(0xc0|add);TM1638_Write(DA TA);STB=1;}/*void Write_oneLED(unsigned char num,unsigned char flag) //单独控制一个LED函数,num 为需要控制的led序号,flag为0时熄灭,不为0时点亮{if(flag)Write_DATA(2*num+1,1);elseWrite_DATA(2*num+1,0);}void Write_allLED(unsigned char LED_flag) //控制全部LED函数,LED_flag表示各个LED状态{unsigned char i;for(i=0;i<8;i++){if(LED_flag&(1<<i))Write_DATA(2*i+1,3);elseWrite_DATA(2*i+1,0);}} */void init_TM1638(void){unsigned char i;Write_COM(0x8a);//亮度Write_COM(0x40);STB=0;TM1638_Write(0xc0);for(i=0;i<16;i++)TM1638_Write(0x00);STB=1;}#endif#include <at89x51.H>#include <tm1638.h>#include "555.h"unsigned char num[8]; //各个数码管显示的值unsigned char x=0xff;sbit key=P3^4;int main(void){init_TM1638();system_init();display(x);delay_ms(200);display1638();while(1){display1638();// detectkey();x=Read_key();display(~x);}}void display1638(){ uchar i;if(sec_flag|i){num[0]=hour/10;num[1]=hour%10;num[3]=minute/10;num[4]=minute%10;num[6]=second/10;num[7]=second%10;num[2]=16;num[5]=16;for(i=0;i<8;i++){Write_DATA(i*2,tab[num[i]]);}}}#ifndef _555_H#define _555_H#include<at89x51.h>#define uchar unsigned charvoid delay_ms(uchar);void display();void detectkey();void display1638();uchar code tap[10]={0xC0,/*0*/0xF9,/*1*/0xA4,/*2*/0xB0,/*3*/0x99,/*4*/0x92,/*5*/0x82,/*6*/0xF8,/*7*/0x80,/*8*/0x90,/*9*/};sbit key_hour=P3^5;sbit key_min=P3^6;uchar hour=12;uchar minute=0;uchar second=0;uchar flag=0;uchar sec_flag=0;/************************* 初始化程序**************************/ void system_init(){ TMOD=0x01;EA=1;ET0=1;EX0=1;IT0=1;TR0=1;TH0=(65536-50000)/256;TL0=(65536-50000)%256;}/************************* 定时器中断0中断处理程序**************************/ void int1_ISR() interrupt 1 {TH0=(65536-50000)/256;TL0=(65536-50000)%256;flag++;if(flag==20){sec_flag=1;second++;flag=0;}if(second==60){second=0;minute++;}if(minute==60){minute=0;hour++;hour%=24;}}/************************* 按键程序**************************/ void detectkey(){delay_ms(10);if(key_hour==0){hour++;hour=hour%24;while(!key_hour)display();}if(key_min==0){minute++;minute=minute%60;while(!key_min)display();}if(P3_7==0){hour=12;minute=0;second=0;while(!P3_5)display();}/*************************显示程序**************************/void display(uchar i){P0=i;}/*************************延时处理程序**************************/void delay_ms(uchar no){uchar i,j;for(i=0;i<no;i++){for(j=0;j<164;j++);for(j=0;j<164;j++);}}#endif说明:按键值送P0接的LED显示。