下面是我的计数器实验遇到的问题以及解答。代码如下所示:

#include<reg52.h>  
typedef unsigned char uint8;
typedef unsigned long int  uint32;
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ENLED2=P1^3;
sbit ENLED1=P1^4;
uint32 sec=0;//这个用于记录秒数,因为有6个数码管,所以16为已经不够了 ,用32位
uint8 number[]={0x0c0,0x0F9,0x0A4,0x0B0,
0x99,0x92,0x82,0xF8,
0x80,0x90};
void display(); 
void main()
{
uint8 k,i=0;//用于保存数组下表
uint8 j=0;
ENLED1=0;
ENLED2=1;//使能
//设置定时器,假设使用T0
//首先设置TMOD,使之工作在需求状态,也就是把TMOD=0x01 
TMOD=0x01;
//然后根据计算,算出TH0,TL0
  TH0=0x0DB;
TL0=0x0FF;//一毫秒
TR0=1; //设置TR0,当TR0=1,开始计时  
while(1)
{ 
 display();
 if(1==TF0)
{   
   j++; //当j=100,刚刚好为1秒    
 //为下次做准备
 TF0=0;//因为如果溢出不执行中断需要软件清零
 TH0=0x0DB;
     TL0=0x0FF;
}
 if(j==100) 
 {
   sec++;
   j=0;
 }
/* sec=123456;
 for(k=0;k<100;k++)
 for(i=0;i<255;i++);*/    
} 
}
void display()
{
 
static uint8 h = 0;
switch (h)
{
case0:ADDR0=0;ADDR1=0;ADDR2=0;h++;P0=number[sec%10];break;
case1:ADDR0=1;ADDR1=0;ADDR2=0;h++;P0=number[(sec/10)%10];break;
case2:ADDR0=0;ADDR1=1;ADDR2=0;h++;P0=number[(sec/100)%10];break;
case3:ADDR0=1;ADDR1=1;ADDR2=0;h++;P0=number[(sec/1000)%10];break;
case4:ADDR0=0;ADDR1=0;ADDR2=1;h++;P0=number[(sec/10000)%10];break;
case5:ADDR0=1;ADDR1=0;ADDR2=1;h=0;P0=number[(sec/100000)%10];break;
default: break;
}
}

Sec=123456以及红色程序是我的测试数据。

如果加上sec=123456和红色那段程序,那么就会显示123456,

但是如果加上sec=123456不加红色部分了以后就会显示234561。

如果都不加它就会从第二个数码管开始累加。

抛开程序,我还发现了一个奇怪的现象,

如果只是用一个的数码管显示,那么可以正常显示(0->9->0),

但是如果是第一个和第二个数码管,那么第二个变成个位,第一个变为十位,但是如果是三个的话,那么第二位还是个位,第三个是十位,第一个就是百位。我不知道这个是什么原因,自己已经搞了一个下午和晚上都不知道错误在哪里!

解答:为了简化问题,用下面两行程序来讨论。

case0:ADDR0=0;ADDR1=0;ADDR2=0;h++;P0=number[sec%10];break;

case1:ADDR0=1;ADDR1=0;ADDR2=0;h++;P0=number[(sec/10)%10];break;

第一次调用display()时,选中DS1,P0输出个位数6的段码,

紧接着第二次调用display,

执行case1:ADDR0=1;ADDR1=0;ADDR2=0;

(暂停一下,此时138已选中数码管DS2,P0上还保持者上次的内容:个位数6的段码,它会被送显到DS2上),

接下来执行h++;tmp=(sec/10)%10;(/和%运算都要花些时间,这段时间DS2上一直显示着个位数6的段码,在你没加红色延时的情况下,时间要比显示十位数5的时间长),

最后执行P0= number[tmp],这个时候DS2上才显示出十位数5(前面说过,这个时间较短,十位数5显示在DS3上的时间较长)

总结一下:在没加延时的情况下,个位数6在DS1上显示的时间短于在DS2的时间,在DS2上看到的是6和5的混合显示,更多的看到6,同理DS3上更多的看到的是5,DS1上更多的看到的是1,……

加上延时就不同了,DS2上显示5的时间要远远多于显示6的时间,以至于只能看到5,显示就正常了!