文号
t38977
阅读
5549
回复
10
收藏
8
传统数码管动态驱动程序的改进
2011/12/25
IP:北京
    /*本贴纯属原创,如有雷同不胜荣幸*/
    这是用C51编写的数码管动态显示驱动程序:


#include"reg51.h"

#define uchar unsigned char    
#define uint unsigned int

sbit duan=P2^0;    
sbit wei=P2^1;    

void delay(uint);

uchar code numbers[]=
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};

void main()
{
    while(1)
    {
        duan=1;    
        P1=numbers[1];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xfe;
        wei=0;
        delay(10);
        duan=1;    
        P1=numbers[2];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xfd;
        wei=0;
        delay(10);

        duan=1;    
        P1=numbers[3];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xfb;
        wei=0;
        delay(10);

        duan=1;    
        P1=numbers[4];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xf7;
        wei=0;
        delay(10);

        duan=1;    
        P1=numbers[5];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xef;
        wei=0;
        delay(10);

        duan=1;    
        P1=numbers[6];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xdf;
        wei=0;
        delay(10);

        duan=1;    
        P1=numbers[7];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0xbf;
        wei=0;
        delay(10);

        duan=1;    
        P1=numbers[8];
        duan=0;
        P1=0xff;
        wei=1;
        P1=0x7f;
        wei=0;
        delay(10);
    }
}

void delay(uint a)
{
    uchar b;
    uint c;
    for(c=a;c>0;c--)
        for(b=200;b>0;b--);
}
    
   乍一看好像没什么问题,这不就是书上的例程吗?不错,这就是在书上、网上能够找到的最普遍的使用锁存器驱动数码管的C程序,大家已经很习惯了。
    如果我告诉你还有比它更好的程序,你会不会很惊讶?不用惊讶,下面请看我的分析。
    为了使显示清晰,设计者加入了“消影”。想必大家已经知道“消影”的概念了:在送完段选数据之后,I/O 口仍然保持该状态。若直接打开位选,原来的段选数据就会被送入位选,虽然持续时间短暂,但在高速显示的状态下仍会相互重叠,产生“影子”。加上消影后,使I/O 口在位选打开之前变成FF,这样哪一位也不会亮,“影子”问题也就解决了。
    问题真的解决了吗?我们将这个程序下载至单片机:嗯,比不加消影好多了,可是还感觉不太稳定,能不能把延时调短呢?将延时调短,下载至单片机,效果如图所示。
IMG_0062.jpg
   重影出现了,它从哪里来呢?原因如下:段选打开之后,上次的位选还没有清除,虽然单片机反应很快,但延时的减少使其在高速下变得非常明显。
    针对以上问题,本人编写了一个程序,既能保证数码管显示流畅,又解决了所有重影问题:

#include"reg51.h"    //头文件

#define uchar unsigned char    //宏定义
#define uint unsigned int

sbit duan=P2^0;    //段选端
sbit wei=P2^1;    //位选端

void delay(uint);    //延时函数声明

uchar code numbers[]=    //数码数组
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};

void main()
{
    while(1)
    {
        P1=numbers[1];
        duan=1;        //数据入锁存
        duan=0;
        P1=0xfe;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;    //11111111
        wei=1;
        wei=0;
        P1=numbers[2];
        duan=1;
        duan=0;
        P1=0xfd;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;
        wei=1;
        wei=0;
        P1=numbers[3];
        duan=1;
        duan=0;
        P1=0xfb;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;
        wei=1;
        wei=0;
        P1=numbers[4];
        duan=1;
        duan=0;
        P1=0xf7;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;
        wei=1;
        wei=0;
        P1=numbers[5];
        duan=1;
        duan=0;
        P1=0xef;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;
        wei=1;
        wei=0;
        P1=numbers[6];
        duan=1;
        duan=0;
        P1=0xdf;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;
        wei=1;
        wei=0;
        P1=numbers[7];
        duan=1;
        duan=0;
        P1=0xbf;
        wei=1;
        wei=0;
        delay(10);

        P1=0xff;
        wei=1;
        wei=0;
        P1=numbers[8];
        duan=1;
        duan=0;
        P1=0x7f;
        wei=1;
        wei=0;
        delay(10);
    }
}

void delay(uint a)
{
    uchar b;
    uint c;
    for(c=a;c>0;c--)
        for(b=10;b>0;b--);    //数值越小,亮度越低。
}
  
[size=4][color=#FF9900]原理就不说了,大家都看得懂吧。有一点需要注意:延时并非越短越好,因为单片机每次关闭输出需要一定时间,延时太短会降低占空比,导致亮度减弱。
对比如图:
[/size] IMG_0061.jpg
   总之,大家在学习时不要迷信权威,要勤动脑,这样才能把别人的知识变成自己的。
+100
科创币
ehco
2011/12/25
动态scan中,必须有消隐,尤其在LED点阵应用上。
+100
科创币
1989sean
2011/12/25
+100
科创币
delete
2011/12/25
支持下,做过LED阵列屏的深有体会......
+1
学术分
虎哥
2011/12/25
大神辛苦了。
10
科学人作者
15年0个月前IP:未同步
347755
3楼
回 2楼(jrcsh) 的帖子
谢谢!我的方法还是以牺牲亮度和资源为代价的。
引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的