系统软件设计
图6 定时中断程序
4.2.3调时程序
给三个按键,当P2.0口的按键K0按下,则进入调时状态,按K1,K2加1减1操作,再按K0,调分,再按K0,调秒,再按K0,则退出调时功能,进行正常计数运行。
4.2.5 LED显示模组显示数字
由于系统要显示的内容较简单,显示量不多,所以选用数码管既方便又经济。LED有共阴极和共阳极两种。如图7所示。
二极管的阴极连接在一起,通常此公共阴极接地,而共阳极则将发光二极管的阳极连接在一起,接入+5V的电压。一位显示器由8个发光二极管组成,其中7个发光二极管构成字型“8”的各个笔划(段)a~g,另一个小数点为dp发光二极管。当在某段发光二极管施加一定的正向电压时,该段笔划即亮;不加电压则暗。为了保护各段LED不被损坏,需外加限流电阻。
7
模块特性简介
图7 LED数码管结构原理图
众所周知,LED显示数码管通常由硬件7段译码集成电路,完成从数字到显示码的译码驱动。本系统采用软件译码,以减小体积,降低成本和功耗,软件译码的另一优势还在于比硬件译码有更大的灵活性。所谓软件译码,即由单片机软件完成从数字到显示码的转换。从LED数码管结构原理可知,为了显示字符,要为LED显示数码管提供显示段码,组成一个“8”字形字符的7段,再加上1个小数点位,共计8段,因此提供给LED数码管的显示段码为1个字节。各段码位与显示段的对应关系如表1。
表1 各段码位的对应关系
段码位 显示段 D7 dp D6 g D5 f D4 e D3 d D2 c D1 b D0 a 需说明的是当用数据口连接LED数码管a~dp引脚时,不同的连接方法,各段码位与显示段有不同的对应关系。通常数据口的D0位与a段连接,D1位与b段连接,??D7位与dp段连接,如表1所示,表2为用于LED数码管显示的十六进制数和空白字符与P的显示段码。
表2 LED显示段码
字型 0 1 2 3 4 5 6 7 8 共阳极段码 共阴极段码 C0H F9H A4H BOH 99H 92H 82H F8H 80H 3FH 06H 5BH 4FH 66H 6DH 7DH 07H 7FH 字型 9 A B C D E F 空白 P 共阳极段码 共阴极段码 90H 88H 83H C6H A1H 86H 84H FFH 8CH 6FH 77H 7CH 39H 5EH 79H 71H 00H 73H 注:(1)本表所列各字符的显示段码均为小数点不亮的情况。
系统软件设计
(2)“空白”字符即没有任何显示。
根据AT89C2051单片机灌电流能力强,拉电流能力弱的特点,我们选用共阳数码管。将AT89C2051的P1.0~P1.7分别与共阳数码管的a~g及dp相连,高电平的位对应的LED数码管的段暗,低电平的位对应的LED数码管的段亮,这样,当P0口输出不同的段码,就可以控制数码管显示不同的字符。例如:当P0口输出的段码为1100 0000,数码管显示的字符为0。
数码管显示器有二种工作方式,即静态显示方式和动态扫描显示方式。 为节省端口及降低功耗,本系统采用动态扫描显示方式。动态扫描显示方式需解决多位LED数码管的“段控”和“位控”问题,本电路的“段控”(即要显示的段码的控制)通过P0口实现;而每一位的公共端,即LED数码管的“位控”,则由P3口控制。这种连接方式由于多位字段线连在一起,因此,要想显示不同的内容,必然要采取轮流显示的方式,即在某一瞬间,只让其中的某一位的字位线处于选通状态,其它各位的字位线处于断开状态,同时字段线上输出这一位相应要显示字符的字段码。在这一瞬时,只有这一位在显示,其他几位则暗。在本系统中,字位线的选通与否是通过PNP三极管的导通与截止来控制,即三极管处于“开关”状态。
系统的时分显示部件由4只7段共阳LED数码管构成,前两只用于时的显示,后两只用于分的显示。值得一提的是,在设计中需要实现时与分之间的两个闪烁点,为此,将第三只LED数码管倒置摆放,这样就形成了两个很自然的闪烁点。与此同时,为了能使两点显示能够形象的表示时钟“秒”的变化,设计时,将两个点由P1.7单独控制,每隔一秒使P1.7发送一个正脉冲,从而实现了两个点的闪烁显示,闪烁周期为一秒。
9
模块特性简介
第五章 程序设计
5.1部分程序预览
以下为部分源程序:
#include \#include \#include \#include \
#define uchar unsigned char
#define uint unsigned int idata sbit ADD=P1^1; sbit SUB=P1^0; sbit ACC0 = ACC^0; sbit ACC7 = ACC^7;
void showDay(void);//显示时间 void showData(void);//显示日期 void showDishi(void);//显示定时 void int_0(void);//中断0 void int_1(void);//中断1
void flash_max7219(unsigned char n);//闪一个位max7219
/*********************************************************************/
/* 实时时钟模块 时钟芯片型号:DS1302 */ /*/
/*********************************************************************/
sbit T_CLK = P2^3; /*实时时钟时钟线引脚 */ sbit T_IO = P2^4; /*实时时钟数据线引脚 */ sbit T_RST = P2^5; /*实时时钟复位线引脚 */
/********************************************************************/
void v_RTInputByte(uchar ucDa); //往DS1302写入1Byte数据 uchar uc_RTOutputByte(void);// 从DS1302读取1Byte数据 void v_W1302(uchar ucAddr, uchar ucDa);//往DS1302写入数据 uchar uc_R1302(uchar ucAddr);//读取DS1302某地址的数据
//void v_BurstW1302T(uchar *pSecDa);//往DS1302写入时钟数据(多字节方式)
//void v_BurstR1302T(uchar *pSecDa);//读取DS1302时钟数据
//void v_BurstW1302R(uchar *pReDa);//往DS1302寄存器数写入数据(多字节方式)
//void v_BurstR1302R(uchar *pReDa);//读取DS1302寄存器数据
void v_Set1302(uchar *pSecDa) ;//设置初始时间,,输入: pSecDa: 初始时间地址。初始时间格式为: 秒 分 时 日 月 星期 年
void v_Get1302(uchar ucCurtime[]) ;//读取DS1302当前时间
uchar showTime[8]={0,0,10,0,0,10,0,0};//显示的时间**********************************************全局变量 uchar setTime[2]={0,0};//定时的设定
uchar time[7]={0,0x59,0x19,0x24,0x7,0x01,0x08};//秒 分 时 日 月 星期 年
uchar Tmod=7;//此时的调节模式 void main() {
delay_ms(200); //sound();
initMAX7219();//初始化max7219 cls();//清屏max7219 //v_Get1302(& time); //v_Set1302(& time);
EX0=1; EX1=1;
IT1=1;//下降沿触发 IT0=1;
EA=1;//开中断
v_Get1302(& time); showDay(); //int_1(); //int_0(); while(1) {
v_Get1302(& time); showDay();
if ((setTime[0]==time[2])&&(setTime[1]==time[1]))sound(); } }
//************************************************显示时间 void showDay(void) {
//将数据转化为显示格式
showTime[7]=time[0] & 0x0f;//个位
11