从上一博文《8051单片机实战分析(以STC89C52RC为例) | 05 - 静态数码管驱动》,我们可以了解到数码管一些驱动原理,实际上静态扫描在项目中基本不会用到,在项目中我们经常用动态扫描,所以便有了本文。如果不懂数码管的段选与位选请先看这篇:《3分钟带你彻底弄懂数码管的段选与位选》

1 动态扫描

那什么是动态扫描呢?

举个例子:有 2 个数码管,我们要显示“12”这个数字,可以先让高位的位选三极管导通,然后控制段选让其显示“1”,延时一定时间后再让低位的位选三极管导通,然后控制段选让其显示“2”。把这个流程以一定的速度循环运行就可以让数码管显示出“12”,由于交替速度非常快,人眼识别到的就是“12”这两位数字同时亮了。

在多个数码管显示数字的时候,我们可以轮流点亮数码管(一个时刻内只有一个数码管是亮的),利用人眼的视觉暂留现象(也叫余辉效应),就可以做到看起来是所有数码管都同时亮了,这就是动态显示,也叫做动态扫描

那么一个数码管需要点亮多长时间呢?也就是说要多长时间完成一次全部数码管的扫描呢(很明显:整体扫描时间=单个数码管点亮时间*数码管个数)?答案是:10ms 以内

当电视机和显示器还处在 CRT(电子显像管)时代的时候,有一句很流行的广告语——“100Hz无闪烁”,没错,只要刷新率大于 100Hz,即刷新时间小于 10ms,就可以做到无闪烁,这也就是我们的动态扫描的硬性指标。那么你也许会问,有最小值的限制吗?理论上没有,但实际上做到更快的刷新却没有任何进步的意义了,因为已经无闪烁了,再快也还是无闪烁,只是徒然增加 CPU 的负荷而已(因为 1 秒内要执行更多次的扫描程序)。

所以,通常我们设计程序的时候,都是取一个接近 10ms,又比较规整的值就行了。

2 原理图

① 数码管原理图:

② 数码管的位选使用138译码器进行解析,关于这块我们可以参考这篇文章:《数字器件认识 | 74HC138三八译码器的应用》。

③ MCU原理图:

3 代码

了解原理之后,我们就可以写个Demo让数码管从右至左显示0-7:

#include "reg52.h"          //此文件中定义了单片机的一些特殊功能寄存器typedef unsigned int u16;      //对数据类型进行声明定义
typedef unsigned char u8;sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;u8 code LedChar[]={0x3F,  //"0"0x06,  //"1"0x5B,  //"2"0x4F,  //"3"0x66,  //"4"0x6D,  //"5"0x7D,  //"6"0x07,  //"7"0x7F,  //"8"0x6F,  //"9"0x77,  //"A"0x7C,  //"B"0x39,  //"C"0x5E,  //"D"0x79,  //"E"0x71,  //"F"0xff, //全亮0x00  //熄灭
};/*******************************************************************************
* 函 数 名         : delay
* 函数功能         : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{while(i--);
}/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能         : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigitalDisplay()
{u8 i;for(i=0;i<8;i++){switch(i)   //位选,选择点亮的数码管,{case(0):LSA=0;LSB=0;LSC=0; break;//显示第0位case(1):LSA=1;LSB=0;LSC=0; break;//显示第1位case(2):LSA=0;LSB=1;LSC=0; break;//显示第2位case(3):LSA=1;LSB=1;LSC=0; break;//显示第3位case(4):LSA=0;LSB=0;LSC=1; break;//显示第4位case(5):LSA=1;LSB=0;LSC=1; break;//显示第5位case(6):LSA=0;LSB=1;LSC=1; break;//显示第6位case(7):LSA=1;LSB=1;LSC=1; break;//显示第7位  }P0=LedChar[i];//发送段码delay(100); //间隔一段时间扫描:大约1msP0=0x00;//消隐}
}/*******************************************************************************
* 函 数 名       : main
* 函数功能       : 主函数
* 输    入       : 无
* 输    出         : 无
*******************************************************************************/
void main()
{   while(1){   DigitalDisplay();  //数码管显示函数    }
}

简要分析:

main函数单纯给DigitalDisplay子函数进行无限循环。

DigitalDisplay子函数通过for循环语句在每一次循环指定一个位选与段选。

例如i=0;时,通过LSA=0;LSB=0;LSC=0;语句控制138译码器选择Y0端口输出0,从而选定LED1网络的位选。

然后通过P0=LedChar[i];给P0端口发送段选值,i=0的时候发送的是'0'字符的段选值,每次for循环中间只延时大约1ms。

③ 注意这句话:P0=0x00;//消隐。如果没有这句话就会产生“鬼影”,这个动态扫描的一个bug

鬼影”的出现,主要是在数码管位选和段选产生的瞬态造成的。

举个简单例子,我们在数码管动态显示的那部分程序中,实际上每一个数码管点亮的持续时间是1ms的时间,1ms后进行下个数码管的切换。

在进行数码管切换的时候,比如我们从 case 7 要切换到 case 0 的时候,case 7的位选用的是LSA=1;LSB=1;LSC=1;

==》假如此刻case 7也就是最高位数码管对应的值是0,我们要切换成的 case 0 的数码管位选是LSA=0;LSB=0;LSC=0;,而对应的数码管的值假如是1

==》又因为C语言程序是一句一句顺序往下执行的,每一条语句的执行都会占用一定的时间,即使这个时间非常非常短暂。

==》但是当我们把“LSA=1”改变成“LSA=0”的时候,这个瞬间存在了一个中间状态 LSA=0; LSB=1; LSC=1;在这个瞬间上,我们就给 case 6 对应的数码管LED7网络位选瞬间赋值了0

==》当我们全部写完了LSA=0;LSB=1; LSC=0;后,这个时候,我们的 P0 还没有正式赋值,而 P0此刻却保持了前一次的值,也就是在这个瞬间,我们又给case 4对应的数码管 LED5 网络位选赋值了一个 0。。。

==》直到我们把 case 0后边的语句全部完成后,我们的刷新才正式完成。而在这个刷新过程中,有 3个瞬间我们给错误的数码管赋了值,虽然很弱(因为亮的时间很短),但是我们还是能够发现。

搞明白了原理后,我们只要避开这个瞬间错误就可以了。不产生瞬间错误的方法是,在进行位选切换期间,避免一切数码管的赋值即可。方法有两个,一个方法是刷新之前关闭所有的段选,改变好了位选后,再打开段选即可;第二个方法是关闭数码管的位选,赋值过程都做好后,再重新打开即可。这里用到了第一种方法!!

8051单片机实战分析(以STC89C52RC为例) | 06 - 动态数码管驱动相关推荐

  1. 8051单片机实战分析(以STC89C52RC为例) | 04 - 蜂鸣器驱动

    蜂鸣器发声原理是电流通过电磁线圈,使电磁线圈产生磁场来驱动振动膜发声的,因此需要一定的电流才能驱动它,单片机IO引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放大 ...

  2. 8051单片机实战分析(以STC89C52RC为例) | 09 - LED点阵显示数字

    对于LED 8*8 点阵的驱动需要用到74HC595数字器件,不了解或者忘记的可以查看博文<74HC595秒懂>学习或者回顾一下! 1 LED点阵 LED 点阵是由发光二极管排列组成的显示 ...

  3. 单片机C51(STC89C52RC)实现静态、动态数码管显示

    目录 1.138译码器原理 2.数码管显示原理 3.静态数码管显示 4.动态数码管显示 5.总结 1.138译码器原理 C B A Y Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 0 0 0 0 ...

  4. 单片机原理与应用技术(三)———动态数码管显示汇编语言

    一.数码管基础知识 1.数码管结构 一般数码管通常由八段LED灯组成,又分成共阳数码管和共阴数码管(如下图所示).共阴极数码管即为LED阴极连接在一起为公共阴极,共阳极数码光即为LED阳极连接在一起为 ...

  5. 8051单片机Proteus仿真与开发实例-OLED显示屏(SSD1306控制器)I2C驱动显示中文及图片仿真

    OLED显示屏(SSD控制器)I2C驱动显示中文及图片仿真 1.OLED显示屏介绍 在前面的实例中,已经介绍了OLED显示屏,在这里就不展开介绍了,请参考: OLED显示屏(SSD1306控制器)I2 ...

  6. 基于8051单片机实现电子时钟+数字秒表设计

    电子时钟+数字秒表设计 概述 设计任务的基本要求 整体方案 电路设计原理 软件设计 元件清单 项目下载地址 概述 电子时钟是一种利用数字电路来显示秒.分.时的计时装置,与传统的机械钟相比,它具有走时准 ...

  7. 《迷人的8051单片机》----3.4 程序

    本节书摘来自华章出版社<迷人的8051单片机>一书中的第3章,第3.4节,作者高显生,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 3.4 程序 3.4.1 ...

  8. 基于MT策略的实战分析

    基于MT策略的实战分析 一.概述 1.1研究背景 量化投资是指通过数量化方式及计算机程序化发出买卖指令,以获取稳定收益为目的的交易方式.在海外的发展已有30多年的历史,其投资业绩稳定,市场规模和份额不 ...

  9. 如何通过8051单片机与片外存储器的连接来解决8051片内RAM和ROM容量不够用的问题

    系列文章目录 上期文章回归: <你真的熟悉8051单片机的引脚功能及其使用吗?> 提示:读本文前可先阅读上期文章回归下51单片机的引脚,以便更好的阅读本文. 文章目录 系列文章目录 前言 ...

最新文章

  1. 服务器连接kvm不显示,kvm切换器使用中易出现问题及简单解决方式
  2. 【机器学习PAI实践七】文本分析算法实现新闻自动分类
  3. linux git 备份迁移,linux – 从GitHub迁移到GitLab(作为POSIX环境中的遥控器)
  4. 一些不错 Java 实践推荐!建议熟读并背诵默写全文
  5. v8go 库手动编译 v8 golang 库手动编译
  6. 2012最热门软件游戏下载Top搜集(热门影音,游戏,办公软件大集合)
  7. 程序员必读书单 1.0
  8. oracle实验报告2:: Oracle数据库物理存储结构管理(含实验小结)
  9. 朱棣文先生在哈佛大学毕业典礼上的演讲
  10. 学习SpringBoot:知乎超赞回答:Java如何进阶?分享面经
  11. Android开发:设置背景图片
  12. 开显卡硬件加速和不开的区别
  13. “凝心聚力,携手共进”辰视智能2021第一期登山公益活动顺利举行
  14. bert 中文 代码 谷歌_ACL 2020 | 用BERT解决表格问答任务,谷歌提出弱监督表格解析器TaPas...
  15. red hart linux中文,hart是什么意思_hart的翻译_音标_读音_用法_例句_爱词霸在线词典...
  16. 模电实验——实验一 晶体管共射极单管放大器
  17. 人群环境中基于深度强化学习的移动机器人避障算法
  18. unity-shader-水water实现
  19. 利用python编写祝福_Python节日祝福实现
  20. OpenCV学习笔记02--图像像素处理--二值图像、灰度图像、彩色图像像素的处理、numpy.array中的对应的函数

热门文章

  1. Copyright 与 Copyleft
  2. 哈尔滨工业大学博士覃立波:多领域端到端任务型对话系统研究分享
  3. 移动支付进入下半场 BAT将各自为王
  4. 西安电子科技大学计算机研究生工资,双一流高校本硕博毕业生,薪酬排名!西安电子科技大学全国第5!...
  5. bootchart使用
  6. 【题解】CF1181D Irrigation
  7. AP6255蓝牙语音功能的实现
  8. 【转】我国交通信号控制产品市场及技术的现状和发展
  9. Java11 ZGC 和 Java12 Shenandoah 介绍:苟日新、日日新、又日新
  10. 新邮政法规定:邮政企业对平常邮件损失不赔偿