赞
踩
我是在源程序的基础上进行的改动,改动的地方我会进行说明,下面的顺序也是我学习的顺序
数码管的段选是使用了3-8线译码器,省下了单片机的5个端口。
在程序中要先定义引脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
void DigDisplay() { u8 i=0; //无符号整形i有2^8=16*16=256个状态,所以表示范围是0-255。 for(i=0;i<8;i++) { switch(i) //位选,选择点亮的数码管。我把i改成递减的,更符合看的习惯--最右边是秒。 { case(7): LSA=0;LSB=0;LSC=0; break;//显示第0位(右边低位权重) case(6): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(5): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(4): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(3): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(2): LSA=1;LSB=0;LSC=1; break;//显示第5位 case(1): LSA=0;LSB=1;LSC=1; break;//显示第6位 case(0): LSA=1;LSB=1;LSC=1; break;//显示第7位(左边最高位) } P0=TempData[i];//发送段码 delay(100); //间隔一段时间扫描 P0=0x00;//消隐 //delay(1000); } }
unsigned char TempData[8]; //存储时间显示值的全局变量
TempData[8]分别映射到下面8个变量上
TempData[0]=dofly_DuanMa[hour/10]; //时 //数据的转换,因我们采用数码管0~9的显示,将数据分开
TempData[1]=dofly_DuanMa[hour%10];
TempData[2]=0x40; //加入"-"
TempData[3]=dofly_DuanMa[minute/10];//分
TempData[4]=dofly_DuanMa[minute%10];
TempData[5]=0x40;
TempData[6]=dofly_DuanMa[second/10];//秒
TempData[7]=dofly_DuanMa[second%10];
DigDisplay();
这段程序写的很妙,妙就妙在对时间数值做出的处理上。
unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9,也就是选中的数码管显示的内容
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选,一次点亮一个数码管
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
下面是定时器的中断程序,定时器归根结底还是计数器。
计数器:就是对外部脉冲或系统时钟12分频的内部脉冲 进行计数。
波特率:码元传输速率RB,每秒发送码元的个数,码元由0和1构成的,01的个数取决于码元为几进制编码。
比特率:信息传输速率Rb,每秒发送0和1的个数。
/*------------------------------------------------ 定时器中断子程序 ------------------------------------------------*/ void Timer0_isr(void) interrupt 1 //定时器T0的中断号对应为1(查表,主要用于指明中断源的) { static unsigned int num,i; TH0=(65536-2000)/256;//重新赋值 2ms(16位定时器就是2^16=65536微秒,减去2000微秒剩下的就是定时器的初值,分别对低八位高八位=2^8次方取模取余) TL0=(65536-2000)%256; // DigDisplay();// 调用数码管扫描 //-------------------------------------- // 只用当计时器计2000个1us,即每2ms,才+1 i++; if(i==10) //20ms更新一次 { i=0; UpdateTimeFlag=1; //更新时间志位置1 } //-------------------------------------- // 只用当计时器计2000个1us,即每2ms,才+1 num++; if(num==500) //大致1s { num=0; second++; if(second==60) //秒到60,分钟加1 { second=0; minute++; if(minute==60) //分钟到60,小时加1 { minute=0; hour++; if(hour==24) //小时到24,回零 hour=0; } } } }
但是使用定时中断的时候要对定时器进行初始化
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用定时器模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00; //给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------ 按键扫描函数,返回扫描键值 ----------------------------------------------*/ unsigned char KeyScan(void) { unsigned char keyvalue; if(KeyPort!=0xff) { DelayMs(10); if(KeyPort!=0xff) { keyvalue=KeyPort; while(KeyPort!=0xff);//延时消抖了之后在检测如果还有执行下面语句,(正常人的反应按一个按键要持续几百ms) switch(keyvalue) { case 0xfe:return 1;break; case 0xfd:return 2;break; case 0xfb:return 3;break; case 0xf7:return 4;break; case 0xef:return 5;break; case 0xdf:return 6;break; case 0xbf:return 7;break; case 0x7f:return 8;break; default:return 0;break; } } } return 0; }
下面对应不同的取值有不同的函数
Key_Num=KeyScan();
switch(Key_Num)
{
case 1:hour++;if(hour==24)hour=0; //正常时间 小时 加1
break;
case 2:hour--;if(hour==255)hour=23; //正常时间 小时减1
break;
case 3:minute++;if(minute==60)minute=0; //分钟加1
break;
case 4:minute--;if(minute==255)minute=59; //分钟减1
break;
default:break;
}
每次运行 DigDisplay()函数,都会让*P0=TempData[i]*中的i值从0到7变化,不同的i对对应不同的时间信息,此外了位方便映射到相应的数码管上了,i也会让相应的信息单独显示,这是通过switch(i)实现的(如从右往左数,第i=0个数码管显示,秒的低位,让i=1显示秒的高位,让i=2显示横线·····)。这样利用了视觉暂留的效果做到了,让一排数码管显示不同的数。
如何让数码管走动,只需要隔一秒改变一下时间变量TempData的取值。用到定时器,装上初值后让定时器,恰好经过1s后溢出,运行中断服务函中的内容,改变时间变量,也就是让对应的时间+1。
看懂了源程序的基础上改我们要添加相应的功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。