问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

什么是数码管动态显示

发布网友 发布时间:2022-04-20 15:01

我来回答

1个回答

热心网友 时间:2023-07-05 15:49

  该实验用到实验板的资源电路图如下:

  其中P0口是段码,低电平有效。P2口是位码,高电平有效。P2.0口控制第1个数码管,一直到P2.7口控制第8个。该板的段码表如下:

  各个数码管的段码都是p0口的输出,即各个数码管输入的段码都是一样的, 为了使其分别显示不同的数字, 可采用动态显示的方式,即先只让最低位显示0(含点),经过一段延时,再只让次低位显示1,如此类推。由视觉暂留,只要我们的延时时间足够短,就能够使得数码的显示看起来非常的稳定清楚。过程如下图。

  采用上述方法思路编写如下:

  org 0000h

  start: mov a,#08h ;0 ;段码
  mov p0,a
  mov p2,#01h ;位码
  lcall delay_1ms

  mov a,#0abh ;1
  mov p0,a
  mov p2,#02h
  lcall delay_1ms

  mov a,#12h ;2
  mov p0,a
  mov p2,#04h
  lcall delay_1ms

  mov a,#22h ;3
  mov p0,a
  mov p2,#08h
  lcall delay_1ms

  mov a,#0a1h ;4
  mov p0,a
  mov p2,#10h
  lcall delay_1ms

  mov a,#24h ;5
  mov p0,a
  mov p2,#20h
  lcall delay_1ms

  mov a,#04h ;6
  mov p0,a
  mov p2,#40h
  lcall delay_1ms

  ; mov a,#0aah ;7
  ; mov p0,a
  mov p0,#0aah ;感觉用这句和上面两句实现一样,可能这种习惯以后会有用吧
  mov p2,#80h
  lcall delay_1ms

  ljmp start

  delay_1ms: mov r6,#2
  temp: mov r5,#0ffh
  djnz r5,$
  djnz r6,temp
  ret
  end

  下载到板上得到测结果为从低到高八位分别显示0到7(含点)。

  ★ 上述方法逐次给P0或者P2赋值,一方面程序的复杂程度增加,另外一方面会使得程序的灵活性降低。如果要改变显示的数字,程序改动起来很麻烦。 所以要用51单片机中常用的一种方法:查表法。例如P0口输出段码时,我们可以把要显示的段码放在一个表格中,然后每次从这个表格里面取数,送到P0口即可。P2口输出位码时,可以把要用的位码放在另一个表格里,每次从此表中取数,送入P2口。这样,如果要改变显示的数字,只需要改变表格里面的数。

  org 0000h

  start: mov r7,#0ffh ;r7,r6查表时送入变址寄存器a (因自加1后为0,所以预置ffh)
  mov r6,#0ffh
  loop: lcall play1 ;调用显示段码子程序
  lcall play2 ;调用显示位码子程序
  lcall delay_1ms
  cjne a,#80h,loop ;判断是否到了最左边的数,即第8个位码
  ajmp start

  play1: ;查表求段码子程序
  ; mov a,r7
  ; inc a
  ; mov r7,a

  inc r7 ;这2句和上面三条语句实现功能相同
  mov a,r7 ;a在这里做变址寄存器

  mov dptr,#table1 ;表首址送dptr,dptr做基址寄存器
  movc a,@a+dptr ;基址寄存器加变址寄存器寻址
  mov p0,a
  ret

  play2: ;查表求位码子程序(原理同play1)
  mov a,r6
  inc a
  mov r6,a
  mov dptr,#table2
  movc a,@a+dptr
  mov p2,a
  ret

  table1: db 08h,0abh,12h,22h,0a1h,24h,04h,0aah ;段码表
  table2: db 01h,02h,04h,08h,10h,20h,40h,80h ;位码表

  delay_1ms: mov r5,#02h ;延时1ms子程序
  temp: mov r4,#0ffh
  djnz r4,$
  djnz r5,temp
  ret
  end

  下载到板上验证得到预想结果。

  --------------------------------------------------------------------------------
  C51实现如下(参考了AS的例程):

  #include <reg51.h>
  #include <intrins.h> // 包含了左移函数_crol_()

  void delayms(unsigned char ms); // 延时子程序

  unsigned char data dis_digit; // 位选通值, 传送到P2口用于选通当前数码管的数值,
  // 如等于0x01时,选通P2.0口数码管

  unsigned char code dis_code[11]={0x08,0xab,0x12,0x22,0xa1, // 0,1,2,3, 4
  0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9, off

  unsigned char data dis_buf[8]; // dis_buf 显于缓冲区基地址

  unsigned char data dis_index; // 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量

  void main()
  {
  P0 = 0xff; // 关闭所有数码管
  P2 = 0x00;

  dis_buf[0] = dis_code[0];
  dis_buf[1] = dis_code[1];
  dis_buf[2] = dis_code[2];
  dis_buf[3] = dis_code[3];
  dis_buf[4] = dis_code[4];
  dis_buf[5] = dis_code[5];
  dis_buf[6] = dis_code[6];
  dis_buf[7] = dis_code[7];

  dis_digit = 0x01; // 首先选通P2.0
  dis_index = 0; // 当前偏移量为0

  while(1)
  {
  P0 = dis_buf[dis_index]; // 段码送P0口
  P2 = dis_digit; // 选能位(即位码)
  delayms(1); // 延时
  dis_digit = _crol_(dis_digit, 1); // 位选通左移, 下次选通下一位
  dis_index++; // 下一个段码

  dis_index &= 0x07; // 见注释
  }

  }
  void delayms(unsigned char ms) // 延时子程序(晶振12M)
  {
  unsigned char i;
  while(ms--)
  {
  for(i = 0; i < 120; i++);
  }
  }

  ★ 注释: 此句作用是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 代替,效果一样。

  ★ 通过C51用上述方法实现时,其段码放在了数组dis_code[11]中,再通过缓冲区数组dis_buf[]将程序中要调用的值装入,这样就可以用下标(偏移量)访问了。这样看上去有些繁锁,但其思路比较清楚,结构上也很明了,具有通用性,便于扩展。

  ★ 另外只要把程序中的延时加长,如delayms(1000),下载到板上就可以看到实际上数码管是由低位到高位逐位显示的。

  --------------------------------------------------------------------------------
  若单单就实现这个功能而言,可以直接调入段码数组dis_code[11]中下标从0到7的值,而不必再设置缓冲数组dis_buf[],实现如下:

  #include <reg51.h>
  #include <intrins.h> //_crol_()用

  void delayms(unsigned char ms); //延时子程序

  unsigned char data dis_digit; //位选通值, 传送到P2口用于选通当前数码管的数值,
  //如等于0x01时,选通P2.0口数码管

  unsigned char code dis_code[11]={0x08,0xab,0x12,0x22,0xa1, // 0,1,2,3,4
  0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9,off

  unsigned char data dis_index; //显示索引, 用于标识当前显示的数码管和缓冲区的偏移量

  void main()
  {
  P0 = 0xff; // 关闭所有数码管
  P2 = 0x00;

  dis_index = 0; // 当前偏移量为0
  dis_digit = 0x01; // 选通P2.0

  while(1)
  {
  P0 = dis_code[dis_index]; // 段码送P0口
  P2 = dis_digit; // 位码送P2口
  delayms(1);

  dis_digit = _crol_(dis_digit, 1); // 位选通左移, 下次选通下一位

  dis_index++;
  dis_index &= 0x07;
  }
  }
  void delayms(unsigned char ms) // 延时子程序(晶振12M)
  {
  unsigned char i;
  while(ms--)
  {
  for(i = 0; i < 120; i++);
  }
  }

  ★ 通本来是想通过以下方式实现一次循环的:

  for (dis_index = 0; dis_index < 8; dis_index++)
  {
  P0 = dis_code[dis_index]; // 段码送P0口
  P2 = dis_index+1; // 位码送P2口
  delayms(1);
  }

  可得到的总是错误的结果:第0位到第2位这三位显示的是三个8,第3位显示的是7,高四位没有显示。加长延时逐位观察也没有发现错误的规律,对Keil的调试也不熟悉,先把问题留到这,待找出原因后再补上。

  [2006.5.2] 找出原因啦,补上:

  今天又看了一下,找到上面的错误出在哪了。当时是想用dis_index的值做为位码的,即第一位显示0时,段码为dis_code[0], 即dis_index值为0, 此时位码值为1。第二位显示1时,段码为dis_code[1],即dis_index值为1,此时位码值为2。所以就简单用了个加1运算,将P0口的偏移值与P2口的位码联系起来。但仔细想一下位码的原理,上述方法显然是错的,只要再验证一步就明白了,即当第3位显示2时,段码为dis_code[2], dis_index值为2,加1后为3,按上述方法时就将这个3作为了位码,而正确的位码应该是4 (00000100B)。所以出错。实际上这个对应关系是有的,但不是简简单单的加1,位码应该是2的dis_index次幂。即:
  0--1
  1--2
  2--4
  3--8
  4--16 ……
  幂次运算函数flaot pow(float x, float y)包含在math.h中, 返回值为xy (float型):

  for (dis_index = 0; dis_index < 8; dis_index++)
  {
  P0 = dis_code[dis_index]; // 段码送P0口
  P2 = (char) pow(2, dis_index); // 位码送P2口
  delayms(255);
  }

  再次下载到板上发现仍有问题, 即延时很小的时候显示混乱,但加大延时时间(如程序中的值)可以观查到数码管是按位正确显示的。另外用这种方法产生的代码量也很大(从写入速度看,很明显)。这里仅提出了一个思路,只在此实验中适用,意义不大,到此为止。

  [补充结束]

  --------------------------------------------------------------------------------

  AS中绐出的例程是利用定时中断做的延时,参考修改到我的板上,程序如下:

  #include <reg51.h>
  #include <intrins.h> // 包含了左移函数_crol_()

  unsigned char data dis_digit; // 位选通值, 传送到P2口用于选通当前数码管的数值,
  // 如等于0x01时,选通P2.0口数码管

  unsigned char code dis_code[11]={0x08,0xab,0x12,0x22,0xa1, // 0,1,2,3,4
  0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9,off

  unsigned char data dis_buf[8]; // dis_buf 显于缓冲区基地址

  unsigned char data dis_index; // 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量

  void main()
  {
  P0 = 0xff; //关闭所有数码管
  P2 = 0x00;

  TMOD = 0x01; // 00000001B 定时计数器0工作在方式1,16位定时器/计数器
  TH0 = 0xFC;
  TL0 = 0x17; // 预置初值 FC17H=64535D, 216-64535=1001us=1ms

  IE = 0x82; // 10000010B T0溢出中断允许

  dis_buf[0] = dis_code[0x0];
  dis_buf[1] = dis_code[0x1];
  dis_buf[2] = dis_code[0x2];
  dis_buf[3] = dis_code[0x3];
  dis_buf[4] = dis_code[0x4];
  dis_buf[5] = dis_code[0x5];
  dis_buf[6] = dis_code[0x6];
  dis_buf[7] = dis_code[0x7];

  dis_digit = 0x01; // 选通第0位数码管
  dis_index = 0; // 偏移初值为0

  TR0 = 1; // 启动T0
  while(1); // 循环等待中断

  }

  void timer0() interrupt 1 // 定时器0中断服务程序, 用于数码管的动态扫描

  {
  TH0 = 0xFC; // 发生中断定时/计数器重装初值
  TL0 = 0x17; // 感觉此处(及上)应该是0x18,而不是17,分析如下

  P2 = 0x00; // 先关闭所有数码管
  P0 = dis_buf[dis_index]; // 段码送P0口
  P2 = dis_digit; // 位码送P2口

  dis_digit = _crol_(dis_digit,1); // 位选通值左移, 下次中断时选通下一位数码管
  dis_index++;

  dis_index &= 0x07; // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描
  }

  ★ 定时器/计数器的输入脉冲周期与机器周期一样, 为时钟振荡频率的1/12。晶振用12M时,输入脉冲周期间隔为1us。机器周期为 1us。设T0的初值为X,计算初值的方法:本例中定时器用方式1,是16位的定时器,即最大值为216=65536,超过此值将发生溢出,引起中断,进入中断处理程序。这里要让其延时1ms,即1000us, 则有式216-X=1000,可得X=64536,换算为16进制为FC18,即初值TH0=0xFC,TL0=0x18。即定时器由64536开始计数,经1000次计数后值为65536,将发生定时中断,再进入中断处理子程序后,重新装和初值,如此循环下去。
  而在上例中其装入的初值并非FC18(64536),而是FC17(64535)。我想大概认为其计数范围在0~65565的原因吧,我也想过这个问题,是用216-计数初值=中断间隔 呢,还是用(216-1)-计数初值=中断间隔呢? 随手查了几本书, 说法不一,不过用前者的较多, 我自己也认为前者比较合理, 因为在计算机中16位的二进制不能表示65536, 在各位均为1时表示的值为65535, 即65535H=1111111111111111B, 也可以说65536是溢出得到的。而何时响应中断就成了关键,拿上例来说,如设初值为64535(FC17),则计数到65535时,已经计数为1000个,即1ms,但此时并未发生溢出,因此也没有触发中断。而是在下一个计数后才发生。确切值应为1001us。若初值为64536(FC18),则恰好为所需值,所以上例中的初值应该用FC18而不是FC17。这仅仅是我自己的一点看法,至于是不是这样,还有待进一步考证。

  --------------------------------------------------------------------------------
  最终下载到实验板上结果:

  ######################################补充########################################

  用Proteus仿真结果如下(某一状态的截图):

  ★ 该电路段码是按与板上接法对应的,即按前面的段码表次序连接。另外这个八位的仿真数码管最左端是第一位,最右端是第八位,与板上的顺序相反,所以接为了统一,该图以板为准连接。上图不加上拉电阻也可仿真出结果,只是P0口高电平显示为灰,即高阻。

参考资料:http://www.programfan.com/blog/article.asp?id=12535

什么是数码管动态显示

数码管动态显示是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟...

什么是LED数码显示中的静态、动态显示技术?各自特点是什么?

数码管静态显示就是每个数码管的驱动电平不会改变,知道这个数码管的数值发生变化。动态显示就是利用人眼反应迟钝,数码管轮流显示一段时间,比如都是20ms,效果看起来是几个数码管同时亮(实际是只有一个在点亮,其他的是余晖)。静态显示亮度比较亮,功耗大;动态显示亮度稍微差点,但是显示位数多;注意动...

数码管动态显示和静态显示的区别?

1、动态显示:动态显示需要CPU不断的扫描位码发送显示数据,占用CPU时间长。2、静态显示:静态显示由于不用不断变换位码,占用CPU时间短。三、硬件资源不同 1、动态显示:动态显示消耗的硬件资源相较于静态显示消耗的硬件资源较少。2、静态显示:静态显示消耗的硬件资源相较于动态显示消耗的硬件资源较多。

什么是数码管动态显示

各个数码管的段码都是p0口的输出,即各个数码管输入的段码都是一样的, 为了使其分别显示不同的数字, 可采用动态显示的方式,即先只让最低位显示0(含点),经过一段延时,再只让次低位显示1,如此类推。由视觉暂留,只要我们的延时时间足够短,就能够使得数码的显示看起来非常的稳定清楚。过程如下图。 采用上述方法...

什么是数码管的动态显示和静态显示?

数码管是一种常用的数字显示设备,它可以通过动态显示和静态显示两种方式来显示数字和字符,它们的区别和作用如下🌊动态显示动态显示是指数码管中的数字依次或随着特定的时间间隔依次点亮,形成连续的数字或字符显示效果。一般通过快速切换数码管的每个段来实现。动态显示可以实现数字和字符的流动效果,...

数码管动态显示原理

数码管,也称作辉光管,是一种可以显示数字和其他信息的电子设备。玻璃管中包括一个金属丝网制成的阳极和多个阴极。大部分数码管阴极的形状为数字。管中充以低压气体,通常大部分为氖加上一些汞和/或氩。给某一个阴极充电,数码管就会发出颜色光,视乎管内的气体而定,一般都是橙色或绿色。

数码管显示技术:静态与动态

数码管显示技术是一种常见的数字显示方式。本文将介绍数码管的静态和动态显示方式,以及它们的优缺点。静态显示数码管静态显示是指每个数码管的驱动电平保持不变,直到数值发生变化。它的亮度较高,但功耗较大。动态显示数码管动态显示利用人眼的短暂视觉停留,让数码管轮流显示一段时间,如20ms,造成多个数码管同时...

数码管动态显示工作原理

1、多个数码管的段码连接在一起,位码分别控制。2、由于段码连接在一起,如果数码管全亮,则显示的数据相同,所以为了显示不同的数字,任何时刻,只能有一个数码管显示,其余不显示。3、用软件使这几个数码管轮流显示我们需要的数字。4、只要更新频率足够快(&gt;100Hz),肉眼看起来,这些数码管就同时...

为什么数码管一般采用动态显示

动态显示也就是扫描显示,目的是减少驱动的IO口。如8*8扫描只需要16个IO口,但是,可以驱动8个7段数码管(7段加小数点)。如果不采用扫描技术,需要64个IO口。

数码管动态显示原理是什么

数码管动态显示原理基于电路中的段选和位选技术。每一个数码管都有七个段(segment),如数字0~9和小数点。段选技术可以选择一个特定的段来显示数字。位选技术则可以选择一个特定的位置来显示数字。通过不断地更改段选和位选,可以使数码管呈动态显示。

数码管动态显示原理 数码管动态显示原理简述 数码管动态显示问题分析 数码管的动态显示和静态显示 怎么样编写数码管动态显示 led数码管动态显示 共阳极数码管动态显示 数码管动态显示原理是什么 数码管连接方式
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
心电图运动负荷试验运动负荷量的确定 和平精英极寒模式攻略 极寒模式规则详解-手游资讯-安族网 和平精英极寒模式怎么玩 快速上分熬过暴风雪方法 四年级下册白桦课文主要内容白桦这篇课文的主要内容 白桦丛作者作品 和平精英冰寒模式怎么玩 白桦是苏联著名诗人叶赛宁的抒情诗对吗 重庆千青生态农业有限公司怎么样? 玉米秸秆怎么制作成可贮藏的饲料 千青爱草仙龙园地址在哪里? 什么是LED数码管静态扫描和动态扫描.简述LED数码管... LED 动态数码管显示? 单片机 汇编 LED数码管动态显示 1,led数码管静态显示和动态显示有什么不同 采用动态方式控制4位LED数码管显示时,对4位数码管... 简述LED数码管动态扫描的原理及其实现方式 单片机驱动LED数码管有哪几种显示方法 4位共阳极led数码管动态显示驱动原理? 请教51汇编之LED数码管动态显示方法 在单片机应用系统中。LED数码管显示电路通常有什么... 数码管动态显示工作原理 LED的静态显示方式与动态显示方式有何区别? LED的静态显示方式与动态显示方式有何区别 简述LED数码管动态,扫描的原理及其实现方式? 什么是LED数码显示中的静态、动态显示技术?各自特... 印度总统是谁? 是谁发明的火狐浏览器? 火狐浏览器好用吗、 火狐浏览器无法使用 火狐浏览器无法进入网页 为什么数码管一般采用动态显示 用AT89C51单片机控制两位8段LED数码管采用动态显示... LED数码管有哪些种类 LED数码管的驱动方式 印度总统 苹果6美版有铆钉版么 波司登X高缇耶设计师联名款哪款最好看? 有人用过春缇舍氧元素去过疤痕吗? 王晶拍戏时怒骂张敏,被暴打后缝了15针,为啥张敏... vivo手机怎样关掉分屏 张敏的成功离不开三位男人,除了周星驰外,另两位... 向华胜爱了张敏9年,为她与导演王晶对立,他后来怎... vivo x21分屏微信锁怎么去掉? 张敏的简介 vivo+s6分屏密码锁怎么解 如何评价张敏? vivo怎么退出分屏 张敏现在怎么样了? vivox50分屏模式怎么关闭 张敏有什么作品?