多位数码管的动态显示(上)

单片机课程代码详解

提示:撰文本文的目的是为了学习交流,仅供参考,不保证其正确性。

  废话少说,上代码!

#include <STC15.H>

#define u8 unsigned char //将unsigned char重定义为u8,下面一行同理
#define u16 unsigned int

#define PLed P2 //将单片机的P2口用PLed表示,下面两行同理
#define PSeg P4
#define PSel P6

u8 code SegCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92
,0x82,0xf8,0x90,0xbf,0xff,0x8c};
//定义一个名为SegCode的数组,用来存放多位数码管的字形码

u8 DisBuff[4]={10,10,10,10}; //该数组用来存放Sec处理后的数据

void DelayNms(unsigned int i); //声明子函数,下面两行同理
void Display();
void ToDisBuff();

u8 Sec;

void main ()
{
u8 s;
while (1)
{
for(Sec=0;Sec<100;Sec++)
{
ToDisBuff();
for(s=0;s<100;s++) //这里的for循环目的是为了延时
Display();
}
}
}
void DelayNms(unsigned int i) //延时函数,用于延时
{
unsigned int j;
while(i--)
for(j=0;j<100;j++);
}

void Display() //动态显示函数
{
u8 i;
for (i=1;i<4;i++)
{
PSel=0x00; //位选段置零,即没有选择哪一位点亮
PSeg=SegCode[ DisBuff[i] ];
PSel=0x01<<i;
DelayNms(1);
}
}
void ToDisBuff() //数据处理函数
{
DisBuff[2]=Sec/10;
DisBuff[3]=Sec%10;
}

  我们按照主函数的运行顺序一一介绍各个子函数的作用。

主函数

for(Sec=0;Sec<100;Sec++)
{
ToDisBuff();
for(s=0;s<100;s++)
Display();
}

  这里的for循环语句,我们可以看到这里Sec被设置初值为0,一共要循环100次(即0-99),这与我们要实现的0-99动态显示这一功能有关。

数据处理函数

void ToDisBuff()
{
DisBuff[2]=Sec/10;
DisBuff[3]=Sec%10;
}

  这里的ToDisBuff函数,目的是将for循环当中的Sec进行处理。当for循环开始时,Sec的值为0.经过算式Sec/10(这里是除法运算,计算结果为商,例如25/7的结果为3),得出结果为0,并将0这个结果存入DisBuff[2]。此时在数组DisBuff当中,下表为2的数已经不是10了,而是0。下一句同理,将计算后的值存入DisBuff[3]当中。这里可以自己简单的写一段C代码来证明一下:

动态显示函数

void Display()   //动态显示函数
{
u8 i;
for (i=1;i<4;i++)
{
PSel=0x00; //位选段置零,即没有选择哪一位点亮
PSeg=SegCode[ DisBuff[i] ];
PSel=0x01<<i;
DelayNms(1);
}
}

  这里的for循环总共循环四次,原因应该是因为本数码管为四位数码管。for循环第一次开始循环时,PSeg开始调用数组SegCode当中的字形码,DisBuff[i]是为了控制字形码数组的角标,当i=1时,得出DisBuff[1],DisBuff[1]的值为10,即PSeg=SegCode[10](0xff),接着PSel位选段向左位移1位(因为i=1),之后用延时函数进行延时。

提示:事实上也可以直接将DelayNms(1);这句改为DelayNms(100);,然后再将主函数里的for(s=0;s<100;s++)注释掉也能达到同样效果。

  因为在这里使用的是共阳数码管,点亮是低电平有效。所以当PSeg=0xff时,数码管不点亮。

  当循环到第二次时,此时i=2。PSeg=SegCode[DisBuff[2]]=SegCode[0](0xc0)。接着位选段向左移动2位,在数码管的第三位显示数字0,随着循环的进行依此类推,最终形成了0-99的动态显示。