好久之前学了点51,现在随手做了一个基于51普中开发板进行的时间计时和倒计时以及倒计时计数装置设计,设计较为简单。
第一章 设计原理
1.1 设计要求思路
以STC12C5A60S2(引脚排序及基本功能同AT89S51)作为主控芯片,设计利用LCD1602显示时间和倒计时时间(最大99:59:59)的装置。一是扩展DS12C887时钟电路设计,;二是利用LCD1602显示时间和倒计时剩余时间;三是在倒计时时间减为零以后,进行加1时间显示;四是设计启动、暂停、停止按键来进行倒计时的时间控制。
1.2 设计原理结构图
设计总共分为三个部分(如图1.1):1、倒计时显示 2、功能控制 3、时钟显示。本课设实验将围绕这三部分进行设计。
图1.1 设计原理机构示意图
1.3 设计原理简介
1.3.1 倒计时显示
倒计时设计采用了51单片机里的定时器,通过定时器的中断系统来控制定时器的开关,从而达到能控制倒计时的开启、暂停与停止(复位)。倒计时采用99:60:60的时间来进行倒计时,并且在每60秒清零后,位于LCD1602的第二行第15列位置的数值将会进行+1数值计算显示。
1.3.2 按键控制
本设计共设置了3个独立按键,其中2个按键分别从中断系统中将TR0进行开关控制,当按键1按下时,中断系统的TR0=1,51单片机的定时器将被打开,倒计时开启;当按键2按下时,中断系统的TR0=0,51单片机的定时器将被暂停运行,倒计时暂停计数。按键3则将倒计时进行复位,以便于重新进行倒计时。
1.3.3 DS1302与DSC887时钟显示 两者皆为时钟芯片,使用区别之一是DS1302为串口通讯,而DS12C887则是并口通讯。本实验开发板使用了是普中的开发板,故主要以DS1302芯片为介绍,DSC887为辅介绍。
(1)DS1302时钟芯片
操作DS1302的大致过程,就是将各种数据写入DS1302的寄存器,来设置它当前的时间的格式;然后使DS1302开始运作,DS1302时钟会按照设置情况运转,再用单片机将其寄存器内的数据读出;最后用LCD1602显示,进而就能得到一个简易的电子时钟。
(2)DS12C887
DS12C887时钟芯片能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部有世纪寄存器,从而利用硬件电路解决“千年”问题。 DS12C887中自带电池,外部掉电时,其内部时间信息还能够保持10年之久,对于一天内的时间记录,有12小时制和24小时制两种模式,但开发板上只有时钟芯片,故当开发板掉电时,DS12C887的数据也将一并丢失(本次实验DS1302时钟芯片也同理),故扩展的电子时钟需要通过软件来进行设计。
1.4 LCD1602显示
本课设实验LCD1602的第一行为字符和倒计时99:60:60的显示(如图1.2 LCD1602显示),第二行为扩展时钟显示以及时倒计时时间每分钟计数清零的+1显示。
图1.2 LCD1602显示
第二章 硬件电路设计
2.1 AT89C51芯片设计
2.1.1 AT89C51芯片概述
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS8位微处理器,俗称单片机。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
2.1.2主控芯片STC12C5A60S2
本设计基于开发板上的STC12C5A60S2主控芯片,51单片机一共有I/O引脚32个,控制信号或者数据[4]。因其引脚排序及基本功能同AT89S51芯片(如图3.1),故以AT89S51进行功能设计原型来进行开发设计。
DS12C887时钟模块负责存储时间信息和提供实时时钟功能,而51单片机负责控制和操作倒计时功能。具体来说,DS12C887时钟模块可以提供当前的小时、分钟和秒数,并且可以设置闹钟功能来触发倒计时。然后,51单片机可以读取DS12C887时钟模块的时间信息,并根据需要进行倒计时功能的实现,包括显示倒计时时间、每秒更新倒计时、处理倒计时结束等操作。因此,DS12C887时钟模块和51单片机可以协作来实现倒计时功能,DS12C887时钟模块提供时间信息,而51单片机控制倒计时功能的逻辑和显示则有定时器和中断系统控制。
图2.1 AT89C51芯片及其管脚
2.2 定时与中断
向CPU发出中断请求的来源称之为中断源。MCS-51是一个多中断源的单片机,80C51有三类共五个中断源,分别是外部中断两个,定时中断两个和串行中断一个。
2.2.1 外中断
外中断是由外部信号引起的,共有两个中断源,即外部中断“0”和外部中断“1”。它们的中断请求信号分别由引脚 INTO (P3.2)和 INT1 (P3.3)引入。
2.2.2 定时中断
定时中断是为满足定时或计数的需要而设置的。
2.2.3串行中断
串行中断是为串行数据传送的需要而设置的。
2.2.4 中断控制
中断控制是指提供给用户使用的中断控制手段,实际上就是一些专用寄存器。在MCS-51单片机中,用于此目的的控制寄存器共有四个,即定时器控制寄存器、中断允许控制寄存器、中断优先控制寄存器以及串行口控制寄存器。本课设设计就是通按键来控制中断,进而使倒计时满足开启和暂停功能。
2.2.5 定时器控制寄存器(TCON)
寄存器用于保存外部中断请求和以及定时器的计数溢出。寄存器地址88H,位地址8FH~88H。这个寄存器既有定时器/计数器的控制功能又有中断控制功能,其中与中断有关的控制位共有六位:IE0和IE1 、IT0和 IT1以及TF0和TF1 (如图3.2 定时器相关寄存器) ,TF0:定时器T0溢出中断请求。当定时器TO产生溢出时,TO中断请求标志TF0置1,请求中断处理。TF1:定时器T1溢出中断请求。当定时器Tl产生溢出时,T1中断请求标志TF1置1,请求中断处理[2]。定时/计数器T0和T1分别是由两个8位的专用寄存器组成,即定时/计数器T0由TH0和TL0组成,T1由TH1和TL1组成。此外,其内部还有2个8位的特殊功能寄存器TMOD和TCON,TMOD负责控制和确定T0和T1的功能和工作模式,TCON用来控制T0和T1启动或停止计数,同时包含定时/计数器的状态。TF1:定时器1溢出标志。定时/计数器溢出时由硬件置位。中断处理时由硬件清除,或用软件清除。TF0:定时器0溢出标志。定时/计数器溢出时由硬件置位。中断处理时由硬件清除,或用软件清除。本课设设计,当按键1按下后,TR0=1,中断关闭,倒计时开启;当按键2按下后,TR0=0,中断开启,倒计时暂停。
定时器流程:1.时钟→2.计数单元→3.中断系统
- 时钟:提供计数单元的时钟脉冲。
- 计数单元:时钟进行计数。
- 中断系统:产生中断,执行定时任务。
3.2 定时器相关寄存
第三章 主函数代码
这里给出了主函数的代码,其余没给出的皆为模块代码,模块代码参考了网上b站普中51教程的模块代码,大家可以直接去复制使用那些模块代码。
主函数代码
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
#include "Key.h"
#include "DS1302.h"
unsigned int Sec=60,Min=59,Hour=99,shu=000;
unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
void TimeShow(void)//时间显示功能
{
DS1302_ReadTime();//读取时间
LCD_ShowNum(2,1,DS1302_Time[0],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[1],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[2],2);//显示秒
}
void TimeSet(void)//时间设置功能
{
DS1302_Time[TimeSetSelect]++;//时间设置位数值加1
if(DS1302_Time[0]>23){DS1302_Time[0]=0;}//时越界判断
if(DS1302_Time[1]>59){DS1302_Time[1]=0;}//分越界判断
if(DS1302_Time[2]>59){DS1302_Time[2]=0;}//秒越界判断
}
void main()
{
LCD_Init();
Timer0Init();
LCD_ShowString(2,1," : : ");
LCD_ShowString(1,1,"~time:"); //上电显示静态字符串
LCD_ShowString(1,8," : :");
DS1302_Init();
DS1302_SetTime();//设置时间
while(1)
{
LCD_ShowNum(1,8,Hour,2); //显示时分秒
LCD_ShowNum(1,11,Min,2);
LCD_ShowNum(1,14,Sec,2);
LCD_ShowNum(2,14,shu,2);
KeyNum=Key();//读取键码
if(KeyNum==1)//按键1按下
{
TR0=1;
}
if(KeyNum==2)//按键2按下
{
TR0=0;
}
if(KeyNum==3)//按键3按下
{
Hour=99;
Min=60;
Sec=60;
shu=0;
}
switch(MODE)//根据不同的功能执行不同的函数
{
case 0:TimeShow();break;
case 1:TimeSet();break;
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000) //定时器分频,1s
{
T0Count=0;
Sec--; //1秒到,Sec自减
if(Sec>=60)
{
Sec=0; //60秒到,Sec清0,Min自减
Min--;
Sec=60;
shu++;
if(Min>=59)
{
Min=0; //60分钟到,Min清0,Hour自减
Hour--;
Min=60;
if(Hour>=99)
{
Hour=0; //99小时到,Hour清0
}
}
}
}
if(T0Count>=1000)//每500ms进入一次
{
TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反
}
}
第四章 仿真设计及程序
4.1 运行原理流程图
当开发板上电后,开发板将按图4.1的逻辑流程进行运行。
图4.1 倒计时工作运行流程图
4.2 原理图仿真
原理图设计通过使用Protues软件来进行设计,并且成功完成仿真测试(如图4.2 原理图仿真设计)。仿真测试结果显示了99:59:59的倒计时,以及经时钟DS1302调用的时钟。
图 4.2 原理图仿真设计
4.3 程序仿真测试
程序设计采用模块化设计,共使用了5给模块,并且这些模块大致还可以通用给其它程序开发同类功能设计。5个模块对应不同的功能,Delay模块程序为延时函数模块,便于主函数程序设计延时功能;LCD1602程序模块,这是LCD1602显示屏的调用和初始化,便于主函数的直接引用;KEY程序模块为3个独立按键的设计及调用。