(五) 相信大家一定见过数字时钟,教学楼大厅一定有吧。每次路过,基本上只是随便瞟上一眼,根本没去想过他的工作原理什么。但是今天 你也可以把他做出来了,是不是觉得自己很有成就感呢!呵呵! ^_^ 接上面所讲的,我们先来做个简单的实验:在一个数码管上轮流显示0--9这10个数字。还楞着干什么,快动手写程序呀!好象有点难哦,要不先不要往下看了,嘿嘿,关机吧,自己先去想想,怎么样?
#include<reg51.h>
unsigned char code SEG_TAB[ ] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9数字
void Delay(unsigned int a) //unsigned int定义为无符整形,取值范围为0--32768
{
unsigned char i;
while( --a != 0)
{
for(i = 0; i < 125; i++);
}
}
void main(void)
{
unsigned char i;
while(1)
{
for(i = 0; i < 10; i++)
{
P0 = SEG_TAB[ i ]; //取SEG_TAB数组中的值
P2 = 0X01;
Delay(1000);
}
}
}
是不是显示从0--9,跳动显示,你的心是不是也跟着一起跳呀,离我们的目标又迈进了一步!不错,继续努力!上面只显示了一个数码管的数字0--9,但是怎么样要让他显示6个数字呢?这样我们就可以做个时钟出来玩玩了!还记不记得我们前面 讲过的P2口的位选作用!嘿嘿,没忘记就好!
#include<reg51.h>
unsigned char hour = 12, min = 0, sec = 0;
unsigned char code SEG_TAB[ ] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9数字
void Delay(unsigned char a)
{
unsigned char i;
while( --a != 0)
{
for(i = 0; i < 125; i++);
}
}
void disp(void)
{
P0 = SEG_TAB[ sec % 10 ];//显示秒的个位
P2 = 0X01;
Delay(15);
P2 = 0;
P0 = SEG_TAB[ sec / 10 ];//显示秒的十位
P2 = 0X02;
Delay(15);
P2 = 0;
P0 = SEG_TAB[ min % 10 ];//显示分的个位
P2 = 0X04;
Delay(15);
P2 = 0;
P0 = SEG_TAB[ min / 10 ];//显示分的十位
P2 = 0X08;
Delay(15);
P2 = 0;
P0 = SEG_TAB[ hour % 10 ];//显示时的个位
P2 = 0X10;
Delay(15);
P2 = 0;
P0 = SEG_TAB[ hour / 10 ];//显示时的十位
P2 = 0X20;
Delay(15);
P2 = 0;
}
void main(void)
{
while( 1 )
{
disp( );
}
}
编译烧录芯片后,观察运行现象。矣...怎么一直显示12:00:00,难道是时钟没有启动?还是,另外的原因呢? 哦,原来是3个变量sec,min,hour初始化后,其值一直没有改变!那我们怎么样才能让他改变数值呢?有的朋友一定会这么认为:让秒个位延时1秒,后加1,而秒十位延时10秒后,再加1,一直加到6,分个位加1,依次类推...这样的想法是不错,但是朋友你有没有想过C语言的一般延时(除非你把他放到中断里)极不精确!这样累计下来,一天24小时的误差,肯定很大很大,我曾经也用延时的方法写过时钟,1个小时误差8秒,那是个什么概念!一天24小时就要24*8=192,约为3分钟,一个月就是10分钟...有没有其他的方法可以改进些呢?有!这里就要涉及到单片机中另一个比较重要的核心部分:单片机的中断和定时器的运用!想写出比较精确(这里说的只的相对前面的做法而言比较精确而已,如果要做更加精确的时钟,用时钟芯片比较好点,常用的有DS12887和DS1302等)的时钟程序,就一定要调用中断和定时器。还是大家先看看教材和书吧,毕竟人家出的书,肯定比我要写的系统多了,下面我们再来简单的讲讲!
联系客服