① 用单片机设计一个时钟,可显示时和分,可以调时间,也要有闹钟功能,要有设计的电路图
其实不用定时中断也能实现功能:
#include<reg51.h> 主函数
unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};定义0-9数组
unsigned int tmp;定义变量
void delay(unsigned int xms)定义延时函数
{unsigned int j,i;
for(i=0;i<xms;i++)
for(j=0;j<100;j++);
}
void disp()定义子函数
{
P1=tmp;
delay(1);
P2=0xff;
tmp=tmp<<1;
}
void main( )
{
unsigned char z,s=00,m=00,h=00;给时钟初始值
while(1)
{
for(z=0;z<100;z++)
{
tmp=0x01;
P2=tab[h/10];小时显示
disp();
P2=tab[h%10];
disp();
P2=tab[m/10];分钟显示
disp();
P2=tab[m%10];
disp();
P2=tab[s/10];秒显示
disp();
P2=tab[s%10];
disp();
}
s++;
while(s==60)秒进一位,到60清0
{
m++;
s=00;
}
while(m==60)分钟进一位,到60清0
{
h++;
m=00;
}
while(h==24)小时进一位,到24清0
{
h=00;
}
}
}
② 请教一个单片机时钟计时器c语言程序和原理图 注:不要复制的
//------------------------------------------------------------------
//名称:DS1302时钟
//------------------------------------------------------------------
//说明:从DS1302
中读取时钟数据,在LCD上显示日期和时间
//------------------------------------------------------------------
#include
<reg51.h>
#include
<intrins.h>
#include
<string.h>
#define
uchar
unsigned
char
#define
uint
unsigned
int
sbit
IO=P1^0;
//DS1302数据线
sbit
SCLK=P1^1;
//DS1302时钟线a
sbit
RST=P1^2;
//DS1302复位线
uchar
WEEK[][4]={
"***","SUN","MON","TUS","WEN","THU","FRI","SAT"};
//亦可定义成指针数组*WEEK[]
uchar
LCD_DSY_BUFFER1[]={"DATE
00-00-00
"};
uchar
LCD_DSY_BUFFER2[]={"TIME
00:00:00
"};
uchar
DateTime[7];
void
Initialize_LCD();
void
Display_LCD_String(uchar
p,uchar
*s);
void
DelayMS(uint
ms);
//------------------------------------------------------------------
//函数名称:Write_A_Byte_TO_DS1302(uchar
x)
//函数功能:向DS1302写入一个字节
//输入参数:x
将要写入的数据
//返回值:无
//时序原理:在控制指令字输入后的下一个SCLK时钟的上升沿时数据被写入DS1302,数据输入从第0位开始
//------------------------------------------------------------------
void
Write_A_Byte_TO_DS1302(uchar
x)
{
uchar
i;
SCLK=0;
//拉低SCLK,为脉冲上升沿写入数据做好准备
for
(i=0;i<8;i++)
{
IO=x
&
0x01;
//取出x的第0位数据写入1302
SCLK=1;
//上升沿写入数据
SCLK=0;
//重新拉低SCLK,形成脉冲
x
>>=1;
//将x的各数据位右移1位,准备写入下一个数据位
}
}
//------------------------------------------------------------------
//函数名称:Get_A_Byte_FROM_DS1302()
//函数功能:从DS1302读取一个字节
//输入参数:无
//返回值:读取的数据
//时序原理:在紧跟8位的控制指令字后的下一个SCLK时钟的下降沿时读出DS1302的数据,读出数据时从低位0位到高位7
//注意:DS1302中所存放的数据是BCD码,在读写时要注意转换
//例如:00011000,当把它视为二进制数时,其值为24;但作为2位BCD码时,其值为18。
//------------------------------------------------------------------
uchar
Get_A_Byte_FROM_DS1302()
{
uchar
i,b=0x00;
for
(i=0;i<8;i++)
{
b
|=
_crol_((uchar)IO,i);//将uchar类型的IO数据左移i位
SCLK=1;
//将SCLK置于高电平,为下降沿读出
SCLK=0;
//时钟下降沿读取
}
return
(b/16)*10+b%16;
//从二进制数返回BCD码
}
//------------------------------------------------------------------
//函数名称:Read_Data(uchar
addr)
//函数功能:从DS1302的指定寄存器读数据
//输入参数:addr
为读寄存器的地址
//返回值:dat
读取的数据
//命令字:也即读寄存器的地址
最高位位7必须为1,位6如果为0表示存取日历数据,位5至位1表示操作单元的地址,位0为1表示读操作
//------------------------------------------------------------------
uchar
Read_Data(uchar
addr)
{
uchar
dat;
RST=0;
//拉低RST
SCLK=0;
//确保写数据前SCLK被拉低
RST=1;
//启动数据传输,只有在SCLK为低电平时才能将RST置为高电平
Write_A_Byte_TO_DS1302(addr);
//写入命令字
dat=Get_A_Byte_FROM_DS1302();
SCLK=1;
//将时钟电平置于已知状态
RST=0;
//禁止数据传递
return
dat;
}
//------------------------------------------------------------------
//函数名称:GetTime()
//函数功能:读取当前日期时间,将秒、分钟、小时、日期、月份、周日、年份七个数值分//别存入数组DateTime[0]~
DateTime[6]
//输入参数:无
//返回值:无
//------------------------------------------------------------------
void
GetTime()
{
uchar
i,addr
=0x81;
for
(i=0;i<7;i++)
{
DateTime[i]
=
Read_Data(addr);
addr+=2;
}
}
//------------------------------------------------------------------
//日期与时间值转换为数字字符
//------------------------------------------------------------------
void
Format_DataTime(uchar
d,uchar
*a)
{
a[0]=d/10+'0';
a[1]=d%10+'0';
}
//------------------------------------------------------------------
//主程序
//------------------------------------------------------------------
void
main()
{
Initialize_LCD();
while(1)
{
GetTime();
Format_DataTime(DateTime[6],LCD_DSY_BUFFER1+5);
//0x8D
年份寄存器
Format_DataTime(DateTime[4],LCD_DSY_BUFFER1+8);
//0x89
月份寄存器
Format_DataTime(DateTime[3],LCD_DSY_BUFFER1+11);
//0x87
日期寄存器
//星期
strcpy
(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]);//将字符串WEEK[DateTime[5]]复制到字符数组LCD_DSY_BUFFER1+13中
//0x8B
周日寄存器
Format_DataTime(DateTime[2],LCD_DSY_BUFFER2+5);
//0x85
小时寄存器
Format_DataTime(DateTime[1],LCD_DSY_BUFFER2+8);
//0x83
分钟寄存器
Format_DataTime(DateTime[0],LCD_DSY_BUFFER2+11);
//0x81
秒寄存器
Display_LCD_String(0x00,LCD_DSY_BUFFER1);
//第一行显示年、月、日、星期几
Display_LCD_String(0x40,LCD_DSY_BUFFER2);
//第二行显示小时、分钟、秒
}
}
//--------------------------------------------------------
//注意:1.本例中DS1302的属性设置为:自动根据PC的时间初始化。
//可以编程写入某个自定的初始时间,然后由该时间开始显示时钟。
//
//
//--------------------------------------------------------
③ 单片机时钟制作的可行性研究,短点的,一二百字足矣
多功能电子时钟
概述:加入世贸组织以后,中国会面临激烈的竞争。这种竞争将是一场科技实力、
管理水平和人才素质的较量,风险和机遇共存。于是老师在单片机理论课程学习的基
础上,为我们安排了一个涉及MCS—51 单片机多种资源应用及具有综合功能的电子
时钟设计。
关键字: 显示时间 定时 温度采集 系统仿真
1 引 言
《单片原理及应用》是一门技术性、应用性很强的学科,实践教学是它的一个极
为重要的环节。不论是硬件扩展、接口应用还是编程方法、程序调试,都离不开实验
教学。如果不在切实认真地抓好学生的实践技能的锻炼上下功夫,单凭课堂理论课学
习,势必出现理论与实践脱节的局面。任随书本上把单片机技术介绍得多么重要、多
么实用多么好用,同学们仍然会感到那只是空中楼阁,离自己十分遥远,或者会感到
对它失去兴趣,或者会感到它高深莫测无从下手,这些情况都会令课堂教学的效果大
打折扣。
仿真设计的目的就是在理论学习的基础上,通过完成一个涉及MCS
—51 单片机都种资源应用并具有综合功能的小系统目标板的设计与编程应用,使学生
不但能够将课堂上学到的理论知识与实际应用结合起来,而且能够对电子电路、电子
元器件、印制电路板等方面的知识进一步加深认识,同时在软件编程、排版调试、焊
接技术、相关仪器设备的使用技能等方面得到较全面的锻炼和提高,为今后能够独立
进行某些单片机应用系统的开发设计工作打下一定的基础。
该电子时钟不但具有定时作用还有温度采集作用。定时部分可以显示时、分、秒,
而且用按键还可以实现时间的调整和闹铃的设定。温度采集部分实现环境温度数据的
采集。
2 系统结构
整个电子时钟系统电路可分为五大部分:中央处理单元(CPU)、电源电路部分、
显示部分、键盘输入部分、温度采集部分。
2. 1 中央处理单元
CPU选用AT89C—2051 对整个系统进行控制:
1)它将定时数据输出到LED,实现时间的显示;
2)根据键盘输入调用相应键处理子程序,实现时间的调整和闹铃的设定;
3)接收温度传感器输入的温度数据,进行一定的转换,然后输出到2 位的LED
更多资料请访问 福星电子网-收集整理
3
显示器显示出来。
2.2 电源电路部分
在各种电子设备中,直流稳压电源是必不可少的组成部分,它是电子设备唯一能
量来源,它的设计思路是根据我们以前学过的模电电子技术,要想得到我们所要的
+6V输出电压,就需将交流220V的电压经过变压器、整流电路、滤波电路和稳压电
路四个部分。
2.3 显示部分
显示部分是整个电子时钟最为重要的部分,它分为时间的显示和温度的显示两部
分,共需要8 位LED 显示器。采用动态显示方式,所谓动态显示方式是时间(或温
度)数字在LED 上一个一个逐个显示,它是通过位选端控制在哪个LED 上显示数字,
由于这些LED 数字显示之间的时间非常的短,使的人眼看来它们是一起显示时间数
字的,并且动态显示方式所用的接口少,节省了CPU 的管脚。由于端口的问题以及
动态显示方式的优越性,在此设计的连接方式上采用共阴级接法。显示器LED 有段
选和位选两个端口,首先说段选端,它由LED 八个端口构成,通过对这八个端口输
入的不同的二进制数据使得它的时间(或温度)显示也不同,从而可以得到我们所要
的时间显示和温度。但对于二十个管脚的AT89C2051来说,LED 八个段选管脚太多,
于是我选用74LS164 芯片来扩展主芯片的管脚,74LS164 是数据移位寄存器,还选用
了74LS244 作为数据缓存器。
2.4 键盘部分
它是整个系统中最简单的部分,根据功能要求,本系统共需四个按键:
功能移位键、功能加键、功能减键、定闹键。并采用独立式按键。温度采
集部分
此部分选用DS18B20 传感器,主要由四部分组成:64 位ROM、温度传感器、非挥
发的温度报警触发器TH 和TL、配置寄存器。有三个管脚:DQ 为数字信号输入/输出
端;GND 为电源地;VDD 为外接供电电源输入端。电源有两种接法:1)远端因入;2)
寄生电源方式。它是支持“一线总线”接口的温度传感器,测量温度范围为
-55°C~+125°C,在-10~+85°C 范围内,可编程为9 位—12 位A/D 转换精度,工作电
压在3V—5V之间。现场温度直接以“一线总线”的数字方式传输,大大提高了系统
的抗干扰性。
何为“一线总线”:独特的电源和信号复合在一起;仅使用一条口线;每个芯片
唯一编码,支持联网寻址;简单的网络化的温度感知;零功耗等待。
2.电路制作
根据元器件种类和体积以及技术要求将其布局在电路板上的适当位置。可以先从
体积较大的器件开始,如单片机底座、电源稳压器、变压线圈、锁存器、温度传感器
等。待体积较大的元器件布局好之后,小型的电子元器件就可以根据间隙面积灵活布
置。二极管、电感器、阻容元件的装配方式一般有直立式、俯卧式和混合式三种。
①直立式。电阻、电容、二极管等都是竖直安装在印刷板上的。这种方式的特点
是:在一定的单位面积内可以容纳较多的电子元件,同时元件的排列也比较紧凑。缺
点是:元件的引线过长,在一个平面上,欠美观,元器件引脚弯曲,且密度较大,元
器件之间容易引脚碰触,可靠性欠佳,且不太适合频率较高的电路采用。
②俯卧式。电阻、电容、二极管等都是俯卧式安装在印刷板上的。这样可以明显
地降低元件的排列高度,可实现薄形化,同时元器件的引脚也最短,适合于较高工作
频率的电路采用,也是目前采用最广泛的一种安装方式。
③混合式。为了适应各种不同条件的要求或某些位置受面积所限,在一块印刷电
路板上,有的元器件则采用俯卧式。这受到电路结构各式以及机壳内尺寸的限制,同
时灵活处理。
元器件配置布局应考虑的因素:
①电路板是矩形,元件排列的长度方向一般应与电路板的长边平行,这样不但可
以提高元件的装配好的印刷电路板更美观。
②应尽可能地缩短元件及元件之间的引线。尽量避免电路板上的导线的交叉,设
法减小它们的分布电容和互相之间的电磁干扰,以提高系统工作的可靠性。
③应以功能电路的核心器件为中心,外围元件围绕它进行布局。
更多资料请访问 福星电子网-收集整理
5
④要注意各种门电路多余的处理,或接电源端或接地端,并按照正确的 方法实
现不同逻辑门的组合转换。
⑤元器件的配置和布局应有利于设备的装配、检查、高度和维修。
元器件焊接注意事项:
焊接前务必认准元件数值,会认元件上的标识和会用数字多用表测试。焊接时速
度要快,电烙铁不可长时间停留在电路板和元件的焊脚上。特别是晶振、发光二极管、
电解电容、9041 三极管等元件,时间过长容易导致元器件损坏。
3.软件仿真
3.1仿真器介绍
仿真器采用伟福仿真器系统,该仿真器介绍如下:
系统的特点介绍
本仿真器系统由仿真主机+仿真头、MULTIA用户板、实验板、开关电源等组成。
本系统的特点是:
1.主机+仿真头的组合,通过更换不同型号的仿真头即可对各种不同类型的单片
机进行仿真,是一种灵活的多CPU 仿真系统。采用主机+POD 组合方式,更换POD,可
以对各种CPU 进行仿真。本仿真器主机型号为E2000/S,仿真头型号为POD8X5X(可
仿真系列8X5X单片机)。
2.双平台,具有DOS版本和WINDOWS 版本,后者功能强大,中/英文界面任选,
用户源程序的大小不再有任何限制,支持ASM,C,PLM 语言混合编程,具有项目管理
功能,为用户的资源共享、课题重组提供强有力的手段。支持点屏显示,用鼠标左键
点一下源程序中的某一变量,即可显示该变量的数值。有丰富的窗口显示方式,多方
位,动态地显示仿真的各种过程,使用极为便利。本操作系统一经推出,立即被广大
用户所喜爱。
3.双工作模式
1)软件模拟仿真(不要仿真器也能模拟仿真)。
2)硬件仿真。
4.双CPU 结构,100%不占用户资源。
全空间硬件断点,不受任何条件限制,支持地址、数据、外部信号、事件断点、
支持实时断点计数、软件运行时间统计。
5.双集成环境
编辑、编译、下载、调试全部集中在一个环境下
多种仿真器,多类CPU 仿真全部集成在一个环境下。可仿真51 系列,196 系列,
PIC 系列,飞利蒲公司的552、LPC764、DALLAS320,华邦438 等51 增强型CPU。为
了跟上形势,现在很多工程师需要面对和掌握不同的项目管理器、编辑器、编译器。
他们由不同的厂家开发,相互不兼容,使用不同的界面,学习使用都很吃力。伟福
WINDOWS 调试软件提供了一个全集成环境,统一的界面,包含一个项目管理器,一个
功能强大的编辑器,汇编Make,Build 和调试工具并提供千个与第三方编译器的接口。
更多资料请访问 6
由于风格统一,大大节省了精力和时间。
6.强大的逻辑分析仪综合调试功能。
逻辑分析仪由交互式软件菜单窗口对系统硬件的逻辑或时序进行同步实时采样,
并实时在线调试分析,采集深度32K(E2000/L),最高时基采样频率达20MHz,40
路波形,可精确实时反映用户程序运行时的历史时间。系统在使用逻辑分析仪时,除
普通的单步运行、键盘断点运行、全速硬件断点运行外,还可实现各种条件组合断点
如:数据、地址、外部控制信号、CPU 内部控制信号、程序区间断点等。由于逻辑仪
可以直接对程序的执行结果进行分析,因此极大地便利于程序的调试。
7.强大的追踪器功能
追踪功能以总线周期为单位,实时记录仿真过程中CPU 发生的总线事件,其触
发条件方式同逻辑分析仪。追踪窗口在仿真停止时可收集显示追踪的CPU指令记忆信
息,可以以总线反汇编码模式、源程序模式对应显示追踪结果。屏幕窗口显示波形图
最多追踪记忆指令32K并通过仿真器的断点、单步、全速运行或各种条件组合断点来
完成追踪功能。总线跟踪可以跟踪程序的运行轨迹。可以统计软件运行时间。
伟福系统仿真
3.2 仿真器编程
双击桌面上的WAVE 图标或从开始/程序/WAVE FOR WINDOWS/WAVE 进入本开发环
境。在实验开始时要先根据需要设置好仿真器类型、仿真头类型以及CPU类型,并注
7
意是否“使用伟福软件模拟器”,若使用硬件仿真,请注意去掉“使用伟福软件模拟
器”前的选择。在文件窗口下可进行包括新建、打开、保存等文件操作。在编译文件
窗口下可将源文件编译成目标文件。在窗口窗口下可以观察各种窗口信息,其中最常
用到的是CPU 窗口和数据窗口。在CPU 窗口下可以通过CPU 窗口看到编译正确的机器
码及反汇编程序,可以更清楚地了解程序执行过程。CPU 窗口中还有SFR窗口和位窗
口,了解程序执行过程中寄存器内容的变化。在数据窗口下有DATA 内部数据窗口;
CODE 程序数据窗口;XDATA 外部数据窗口;PDTA外部数据窗口。
结束语
通过这次的设计使我认识到我对单片机方面的知识知道的太少了,对于书本上的
很多知识还不能灵活运用,有很多我们需要掌握的知识在等着我去学习,我会在以后
的学习生活中弥补我所缺少的知识。本次的设计使我从中学到了一些很重要的东西,
那就是如何从理论到实践的转化,怎样将我所学到的知识运用到我以后的工作中去。
在大学的课堂的学习只是在给我们灌输专业知识,而我们应把所学的用到我们现实的
生活中去,此次的电子时钟设计给我奠定了一个实践基础,我会在以后的学习、生活
中磨练自己,使自己适应于以后的竞争。
参考文献
[1] 李建忠主编,单片机原理及应用,西安电子科技大学出版社,2004
④ 利用CPU的定时器定时,设计一个电子时钟
没有定时器的不过有数字钟的
你可以参考下
其中可有有用的
摘要
本题给出基于单片机的数字中的设计,设计由单片机作为核心控制器,通过频率计数实现计时功能,将实时时间经由单片机输出到显示设备——数码管上显示出来,并通过键盘来实现启动、停止、复位和调整时间的功能。
关键词: 单片机、数字钟、AT89S52、LED
1 引言
在单片机技术日趋成熟的今天,其灵活的硬件电路的设计和软件的设计,让单片机得到了广泛的应用,几乎是从小的电子产品,到大的工业控制,单片机都起到了举足轻重的作用。单片机小的系统结构几乎是所有具有可编程硬件的一个缩影,可谓是“麻雀虽小,五脏俱全”。
现在是一个知识爆炸的新时代。新产品、新技术层出不穷,电子技术的发展更是日新月异。可以毫不夸张的说,电子技术的应用无处不在,电子技术正在不断地改变我们的生活,改变着我们的世界。在这快速发展的年代,时间对人们来说是越来越宝贵,在快节奏的生活时,人们一旦遇到重要的事情而忘记了时间,这将会带来很大的损失,因此我们需要一个计时系统来提醒这些忙碌的人。 然而,随着科技的发展和社会的进步,人们对时钟的要求也越来越高,传统的时钟已不能满足人们的需求。多功能数字钟不管在性能上还是在样式上都发生了质的变化,如电子闹钟、数字闹钟等等。 单片机在多功能数字钟中的应用已是非常普遍的,基于单片机的数字钟给人们带来了极大的方便。
现今,高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟,石英表,石英钟都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调校,数字式电子钟用集成电路计时,译码代替机械式传动,用LED显示器代替指针显示进而显示时间,减小了计时误差,这种表具有时,分,秒显示时间的功能,还可以进行时和分的校对,片选的灵活性好。本文利用单片机实现数字时钟计时功能的主要内容,其中AT89S52是核心元件同时采用数码管动态显示“时”,“分”,“秒”的现代计时装置。与传统机械表相比,它具有走时精确,显示直观等特点。它的计时周期为24小时,显满刻度为“23时59分59秒”,另外具有校时功能,断电后有记忆功能,恢复供电时可实现计时同步等特点。
2 方案论证
2.1 方案一
数字钟采用FPGA作为主控制器。由于FPGA具有强大的资源,使用方便灵活,易于进行功能扩展,特别是结合了EDA,可以达到很高的效率。此方案逻辑虽然简单一点,但是一块FPGA的价格很高,对于做电子钟来说有一点浪费,而且FPGA比较难掌握,本设计中不作过多研究,也不采用此方案。
2.2 方案二
数字钟由几种逻辑功能不同的CMOS数字集成电路构成,共使用了10片数字集成电路,其原理图如图2.1所示。它是由秒信号发生器(时基电路)、小时分钟计数器及译码和驱动显示电路3部分组成,其基本工作过程是:时基电路产生精确周期的脉冲信号,经过分频器作用给后面的计数器输送1HZ的秒信号,最后由计数器及驱动显示单元按位驱动数码管时间显示,但是这样设计的电路比较复杂,使用也不灵活,而且价格比较高,故不采用此方案。
图2.1 方案二原理示意图
2.3 方案三
AT89S52是一种低功耗、高性能CMOS 8位微控制器。使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、有效的解决方案。它具有串行口,片内晶振及时钟电路。另外,AT89S52可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
基于AT89S52单片机来实现系统的控制,外围电路比较简单,成本比较低,此系统控制灵活能很好地满足本课题的基本要求和扩展要求,因此选用该方案。其硬件框图如图2.2所示,原理图见附录图6.1。
图2.2 数字钟硬件框图
2.4 电路组成及工作原理
本文数字时钟设计原理主要利用AT89S52单片机,由单片机的P0口控制数码管的位显示,P2口控制数码管的段显示,P1口与按键相接用于时间的校正。在设计中引入220V交流电经过整流、滤波后产生+5V电压,用于给单片机及显示电路提供工作电压。
整个系统工作时,秒信号产生器是整个系统的时基信号,它直接决定计时系统的精度,将标准秒信号送入“秒计数器”,“秒计数器”采用60进制计数器,每累计60秒发出一个“分脉冲”信号,该信号将作为“分计数器”的时钟脉冲。“分计数器”也采用60进制计数器,每累计60分钟,发出一个“时脉冲”信号,该信号将被送到“时计数器”。“时计数器”采用24进制计时器,可实现对一天24小时的累计。显示电路将“时”、“分”、“秒”计数器的输出,通过六个七段LED显示器显示出来。校时电路是直接加一个脉冲信号到时计数器或者分计数器或者秒计数器来对“时”、“分”、“秒”显示数字进行校对调整。在本设计中,24小时时钟显示、秒表的设计和显示都是依靠单片机中的定时器完成。使用定时器T0产生1s的中断,在中断程序中完成每一秒数字的变化,并在主程序中动态显示该字符。其功能框图如图2.3所示。
图2.3 秒表外中断的功能示意图
数字钟的电路设计主要功能是提供单片机和外部的LED显示、273地址锁存和片选以及外部存储器2764的接口电路,此外还需要设计相关的LED驱动电路。
(1)电路原理和器件选择
本实例相关的关键部分的器件名称及其在数字钟电路中的主要功能:
89S52:单片机,控制LED的数据显示。
LED1--LED6:用于显示单片机的数据,其中三个采用7段显示用于显示时、分、秒的十位,另三个采用8段显示用于显示时、分、秒的个位。
74LS273:锁存器,LED显示扩展电路中的段码和位码使用了两片74LS273,上升沿锁存。
74LS02:与非门,与单片机的读写信号一起使用,选中外部的74LS273,决定LED的字段和字位的显示内容。
7407:驱动门电路,提供数码管显示的驱动电流。
74LS04:非门,对单片机的片选信号取反,并和读写信号一起使用,决定74LS273的片选。
L1--L4:发光二极管,通过单片机的P1.4--P1.7控制,用以显示秒表和时钟的时间变化。
BUZZER:扬声器,在程序规定的情况下,发出声音,提示计时完毕。
74LS373:地址锁存器,将P0口的地址和数据分开,分别输入到2764的数据和地址端口。
2764:EPROM,为单片机提供外部的程序存储区。
开关K0、K1、K2分别调整秒、分、时。
按键RESET:在复位电路中,起到程序复位的作用。
按键PULSE:提供单脉冲,从而实现单片机对外部脉冲的计数功能,利用单脉冲实现相应位加1。
(2)地址分配和连接
P2.7:和写信号一起组成字位口的片选信号,字位口的对应地址位8000H
P2.6:和写信号一起组成字段口的片选信号,字段口的对应地址位4000H
D0--D7:单片机的数据总线,LED显示的内容通过D0--D7数据线从单片机传送到LED
P2.0--P2.5:单片机的P2口,和2764的高端地址线相连,决定2764中的存储单元的地址。
P1.4--P1.7:单片机的P1口,和反光二极管L1--L4相连,通过单片机的P1.4--P1.7控制,用以显示秒表和时钟的时间变化。
(3)功能简介
LED显示模块与单片机的连接中,对LED显示模块的读写和字位、字段通道的选择是通过单片机的P2.6、P2.7口完成。其中,P2.6、P2.7口的片选信号需要和读写信号做一定的逻辑操作,以保证字位和字段选择的正确性。
外部存储器2764是通过74LS373和单片机相连,并且通过P2口的相关信号线进行地址的分配。地址范围为0000H--1FFFH。
3 各电路设计和论证
3.1电源电路设计
在各种电子设备中,直流稳压电源是必不可少的组成部分,它不仅为系统提供多路电压源,还直接影响到系统的技术指标和抗干扰性能。要想得到我们所要的+5V输出电压,就需将交流220V的电压经过二极管全波整流、电容滤波、7805稳压输出稳定的5V直流电压为整个电路提供电源。
图3.1 电源电路图
4个IN4004组成桥式整流电路,电容(104uf)用于滤波,LM7805将经过整流滤波的电压稳定在5V输出。
3.2 晶体振荡器
51系列单片机内部有一个时钟电路(其核心时一个反相放大器),但并没有形成时钟的振荡信号,因此必须外接谐振器才能形成振荡。如何用这个内部放大器,可以根据不同的场合做出不同的选择。这样就对应了单片机时钟产生的不同方式:若采用这个放大器,产生振荡即为内部方式;若采用外部振荡输入,即为外部方式。
方案一、内部方式
如果在51单片机的XTAL1和XTAL2引脚之间外接晶体谐振器,便会产生自激振荡,即可在内部产生与外加晶体同频率的振荡时钟。
最常见的内部方式振荡图如图3.2所示。
图3.2 晶体振荡电路
不同单片机最高工作频率不一样,如AT89C51的最高工作频率为24MHZ,AT89S51的最高工作频率可达33MHZ。由于制造工艺的改进,现在单片机的工作频率范围正向两端延伸,可达40MHZ以上。振荡频率越高表示单片机运行的速度越快,但同时对存储器的速度和印刷电路板的要求也就越高。频率太高有时反而会导致程序不好编写(如延时程序)。一般来说,不建议使用很高频率的晶体振荡器。51系列的单片机应用系统一般都选用频率为6~12MHZ的晶振。
这个电路对C1、C2的值没有严格的要求,但电容的大小多少会影响振荡器的稳定性、振荡器频率的高低、起振的快速性等。一般外接晶体时,C1、C2的值通常选为20~100PF。
晶体振荡器是数字钟的核心。振荡器的稳定度和频率的精确度决定了数字钟计时的准确程度,通常采用石英晶体构成振荡器电路。一般说来,振荡器的频率越高,计时的精度也就越高。在此设计中,信号源提供1HZ秒脉冲,它是采用晶体分频得到的。AT89S52单片机有一个用于构成内部振荡器的反相放大器,XTAL1和XTAL2分别是放大器的输入、输出端。石英晶体和陶瓷谐振器都可以用来一起构成自激振荡器。从外部时钟源驱动器件,XTAL2可以不接,而从XTAL1接入,由于外部时钟信号经过二分频触发后作为外部时钟电路输入的,所以对外部时钟信号的占空比没有其它要求,最长低电平持续时间和最少高电平持续时间等还是要符合要求的。反相放大器的输入端为XTAL1,输出端为XTAL2,两端连接石英晶体及两个电容形成稳定的自激振荡器。电容通常取30PF左右。振荡频率范围是1.2~12MHz。
晶体振荡器的振荡信号从XTAL2端输出到片内的时钟发生器上。时钟发生器为二分频器。向CPU提供两相时钟信号P1和P2。每个时钟周期有两个节拍(相)P1和P2,CPU就以两相时钟P1和P2为基本节拍指挥AT89S52单片机各部件协调工作。在本次设计中取石英晶体的振荡频率为11.0592MHz。
另外在设计电路板时,晶振、电容等均应尽量靠近单片机芯片,以减小分布电容,进一步保证振荡器的稳定性。
方案二、外部方式
在较大规模的应用系统中可能会用到多个单片机,为保证各单片机之间时钟信号的同步,应当引入唯一的公用外部脉冲信号作为各单片机的共同的振荡脉冲,也就是要采用外部方式,外部振荡信号直接引入XTAL1和XTAL2引脚。
由于HMOS、CHMOS单片机内部时钟进入的引脚不同,因此外部振荡信号的接入方式也不一样。所以不选用此方案。
3.3 校时电路
当数字钟走时出现误差时,需要校正时间。校时控制电路实现对“秒”、“分”、“时”的校准。其电路图如图3.3所示:
图3.3 校时电路
3.4 译码显示电路
译码电路的功能是将“秒”、“分”、“时” 计数器中每个计数器的输出状态(8421码),翻译成七段(或八段)数码管能显示十进制数所要求的电信号,然后再经数码管把相应的数字显示出来。译码器采用74LS248译码/驱动器。显示器采用七段共阴极数码管。显示部分是整个电子时钟最为重要的部分,共需要6位LED显示器。采用动态显示方式,所谓动态显示方式是时间数字在LED上一个一个逐个显示,它是通过位选端控制在哪个LED上显示数字,由于这些LED数字显示之间的时间非常的短,使的人眼看来它们是一起显示时间数字的,并且动态显示方式所用的接口少,节省了CPU的管脚。由于端口的问题以及动态显示方式的优越性,在此设计的连接方式上采用共阴级接法。显示器LED有段选和位选两个端口,首先说段选端,它由LED八个端口构成,通过对这八个端口输入的不同的二进制数据使得它的时间显示也不同,从而可以得到我们所要的时间显示和温度。但对于二十个管脚的AT89S52来说,LED八个段选管脚太多,于是我选用2764芯片来扩展主芯片的管脚,74LS164是数据移位寄存器,还选用了74LS373作为数据缓存器。
选用器件时应注意译码器和显示器的匹配,包括两个方面:一是功率匹配,即驱动功率要足够大。因为数码管工作电流较大,应选用驱动电流较大的译码器或OC输出译码器。二是逻辑电平匹配。例如,共阴极型的LED数码管采用高电平有效的译码器。推荐使用的显示译码器有74LS48、74LS49、CC4511。
3.5 显示电路结构及原理
(1)单片机中通常用七段LED构成 “8” 字型结构,另外,还有一个小数点发光二极管以显示小数位!这种显示器有共阴和共阳两种!发光二极管的阳极连在一起的(公共端)称为共阳极显示器,阴极连在一起的称为共阴极显示器。
一位显示器由8个发光二极管组成,其中,7个发光二极管构成字型“8”的各个笔划,另一个发光二极管为小数点为。当在某段发光二极管上施加一定的正向电压时,该段笔画即亮;不加电压则暗。为了保护各段LED不被损坏,需外加限流电阻。
在本设计中时、分、秒的十位采用七段显示,个位采用八段显示,使得更易于区分时、分、秒。
(2)LED显示器接口及显示方式
LED显示器有静态显示方式和动态显示方式两种。静态显示就是当显示器显示某个字符时,相应的段恒定的导通或截止,直到显示另一个字符为止。LED显示器工作于静态显示方式时,各位的共阴极接地;若为共阳极则接+5V电源。每位的段选线分别与一个8位锁存器的输出口相连,显示器中的各位相互独立,而且各位的显示字符一经确定,相应锁存的输出将维持不变。
正因为如此,静态显示器的亮度较高。这种显示方式编程容易,管理也较简单,但占用I/O口线资源较多。因此,在显示位数较多的情况下,一般都采用动态显示方式。
由于所有6位段皆由一个I/O口控制,因此,在每一瞬间,6位LED会显示相同的字符。要想每位显示不同的字符,就必须采用扫描方法流点亮各位LED,即在每一瞬间只使某一位显示字符。在此瞬间,段选控制I/O口输出相应字符段选码(字型码),而位选则控制I/O口在该显示位送入选通电平(因为LED为共阴,故应送低电平),以保证该位显示相应字符。如此轮流,使每位分时显示该位应显示字符。
在多位LED显示时,为了简化电路,降低成本,将所有位的段选线并联在一起,由一个8位I/O口控制。而共阴(共阳)极公共端分别由相应的I/O口线控制,实现各位的分时选通。
段选码,位选码每送入一次后延时2MS,因人的视觉暂留效应,给人看上去每个数码管总在亮。
图3.4 六位LED动态显示电路
3.6 键盘部分
它是整个系统中最简单的部分,根据功能要求,本系统共需三个按键:分别对时、分、秒进行控制。并采用独立式按键。
按键按照结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点式开关按键,如电气式按键,磁感应按键等。前者造价低后者寿命长。目前,微机系统中最常见的是触点式开关按键。
按键按照接口原理可分为编码键盘与非编码键盘两类,这两类键盘的主要区别是识别键符及给出相应键码的方法。编码键盘主要是用硬件来实现对键的识别,非编码键盘主要是由软件来实现键盘的定义与识别。
全编码键盘能够由硬件逻辑自动提供与键对应的编码,此外,一般还具有去抖动和多键、窜键保护电路。这种键盘使用方便,但需要较多的硬件,价格较贵,一般的单片机应用系统较少采用。非编码键盘只简单地提供行和列的矩阵,其它工作均由软件完成。由于其经济实用,较多地应用于单片机系统中。在本套设计中由于只需要几个功能键,此时,可采用独立式按键结构。
独立式按键是直接用I/O口线构成的单个按键电路,其特点是每个按键单独占用一根I/O口线,每个按键的工作不会影响其它I/O口线的状态。独立式按键的典型应用如图3.5 所示。
独立式按键电路配置灵活,软件结构简单,但每个按键必须占用一根I/O口线,因此,在按键较多时,I/O口线浪费较大,不宜采用。
图3.5 独立式按键结构图
3.7 复位电路
复位时使CPU和系统中的其他功能部件都处于一个确定的初始状态,复位后计算机就从这个状态开始工作。在复位期间,CPU并没有开始执行程序,是在做准备工作。
无论时在计算机刚上电时、断电后、还是系统出现故障时都需要复位。
51单片机的复位条件靠外部电路实现。当时钟电路工作时,只要在单片机的RESET引脚上持续出现2个TP以上的高电平就可以使单片机复位。但时间过短往往使复位部可靠。为了确保复位,RESET引脚上的高电平一般要维持大约10ms以上。
常见的复位电路有上电复位和按键复位电路。在此我们选用按键复位电路。
(1)上电复位电路
上电复位电路是利用电容充电来实现的。在接通电源的瞬间,RESET端的电位与VCC相同,都是+5V。随着RC电路的充电,RESET的电位逐渐下降,只要保证RESET为高电平的时间大于10ms就能正常复位了。如图3.6(1)所示。
图3.6(1)上电复位电路
(2)按键复位电路
在单片机已经通电的情况下,只需要按下图3.6(2)的K键也可以复位,此时VCC经过电阻Rs、Rk分压,在RESET端产生一个复位高电平。
在图3.6(2)的电路中,干扰容易窜入复位端,虽然在大多数情况下不会造成单片机的错误复位,但可能会引起内部某些寄存器的错误复位。这时可在RESET端接上一个去耦电容。
另外有些单片机应用系统中的外围芯片也需要复位,如果这些复位端的复位电平要求和单片机的复位要求一致,则可以直接与之相连。常将RC电路接施密特电路后再接入单片机的复位端。这样系统可以有多个复位端,以便保证外部芯片和单片机可靠地同步复位。
图3.6(2) 按键复位电路
4 软件设计
4.1 程序流程
程序整体设计:定时模块,显示模块,时间调整模块,状态调整模块。
(1)总体介绍:此部分主要介绍定时模块,和显示模块。定时部分采用经典的定时器定时。它实现了数字钟的主要部分和秒表的主要部分,以及进行定时设置。显示模块是实现数字钟的又一重要部分,其模块的独立程度直接影响到数字钟的可视化程度。在此部分的设计中,设置专用显示数据缓冲区,与分、时及其他数据缓冲区数据区别,在其中存放的是显示段码,而其他缓冲区存放的是时间数据。在显示时,首先将时间十进制数据转化为显示段码,然后送往数码管显示。显示段码采用动态扫描的方式。在要求改变显示数据的类别时,只须改变指向数据缓冲区的指针所指向的十进制数据缓冲区即可。
(2)时间调整:时间调整有多种方式。一、可以直接进入相关状态进行有关操作,二、将调整分两步,先进入状态,然后执行操作,这两步分别由两个键控制。方式一,比较直接,设计思想也比较简单,但是,这种方式存在操作时间和控制键数目的矛盾。如果用比较少的键,那么可能会在进入状态后处于数据调整等待状态,这样会影响到显示的扫描速度(显示部分可以采用8279芯片来控制,可以解决此问题)。 当然在这种方式下,还可以使用多个状态键,每个状态键,完成一个对应数据的调整。如果采用二的方式,就不会出现这种情况。因为状态的调整,与状态的操作可以分别由两个键控制,其状态的调整数可以多达256个(理论上),操作的完成是这样的,一键控制状态的调整,一键控制数据的调整。以上两种方式的实现都可以采用查询和中断的方式。两种方式必须注意的问题是两者进行相关操作的过程不能太长否则会影响显示的扫描。利用查询的方式,方法传统,对此就不作过多的讨论,以下是采用中断的方式实现的数字钟的一些讨论和有关问题作的一些处理。基于以上的讨论可以设计如下:将调整分为状态调整和数据调整两部分,每次进入中断只执行一次操作,然后返回,这样,就不必让中断处于调整等待状态,这样,可以使中断的耗时很小。将定时器中断的优先级设置为最高级,那么中断的方式和查询的方式一样不会影响到时钟的记数。
(3)中断方式应注意的问题:
采用中断的方式,最好将定时器中断的优先级设置为最高级,关于程序数据的稳定性应注意两个问题:一、在低优先级中断响应时,应在入栈保护数据时禁止高优先级的中断响应。二、在入栈保护有关数据后,对中断程序执行有影响的状态位,寄存器,必须恢复为复位状态的值。例如,在用到了十进制调整时,在中断进入时,需将PSW中的AC,CY位清零,否则,十进制调整出错。
(4)定时准确性的讨论:
程序中定时器,一直处于运行状态,也就是说定时器是理想运作的,其中断程序每隔0.1秒执行一次,在理想状态下,定时器定时是没有系统误差的,但由于定时器中断溢出后,定时器从0开始计数,直到被重新置数,才开始正确定时,这样中断溢出到中断响应到定时器被重新置数,其间消耗的时间就造成了定时器定时的误差。如果在前述定时器不关的情况下,在中断程序的一开始就给定时器置数,此时误差最小,误差大约为:每0.1秒,误差7—12个机器周期。当然这是在定时器定时刚好为0.1秒时的情况,由以上分析,如果数字钟设计为查询的方式或是在中断的方式下将定时器中断设置为最高级,我们在定时值设置时,可以适当的扣除9个机器周期的时间值。但如果在中断的情况下,没有将定时器中断设置为最高级,那就要视中断程序的大小,在定时值设置时,扣除相应的时间值。
(5)软件消抖:
消抖可以采用硬件(施密特触发器)的方式如图4.4所示,也可以采用软件的方式。在此只讨论软件方式。软件消抖有定时器定时,和利用延时子程序的方式。一,定时器定时消抖可以不影响显示模块扫描速度,其实现方法是:设置标志位,在定时器中断中将其置位,然后在程序中查询。将其中断优先级设置为低于时钟定时中断,那么它就可以完全不影响时钟定时。二,在采用延时子程序时,如果显示模块的扫描速度本来就不是很快,此时可能会影响到显示的效果,一般情况下,每秒的扫描次数不应小于50次,否则,数码的显示会出现闪烁的情况。因此,延时子程序的延时时间应该小于20毫秒,如果采用定时器定时的方式,延时时间不影响时钟。
如果,设计时采用的是中断的方式来完成有关操作,同样可以采用软件的方式来消抖,其处理思想是:中断不能连续执行,两次之间有一定的时间间隔。
4.1.1 系统主程序流程图
图4.1 主程序流程图
4.1.2 各子程序流程图
图4.2 时钟调整子程序流程图
⑤ 求一份基于单片机的二进制时钟课程设计报告
这个具体的话还是要看你想做什么的,你熟悉什么的。
⑥ 如何用51单片机制作简易电子钟
我自己做的一个课程设计,程序运行已经成功了:
汇编程序如下:
ORG0000H
AJMPmain
ORG000BH;定时器0的中断向量地址
AJMPTIME0;跳转到真正的定时器程序处
ORG30H
main:
movdptr,#k1;
start:
MOVP0,#00H;中断预处理程序
MOVP1,#00H
MOVP3,#00H;关所有灯
MOVR0,#00H;软件计数器预清0
MOVR7,#00H
MOVR6,#00H
MOVTMOD,#00000001B;定时/计数器0工作于方式1
MOVTH0,#3CH
MOVTL0,#0B0H;即数15536
SETBEA;开总中断允许
SETBET0;开定时/计数器0允许
SETBTR0;定时/计数器0开始运行
LOOP:;判断时钟进位程序
MOVA,R1
CJNEA,#60,LOOP1;R1等于60吗?
MOVR1,#0
INCR2;R1等于60那么R2加一,R1清0
MOVA,R2
CJNEA,#60,LOOP1;R2等于60吗?
MOVR2,#0
INCR3;R2等于60那么R3加一,R2清0
MOVA,R3
CJNEA,#24,LOOP1;R3等于24吗?
MOVR3,#0
;R3等于24那么R3清0
LOOP1:
mova,r2;如果分钟显示为0,报警
cjnea,#01H,LOOP2
mova,r1
cjnea,#00H,LOOP3
clrp2.0
LOOP3:
mova,r1;如果秒钟显示为1,取消报警
cjnea,#05H,LOOP2
setbp2.0
LOOP2:;显示数据处理
MOVA,R1;取来8位二进制数
MOVB,#100
DIVAB;除以100
MOVA,B;取回余数
MOVB,#10
DIVAB;再除以10
MOVR4,A;商是十位数,存放到R4
MOVR5,B;余数是个位,存放到R5
MOV42H,R4
mOV41H,R5
;R1的BCD码放入41-42H单元
MOVA,R2;取来8位二进制数
MOVB,#100
DIVAB;除以100
MOVA,B;取回余数
MOVB,#10
DIVAB;再除以10
MOVR4,A;商是十位数,存放到R4
MOVR5,B;余数是个位,存放到R5
MOV44H,R4
MOV43H,R5
;R2的BCD码放入43-44H单元
MOVA,R3;取来8位二进制数
MOVB,#100
DIVAB;除以100
MOVA,B;取回余数
MOVB,#10
DIVAB;再除以10
MOVR4,A;商是十位数,存放到R4
MOVR5,B;余数是个位,存放到R5
MOV46H,R4
mov45H,R5
;R3的BCD码放入45-46H单元
L1:
mova,41h
movca,@a+dptr
mov51h,a
mova,42h
movca,@a+dptr
mov52h,a
mova,43h
movca,@a+dptr
mov53h,a
mova,44h
movca,@a+dptr
mov54h,a
mova,45h
movca,@a+dptr
mov55h,a
mova,46h
movca,@a+dptr
mov56h,a;将显示代码送入51H--56H
display:;显示程序
movp0,#0ffH;一
movp0,51H
movP1,#0feH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;二
movp0,52h
movP1,#0fdH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;三
movp0,53h
movP1,#0fbH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;四
movp0,54h
movP1,#0f7H
acalldelay1S
movp1,#0ffH
movp0,#0ffH;五
movp0,55h
movP1,#0efH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;六
movp0,56h
movP1,#0dfH
acalldelay1S
movp1,#0ffH
;将51H-56H数据显示,
AJMPLOOP;工作处理程序
TIME0:;定时器0的中断处理程序
INCR7
MOVA,R7
CJNEA,#20,T_RET;R7单元中的值到了20了吗?
T_L1:
INCR1;到了20那么R1+1
MOVR7,#0;清软件计数器
T_RET:;二十分之一秒时的程序
incr6
mova,r6
cjner6,#3,T_over;调节时间的延迟时间
movr6,#0
jbp2.1,T_over1
mova,r2
adda,#1
cjnea,#60,T_tiao1
mova,#0
T_tiao1:
movr2,a
T_over1:
jbp2.2,T_over
mova,r3
adda,#1
cjnea,#24,T_tiao2
mova,#0
T_tiao2:
movr3,a
T_over:
MOVTH0,#3CH
MOVTL0,#0B0H;如果没到一秒重置定时常数
reti
delay1s:MOV31H,#100
D1:MOV32H,#30
D2:DJNZ32H,D2
DJNZ31H,D1
RET
delay2s:MOV33H,#255
D3:MOV34H,#255
D4:DJNZ34H,D4
DJNZ33H,D3
RET
K1:db3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh
⑦ 利用单片机制作数字式时钟
我自己写了个代码,不过是用C来写的,自己看看可要
⑧ 求单片机电子时钟程序设计
#include "../inc/DS1307.H"
#include "../inc/delay.H"
#include "../inc/i2c.H" unsigned char idata Sec,Min,Hr,Dy,Dt,Mn,Yr;
bit hour_mode=0;
/********************************************************************************
函数功能: 数码转换
bcd:BCD码 z:为1转换高位,否则转换低位 Data:二进制数
********************************************************************************/
unsigned char BCD_ASCII(unsigned char bcd,bit z) //把BCD码转换为ASCII码
{
unsigned char temp;
if(z)
temp=(bcd>>4)+'0'; //+48
else temp=(bcd&0x0f)+'0'; //+48
return temp;
}
unsigned char CHAR_BCD(unsigned char Data) //把二进制数转换为BCD码
{
unsigned char bcd; if(Data>100) Data=0;
bcd = Data/10;
bcd<<=4;
bcd = bcd+(Data%10);
return bcd;
}
/********************************************************************************
函数功能: 判断日期是否合法
a:年(00-99之间) b:月 d:日
********************************************************************************/
bit Leap_year(unsigned char n) //判断是否为闰年 计算范围2000-2099年
{
if((((2000+n)%4 == 0)&&((2000+n)%100 != 0)) || ((2000+n)%400 == 0))
return 0;
else return 1; //是闰年返回1
}
bit Valid_date(unsigned char a,unsigned char b,unsigned char c)
{
unsigned char flag=1; if((b<=0)||(b>12)||(c<=0)||(c>31)) flag=0;
if(((b==4)||(b==6)||(b==9)||(b==11))&&(c>30)) flag=0;
if(Leap_year(a)) if((b==2)&&(c>29)) flag=0;
else if(b==2&&c>28) flag=0;
return flag; //合法返回1
}
/********************************************************************************
函数功能: 初始化时间和日期
********************************************************************************/
void RTC_init(void)
{
i2c_start();
i2c_sendbyte(ADDRTC); //写器件地址
i2c_waitACK();
i2c_sendbyte(0); // 地址指针置为 0
i2c_waitACK();
i2c_sendbyte(Sec&0x7f); //CH(Sec^7)位置为 0,启动时钟
i2c_waitACK();
i2c_stop();
i2c_start();
i2c_sendbyte(ADDRTC);
i2c_waitACK();
i2c_sendbyte(2); // 地址指针置为 2
i2c_waitACK();
if(hour_mode)
i2c_sendbyte(Hr|0x40); // 12小时模式,Hr^6置1
else i2c_sendbyte(Hr&0xbf); // 24小时模式,Hr^6置0
i2c_waitACK();
i2c_stop();
i2c_start();
i2c_sendbyte(ADDRTC);
i2c_waitACK();
i2c_sendbyte(7); // 地址指针置为 7
i2c_waitACK();
i2c_sendbyte(0x10); // sqwe引脚1Hz的输出
i2c_waitACK();
i2c_stop();
}
/********************************************************************************
函数功能: 写RTC寄存器
********************************************************************************/
void write_RTC_time(void)
{
i2c_start();
i2c_sendbyte(ADDRTC); // 写从机地址(器件地址)
i2c_waitACK();
i2c_sendbyte(0); // 地址指针置为 0
i2c_waitACK();
i2c_sendbyte(Sec); // Sec
i2c_waitACK();
i2c_sendbyte(Min); // Min
i2c_waitACK();
i2c_sendbyte(Hr); // Hr
i2c_waitACK();
i2c_sendbyte(Dy); // Dy
i2c_waitACK();
i2c_sendbyte(Dt); // Dt
i2c_waitACK();
i2c_sendbyte(Mn); // Mn
i2c_waitACK();
i2c_sendbyte(Yr); // Yr
i2c_waitACK();
i2c_stop();
}/********************************************************************************
********************************************************************************/