📄 【006】多位数码管动态显示 [51] -- 一步一脚印 -- 编程爱好者blog.htm
字号:
<P>start: mov a,#08h
;0 ;段码<BR>
mov p0,a<BR>
mov
p2,#01h
;位码<BR> lcall delay_1ms </P>
<P> mov
a,#0abh ;1
<BR> mov
p0,a<BR> mov
p2,#02h<BR> lcall delay_1ms</P>
<P> mov
a,#12h
;2<BR> mov
p0,a<BR> mov
p2,#04h<BR> lcall delay_1ms</P>
<P> mov
a,#22h
;3<BR> mov
p0,a<BR> mov
p2,#08h<BR> lcall delay_1ms</P>
<P> mov
a,#0a1h
;4<BR> mov
p0,a<BR> mov
p2,#10h<BR> lcall delay_1ms</P>
<P> mov
a,#24h
;5<BR> mov
p0,a<BR> mov
p2,#20h<BR> lcall delay_1ms</P>
<P> mov
a,#04h
;6<BR> mov
p0,a<BR> mov
p2,#40h<BR> lcall delay_1ms</P>
<P><FONT color=#5ea25e>;
mov a,#0aah
;7<BR>; mov
p0,a</FONT><BR> mov
p0,#0aah
;感觉用这句和上面两句实现一样,可能这种习惯以后会有用吧<BR>
mov p2,#80h<BR>
lcall delay_1ms</P>
<P> ljmp start</P>
<P>delay_1ms: mov r6,#2<BR>temp:
mov
r5,#0ffh<BR>
djnz
r5,$<BR>
djnz
r6,temp<BR>
ret<BR>end</P>
<P></P>
<P>下载到板上得到测结果为从低到高八位分别显示0到7(含点)。<BR><BR><FONT
color=#0000ff>★</FONT>上述方法逐次给P0或者P2赋值,一方面程序的复杂程度增加,另外一方面会使得程序的灵活性降低。如果要改变显示的数字,程序改动起来很麻烦。 所以要用51单片机中常用的一种方法:<FONT
color=#0000ff>查表法</FONT>。例如P0口输出段码时,我们可以把要显示的段码放在一个表格中,然后每次从这个表格里面取数,送到P0口即可。P2口输出位码时,可以把要用的位码放在另一个表格里,每次从此表中取数,送入P2口。这样,如果要改变显示的数字,只需要改变表格里面的数。<BR><BR>
org 0000h</P>
<P>start: mov r7,#0ffh
;r7,r6查表时送入变址寄存器a
(因自加1后为0,所以预置ffh)<BR>
mov r6,#0ffh<BR>loop: lcall
play1
;调用显示段码子程序<BR> lcall
play2
;调用显示位码子程序<BR> lcall
delay_1ms<BR> cjne
a,#80h,loop
;判断是否到了最左边的数,即第8个位码<BR>
ajmp start</P>
<P>play1:
;查表求段码子程序
<BR>;<FONT color=#669971>
mov
a,r7
<BR>; inc
a<BR>; mov r7,a</FONT></P>
<P> inc
r7
;这2句和上面三条语句实现功能相同<BR>
mov a,r7
;a在这里做变址寄存器</P>
<P> <FONT
color=#0000ff>mov dptr,#table1</FONT>
;表首址送dptr,dptr做基址寄存器<BR> <FONT
color=#0000ff>movc a,@a+dptr</FONT>
;基址寄存器加变址寄存器寻址<BR>
mov p0,a<BR> ret</P>
<P>play2:
;查表求位码子程序(原理同play1)<BR>
mov
a,r6
<BR> inc
a<BR> mov
r6,a<BR> <FONT
color=#0000ff>mov
dptr,#table2</FONT><BR> <FONT
color=#0000ff>movc
a,@a+dptr<BR></FONT>
mov p2,a<BR> ret</P>
<P>table1: db 08h,0abh,12h,22h,0a1h,24h,04h,0aah
;段码表<BR>table2: db
01h,02h,04h,08h,10h,20h,40h,80h ;位码表</P>
<P>delay_1ms: mov
r5,#02h
;延时1ms子程序<BR>temp:
mov
r4,#0ffh<BR>
djnz
r4,$<BR>
djnz
r5,temp<BR>
ret<BR>end<BR><BR>下载到板上验证得到预想结果。<BR>
<HR>
C51实现如下(参考了<A href="http://blog.programfan.com/article.asp?id=11866"
target=_blank><FONT color=#0099ff>AS</FONT></A>的例程):
<P></P>
<P>#include <reg51.h><BR>#include
<intrins.h>
// 包含了左移函数_crol_()</P>
<P>void delayms(unsigned char ms); // 延时子程序</P>
<P>unsigned char data dis_digit; // 位选通值,
传送到P2口用于选通当前数码管的数值,<BR>
// 如等于0x01时,选通P2.0口数码管</P>
<P>unsigned char code
dis_code[11]={0x08,0xab,0x12,0x22,0xa1,
// 0,1,2,3,
4<BR>
0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9, off </P>
<P>unsigned char data dis_buf[8]; // dis_buf 显于缓冲区基地址</P>
<P>unsigned char data dis_index; // 显示索引,
用于标识当前显示的数码管和缓冲区的偏移量</P>
<P>void main()<BR>{<BR> P0 = 0xff; //
关闭所有数码管<BR> P2 = 0x00; </P>
<P> dis_buf[0] =
dis_code[0];<BR> dis_buf[1] =
dis_code[1];<BR> dis_buf[2] =
dis_code[2];<BR> dis_buf[3] =
dis_code[3];<BR> dis_buf[4] =
dis_code[4];<BR> dis_buf[5] =
dis_code[5];<BR> dis_buf[6] =
dis_code[6];<BR> dis_buf[7] =
dis_code[7];<BR> <BR> dis_digit
= 0x01; // 首先选通P2.0<BR> dis_index =
0; // 当前偏移量为0<BR>
<BR> while(1)<BR>
{<BR> P0 =
dis_buf[dis_index];
// 段码送P0口<BR> P2 =
dis_digit;
// 选能位(即位码)<BR>
delayms(1);
// 延时<BR> dis_digit
= _crol_(dis_digit, 1); // 位选通左移,
下次选通下一位<BR>
dis_index++;
// 下一个段码<BR>
<BR><FONT
color=#0000ff>
dis_index &=
0x07;
// 见注释</FONT><BR> }</P>
<P>}<BR>void delayms(unsigned char
ms)
//
延时子程序(晶振12M)<BR>{
<BR> unsigned char i;<BR>
while(ms--)<BR>
{<BR> for(i = 0; i <
120; i++);<BR> }<BR>}</P>
<P><BR><FONT color=#ff0000>★</FONT><FONT color=#0000ff>注释</FONT>:
此句作用是8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描。写回一般形式:dis_index = dis_index &
0x07 。这种方法挺新,第一次见到,十六进制的07就是二进制的00000111,这样通过与操作可以控制循环了。比如dis_index
经第一次循环后值为00000001,和0x07与操作后值不变仍为0x01,第二次循环时,其值为0为0x02,与0x07后仍为0x02,一直到其值增为0x07时还是不变的,但再次循环后其值为0x80,再与0x07后就变成0x00了,这样又从初始循环了。此句可用
if (dis_index == 8) dis_index = 0 代替,效果一样。</P>
<P><FONT
color=#0000ff>★</FONT>通过C51用上述方法实现时,其段码放在了数组dis_code[11]中,再通过缓冲区数组dis_buf[]将程序中要调用的值装入,这样就可以用下标(偏移量)访问了。这样看上去有些繁锁,但其思路比较清楚,结构上也很明了,具有通用性,便于扩展。<BR><BR><FONT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -