Toggle navigation
科创
{{ getSearchSuggestionLabel(suggestion) }}
{{ part.text }}
查看更多
登录
 
注册
电波
论坛
专栏
应用
登录
注册
{{ getSearchSuggestionLabel(suggestion) }}
{{ part.text }}
查看更多
论坛
>
电子信息
>
电子技术
文号
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,这样哪一位也不会亮,“影子”问题也就解决了。
问题真的解决了吗?我们将这个程序下载至单片机:嗯,比不加消影好多了,可是还感觉不太稳定,能不能把延时调短呢?将延时调短,下载至单片机,效果如图所示。
重影出现了,它从哪里来呢?原因如下:段选打开之后,上次的位选还没有清除,虽然单片机反应很快,但延时的减少使其在高速下变得非常明显。
针对以上问题,本人编写了一个程序,既能保证数码管显示流畅,又解决了所有重影问题:
#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]
总之,大家在学习时不要迷信权威,要勤动脑,这样才能把别人的知识变成自己的。
+100
科创币
ehco
2011/12/25
动态scan中,必须有消隐,尤其在LED点阵应用上。
+100
科创币
1989sean
2011/12/25
+100
科创币
delete
2011/12/25
支持下,做过LED阵列屏的深有体会......
+1
学术分
虎哥
2011/12/25
大神辛苦了。
来自:
电子信息
/
电子技术
10
0
全部
只看作者
科学人
作者
15年0个月前
IP:未同步
347755
3楼
回 2楼(jrcsh) 的帖子
谢谢!我的方法还是以牺牲亮度和资源为代价的。
加载全文
引用
评论
0
全部
只看作者
在列表中查看
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
编辑
删除
{{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
保存
取消
我也是有底线的
保存中...
保存