单片机时钟设计
一 前言……………………………………………….….. ..1 1.1数字电子钟的意义
1.2数字电子钟的应用
二 总体
设计………………………………………..…..1 2.1系统总体结构
2.2芯片选择
2.3PCF8563的主要性能指标
三 系统电路设计………………………………………..…..2 3.1 AT89S52单片机最小系统
3.2 PCF8563与AT89S52单片机接口电路设计
3.3接口电路与AT89S52单片机接口电路设计
四 系统软件设计………………………………………..…..6 4.1主程序框图
4.2 PCF8563时钟程序框图
4.3 显示程序框图
五 系统调试与测试结果
………………………………..9 5.1 实验系统连接图
5.2 程序调试
5.3 实验结果分析
六 设计总结………………………………………..………..9 附录…………………………………………………………11 1系统原理图
2程序清单
一 前言
1.1数字电子钟的意义
单片机模块中最常见的是数字钟,数字钟是一种用数字电路技术实现时、分、秒计时的装置,与机械式时钟相比具有更高的准确性和直观性,且无机械装置,具有更更长的使用寿命,因此得到了广泛的使用。
数字钟广泛用于个人家庭,车站, 码头办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟
, 钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,这些都是以钟表数字化为基础的。因此,研究数字钟及扩大其应用,有着非常现实的意义。
1.2数字电子钟的应用
数字钟已成为人们日常生活中:必不可少的必需品,广泛用于个人家庭以及车站、码头、剧场、办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大的方便。由于数字集成电路技术的发展和采用了先进的石英技术,使数字钟具有走时准确、性能稳定、携带方便等优点,它还用于计时自动报时及自动控制的领域。 二 总体方案设计
1. 系统总体结构
数字钟在日常生活中最常见,应用也最广泛。本文主要就是设计一款数字钟,
以89S52单片机为核心,时钟芯片,8255 IO扩展芯片等构成。数字钟采用24
小时制方式显示时间。
文章的核心主要从硬件设计和软件编程两个大的方面。硬件电路设计主要
包括CPU中央处理,计时,时间显示等三部分组成。软件用C语言来实现,主要
包括主程序、时间设置子程序、时间读取和写入子程序、数码管显示等软件模
块。
硬件:系统使用89S52单片机作为中央处理芯片,选用pcf8563时钟芯片保证时
间稳定运行,使用8255芯片对89S52单片机进行IO扩展,提供更多的需要使用
的接口,时间显示电路通过六位数码管实现,数码管位选和段选接口由8255
提供。
软件:程序主要分为两个部分:时间设置和读取部分,时间显示部分。通过操
作时序由单片机给SCL和SDA以相应的高低电平实现对PCF8563的读写操作,程
序循环读取实时时间;数码管显示子程序采用动态扫描的
,对数码管不同
位赋予不同值,显示不同数字,扫描速度以消除视觉误差为准。 2.芯片选择
PCF8563是PHILIPS公司推出的一款工业级内含I2C总线接口功能的具有极低功耗的多功能时钟/日历芯片。PCF8563的多种报警功能、定时器功能、时钟输出功
能以及中断输出功能能完成各种复杂的定时服务,甚至可为单片机提供看门狗功能。内部时钟电路、内部振荡电路、内部低电压检测电路以及两线I2C总线通讯方式,不但使外围电路极其简洁,而且也增加了芯片的可靠性。同时每次读写数据后,内嵌的字地址寄存器会自动产生增量。当然作为时钟芯片,PCF8563也解决了2000年问题。因而,PCF8563是一款性价比极高的时钟芯片,它已被广泛用于电表、水表、气表、电话、传真机、便携式仪器以及电池供电的仪器仪表等产品领域。
373为三态输出的八D透明锁存器,共有54/74S373和54/74LS373两种74LS
线路结构型式。373为三态输出的8 D透明锁存器, 373的输出端O0-O7可直接与总线相连。当三态允许控制端OE为低电平时,O0-O7为正常逻辑状态,可用来驱动负载或总线。当OE为高电平时,O0-O7呈高阻态,即不驱动总线,也不为总线的负载,但锁存器内部的逻辑操作不受影响。当锁存允许端LE为高电平时,O随数据D而变。当LE为低电平时,O被锁存在已建立的数据电平。当LE端施密特触发器的输入滞后作用,使交流和直流噪声抗扰度被改善400mV。
8255是Intel公司生产的可编程并行I/O接口芯片,有3个8位并行I/O口。具有3个通道3种工作方式的可编程并行接口芯片(40引脚)。 其各口功能可由软件选择,使用灵活,通用性强。8255可作为单片机与多种外设连接时的中间接
口电路。
AT89S52具有 8k字节Flash,256字节RAM,32 位I/O 口线,看门狗定时器,2 个数据指针,三个16 位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,
3 PCF8563的主要性能指标
宽电压范围1.0v-5.5v,复位电压
值为0.9v
超低功耗:典型值为0.25uA
可编程时钟输出频率为:32.768khz、1024hz、32hz、1hz
四种报警功能和定时器功能
内含复位电路、振荡器电容和掉电检测电路
400khz I2C总线,其从地址:读,0A3H;写,0A2H。
三 电路的硬件设计
1.at89s52单片机最小系统
单片机最小系统或者称为最小应用系统,是用最少的元件组成的单片机可以工作的系统,对51系列单片机来说,最小系统一般应该包括:单片机、复位电路、晶振电路。
复位电路:复位电路采用手动复位,所谓手动复位,是指通过接通一按钮开关,使单片机进入复位状态。
晶振电路:用电容和一个晶体振荡器组成为整个电路提供时钟频率。89C58单片
机的时钟信号通常用两种电路形式电路得到:内部震荡方式和外部中断方式。在引脚XTAL1和XTAL2外部接晶振电路器(简称晶振)或陶瓷晶振器,就构成了内部晶振方式。由于单片机内部有一个高增益反相放大器,当外接晶振后,就构成了自激振荡器并产生振荡时钟脉冲。
2(Pcf8563与at89s52单片机接口电路设计 PCF8563是PHILIPS公司推出的一款工业级内含I2C总线接口功能的具有极低功
日历芯片。8563与89S52单片机连接,其时钟线SCL和数据线耗的多功能时钟/
SDA分别与单片机P1.6,P1.7相连,时钟线与数据线需要同时接上拉电阻,Vdd和Vcc分别接通电源和接地。OSCI和OSCO之间接晶体振荡器。
通过芯片pcf8563操作时序的要求,对其进行初始时间设置,写字节,读字节,写入和读取时间的操作。仿真图如下。
3显示电路与at89s52单片机接口电路设计
动态显示驱动。通过单片机对数码管位选通COM端电路的控制,只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。动态显示可以大幅度地降低硬件成本和电源的功耗,因为某一时刻只有一个数码管工作,也就是所谓的分时显示,故显示所需要的硬件电路可分时复用。动态显示方式设计上如果处理不当,易造成亮度低,闪烁问题。因此合
又要保证显示后的数据稳定,无闪烁。 理的设计既应保证驱动电路易实现,
动态显示采用多路复用技术的动态扫描显示方式, 复用的程度不是无限增加的, 因为利用动态扫描显示使我们看到一幅稳定画面的实质是利用了人眼的暂留效应和发光二极管发光时间的长短, 发光的亮度等因素. 我们通过实验发现, 当扫描刷新频率(发光二极管的停闪频率) 为50Hz, 发光二极管导通时间?1m s 时, 显示亮度较好, 无闪烁感.。
通常用的共阳数码显示器的内部有8个发光二极管,其中7个发光二极管组成了数字“8”,剩下一个发光二极管就是这位数字所带的小数点。数码管结构图如图1 - 2所示。各段码位与显示段的对应关系如表1。
图1 – 2 LED数码管结构引脚图
表1 各段码位的对应关系
段码位 D7 D6 D5 D4 D3 D2 D1 D0
显示段 dp g f e d c b a
1. I/O 地址分配
四 软件设计
1) 主程序框图
2) Pcf8563时钟程序框图
3) 显示程序框图
五 系统调试与测试结果分析
1.程序调试
软件程序的调试一般可以将重点放在分模块调试上,统调是最后一环。软件本次课题,选用Keil软件来调试程序,通过各个模块程序的单步或跟踪调试,使程序逐渐趋于正确,最后统调程序。然后在实验箱上进行运行,观察显示结果。根据显示的结果和课题的要求再修改程序,再运行查,直到满足要求。 这次课设两次次调试。第一次调试时,数码管上显示的时间和最初设置的时间不同,秒显示在了分的位置上,检查程序时发现是把秒的地址0x02写成了0x03.改正后可以正常显示。 第二次调试时,最初设置的时间可以正常显示在数码管上,可是时间却不能正常走,再次检查程序没有发现问题,检查试验箱时,发现是线连错了,
由于之前使用实验箱的人将P1.6接SCL,P1.7接SDA,而我们的设计是将P1.6接SDA,P1.7接SCL。改正后,数字钟就可以正常工作了。
2实验结果分析
本系统已符合设计课程基本要求,即可以实现24小时方式;可用六位LED数码管显示时、分、秒;
附录
#include
#include #include
#define uchar unsigned char #define uint unsigned int #define wx XBYTE[0x0ff20]//位选为8255,A口 #define dx XBYTE[0x0ff21]//段选为8255,B口 #define control XBYTE[0x0ff23]//控制寄存器
sbit SDA=P1^6;//定义数据线端口为p1.6 sbit SCL=P1^7;//定义时钟线端口为p1.7 uchar NUM[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //定义七段共阳数码管
数编码表
bit busy=0;
uchar sg;//小时的十位
uchar sd;//小时的个位
uchar fg;//分钟的十位
uchar fd;//分钟的个位
uchar mg;//秒的十位
uchar md;//秒的十位
uchar hou=0x23;// 赋时分秒的初值,应为8563时分秒寄存器为BCD格式,所以需为16进制。
uchar min=0x59;
uchar sec=0x30;
uchar subadd;
uchar dat;
uchar number;
void start_iic();
void stop_iic();
void send_pcf8563_byte(); void receive_pcf8563_byte();
void timechange(); void display(void);
void start_iic() //开启PCF8563IIC {
SDA=1;
SCL=1;
SDA=0;//SCL为低,SDA执行一个上跳
SCL=0;//SCL为低,嵌住数据线
}
void stop_iic() //关闭PCF8563IIC
{
SDA=0;
SCL=1;
SDA=1;//SCL为高,SDA执行一个上跳
SCL=0;//SCL为低,嵌住数据线
}
void display()//显示时间六位
{uint count;
dx=0xff;//关闭数码管显示,防止显示跳变干扰
dx=NUM[md];//要显示的秒的个位送8255PB口
wx=0xfe;//8255PA0=0,数码管0显示
for(count=0;count<200;count++);//延时,大约200us是数码管保持足够的亮度同时亮灭时
不被
dx=0xff;
dx=NUM[mg];//要显示的秒的十位送8255PB口人眼分辨完成动态扫描
wx=0xfd;//8255PA1=0,数码管1显示
for(count=0;count<200;count++);
dx=0xff;
dx=NUM[fd];//要显示的分钟的个位送8255PB口
wx=0xfb;//8255PA2=0,数码管2显示
for(count=0;count<200;count++);
dx=0xff;
dx=NUM[fg];//要显示的分钟的十位送8255PB口
wx=0xf7;//8255PA3=0,数码管3显示
for(count=0;count<200;count++);
dx=0xff;
dx=NUM[sd];//要显示的小时的个位送8255PB口
wx=0xef;//8255PA4=0,数码管4显示
for(count=0;count<200;count++);
dx=0xff;
dx=NUM[sg];//要显示的小时的十位送8255PB口
wx=0xdf;//8255PA4=0,数码管5显示
for(count=0;count<200;count++); }
void Send_pcf8563_byte(uchar bb) //向PCF8563发送一个字节
{
uchar aa;
SCL=0;
for(aa=0;aa<8;aa++)
{ if((bb&0x80)==0x80)
{
SDA=1;
}
else
{
SDA=0;
}
SCL=1;
SCL=0;
bb=bb<<1;
}
_nop_();
_nop_();
SDA=1;
SCL=1;
busy=0;
if(SDA)
{
busy=1;
}
else
{
_nop_();
_nop_();
SCL=0;
busy=0;
}
}
void write_iic(uchar subadd,uchar dat)// 向PCF8563对应地址写数据
{
start_iic();
Send_pcf8563_byte(0xa2);
if(!busy)
{
Send_pcf8563_byte(subadd);
if(!busy)
{
Send_pcf8563_byte(dat);
}
}
stop_iic();
}
void timechange()
{
sg=(int)hou/16;
sd=(int)hou%16;
fg=(int)min/16;
fd=(int)min%16;
mg=(int)sec/16;
md=(int)sec%16;
}
void read_pcf8563() //读当时的时,分,钞 {
start_iic();
Send_pcf8563_byte(0xa2);
if(!busy)
{
Send_pcf8563_byte(0x02);
if(!busy)
{
start_iic();
Send_pcf8563_byte(0xa3);
receive_pcf8563_byte();
sec=number&0x7f;
start_iic();
Send_pcf8563_byte(0xa3);
receive_pcf8563_byte();
min=number&0x7f;
start_iic();
Send_pcf8563_byte(0xa3);
receive_pcf8563_byte();
hou=number&0x3f;
}
}
stop_iic();
}
void receive_pcf8563_byte() //从PCF8563接受一个字节
{uchar cc;
SDA=1;
number=0;
for(cc=0;cc<8;cc++)
{
number<<=1;
SCL=0;
SCL=1;
_nop_();
_nop_();
number= number|SDA;
}
SCL=0;
_nop_();
_nop_();
}
void main(void) {
control=0x81;//8255A口和B口为输出 write_iic(0x02,sec); //写钞 write_iic(0x03,min); //写分 write_iic(0x04,hou); //写时 while(1)
{
read_pcf8563();//读当前时间
timechange(); //从PCF8563读出时间,并转换分离的BCD码,为显示做准备
display(); //显示当前时间 }
}