0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

写一个数码管动态扫描的程序,实现兼验证动态显示原理

2oON_changxuemc 2018-01-21 10:56 次阅读

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

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

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

程序的时候,都是取一个接近 10ms,又比较规整的值就行了。我们开发板上有 6 个数码管,那么我们现在就来着手写一个数码管动态扫描的程序,实现兼验证上面讲的动态显示原理。

我们的目标还是实现秒表功能,只不过这次有 6 个位了,最大可以计到 999999 秒。那么现在要实现的这个程序相对于前几章的例程来说就要复杂的多了,既要处理秒表计数,又要处理动态扫描。在编写这类稍复杂的程序时,建议初学者们先用程序流程图来把程序的整个流程理清,在动手写程序之前先把整个程序的结构框架搭好,把每一个环节要实现的功能先细化出来,然后再用程序代码一步一步的去实现出来。这样就可以避免无处下笔的迷茫感了。如图 6-1 就是本例的程序流程图,大家先根据流程图把程序的执行经过在大脑里走一遍,然后再看接下来的程序代码,体会一下流程图的作用,看是不是能帮助你更顺畅的理清程序流程。

图 6-1 数码管动态显示秒表程序流程图

#include

sbit ADDR0 = P1^0;

sbit ADDR1 = P1^1;

sbit ADDR2 = P1^2;

sbit ADDR3 = P1^3;

sbit ENLED = P1^4;

unsigned char code LedChar[] = { //数码管显示字符转换表

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,

0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E

};

unsigned char LedBuff[6] = { //数码管显示缓冲区,初值 0xFF 确保启动时都不亮

0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF

};

void main(){

unsigned char i = 0; //动态扫描的索引

unsigned int cnt = 0; //记录 T0 中断次数

unsigned long sec = 0; //记录经过的秒数

ENLED = 0; //使能 U3,选择控制数码管

ADDR3 = 1; //因为需要动态改变 ADDR0-2 的值,所以不需要再初始化了

TMOD = 0x01; //设置 T0 为模式 1

TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1ms

TL0 = 0x67;

TR0 = 1; //启动 T0

while (1){

if (TF0 == 1){ //判断 T0 是否溢出

TF0 = 0; //T0 溢出后,清零中断标志

TH0 = 0xFC; //并重新赋初值

TL0 = 0x67;

cnt++; //计数值自加 1

if (cnt >= 1000){ //判断 T0 溢出是否达到 1000 次

cnt = 0; //达到 1000 次后计数值清零

sec++; //秒计数自加 1

//以下代码将 sec 按十进制位从低到高依次提取并转为数码管显示字符

LedBuff[0] = LedChar[sec%10];

LedBuff[1] = LedChar[sec/10%10];

LedBuff[2] = LedChar[sec/100%10];

LedBuff[3] = LedChar[sec/1000%10];

LedBuff[4] = LedChar[sec/10000%10];

LedBuff[5] = LedChar[sec/100000%10];

}

//以下代码完成数码管动态扫描刷新

if (i == 0)

{ ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; }

else if (i == 1)

{ ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; }

else if (i == 2)

{ ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; }

else if (i == 3)

{ ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; }

else if (i == 4)

{ ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; }

else if (i == 5)

{ ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; }

}

}

}

这段程序,大家自己抄到 Keil 中,然后边抄边结合程序流程图来理解,最终下载到实验板上看一下运行结果。其中下边的 if...else 语句就是每 1ms 快速的刷新一个数码管,这样 6个数码管整体刷新一遍的时间就是 6ms,视觉感官上就是 6 个数码管同时亮起来了。

在 C 语言中, /”等同于数学里的除法运算,而“%”等同于我们小学学的求余数运算,这个前边已有介绍。如果是 123456 这个数字,我们要正常显示在数码管上,个位显示,就是直接对 10 取余数,这个“6”就出来了,十位数字就是先除以 10,然后再对 10 取余数,以此类推,就把 6 个数字全部显示出来了。

对于多选一的动态刷新数码管的方式,我们如果用 switch 会有更好的效果,大家来看一下我们用 switch 语句完成的情况。

#include

sbit ADDR0 = P1^0;

sbit ADDR1 = P1^1;

sbit ADDR2 = P1^2;

sbit ADDR3 = P1^3;

sbit ENLED = P1^4;

unsigned char code LedChar[] = { //数码管显示字符转换表

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,

0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E

};

unsigned char LedBuff[6] = { //数码管显示缓冲区,初值 0xFF 确保启动时都不亮

0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF

};

void main(){

unsigned char i = 0; //动态扫描的索引

unsigned int cnt = 0; //记录 T0 中断次数

unsigned long sec = 0; //记录经过的秒数

ENLED = 0; //使能 U3,选择控制数码管

ADDR3 = 1; //因为需要动态改变 ADDR0-2 的值,所以不需要再初始化了

TMOD = 0x01; //设置 T0 为模式 1

TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1ms

TL0 = 0x67;

TR0 = 1; //启动 T0

while (1){

if (TF0 == 1){ //判断 T0 是否溢出

TF0 = 0; //T0 溢出后,清零中断标志

TH0 = 0xFC; //并重新赋初值

TL0 = 0x67;

cnt++; //计数值自加 1

if (cnt >= 1000){ //判断 T0 溢出是否达到 1000 次

cnt = 0; //达到 1000 次后计数值清零

sec++; //秒计数自加 1

//以下代码将 sec 按十进制位从低到高依次提取并转为数码管显示字符

LedBuff[0] = LedChar[sec%10];

LedBuff[1] = LedChar[sec/10%10];

LedBuff[2] = LedChar[sec/100%10];

LedBuff[3] = LedChar[sec/1000%10];

LedBuff[4] = LedChar[sec/10000%10];

LedBuff[5] = LedChar[sec/100000%10];

}

//以下代码完成数码管动态扫描刷新

switch (i){

case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;

case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;

case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;

case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;

case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;

case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;

default: break;

}

}

}

}

程序完成的功能是一模一样的,但大家看一下,switch 语句是不是比 if...else 语句显得要整齐清爽呢。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数码管
    +关注

    关注

    32

    文章

    1874

    浏览量

    90921
  • 动态显示
    +关注

    关注

    0

    文章

    40

    浏览量

    11651

原文标题:单片机数码管动态显示程序及原理讲解

文章出处:【微信号:changxuemcu,微信公众号:畅学单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    数码管动态显示

    数码管动态显示,要让数码管显示0到7这8个数字,如上所示为主函数代码。我的问题是为什么要加上P0=0xff这行代码?按照
    发表于 08-27 15:33

    如何实现数码管动态显示

    实现功能:按下按键时,数码管动态显示‘ 键值-扫描值 ’按键松开时,数码管动态显示‘ 0-00
    发表于 01-07 06:22

    数码管动态显示的基本原理与实现思路

    、模块题目二、原理简述动态显示的基本原理与实现思路(转载)动态显示实质上就是轮流点亮单个数码管实现
    发表于 01-11 06:32

    分享基本的数码管动态显示案例

    稳定地显示各自的图案。在上个链接的文章,即介绍模块化设计的文章中,有实例是利用拨码开关手动地控制数码管的位选。而在实现
    发表于 08-01 15:21

    FPGA入门实现教程之数码管动态显示

    FPGA入门实现教程之数码管动态显示
    发表于 11-13 16:25 93次下载

    数码管动态显示)【C语言版】

    数码管动态显示)【C语言版】数码管动态显示)【C语言版】数码管动态显示)【C语言版】
    发表于 12-29 15:51 0次下载

    MIN数码管动态显示

    数码管动态显示,MIN数码管动态显示,MIN。
    发表于 05-03 10:48 9次下载

    LESSON4_数码管动态扫描显示

    数码管动态显示,51系列单片机控制LED数码管动态显示
    发表于 05-20 15:37 8次下载

    8个数码管静态显示_数码管动态显示

    本文主要介绍了几个数码管静态显示以及数码管动态显示程序数码管由多个发光二极
    发表于 01-16 16:37 2w次阅读
    8<b class='flag-5'>个数码管</b>静态<b class='flag-5'>显示</b>_<b class='flag-5'>数码管</b>的<b class='flag-5'>动态显示</b>

    数码管动态扫描显示01234567程序(三种方案)

    在高校电子信息类专业单片机的教学过程中,数码管动态显示实现方法是学生普遍反映较难掌握的内容。鉴于此,本文为大家带来三个数码管动态
    发表于 01-29 11:24 9.5w次阅读
    <b class='flag-5'>数码管</b><b class='flag-5'>动态</b><b class='flag-5'>扫描</b><b class='flag-5'>显示</b>01234567<b class='flag-5'>程序</b>(三种方案)

    通过FPGA DIY开发板实现数码管动态显示

    8个数码管动态显示数字,数码管依次显示数字0~7
    的头像 发表于 06-20 01:29 4288次阅读
    通过FPGA DIY开发板<b class='flag-5'>实现</b><b class='flag-5'>数码管</b><b class='flag-5'>动态显示</b>

    使用数码管动态显示123456的程序免费下载

    本文档的主要内容详细介绍的是使用数码管动态显示123456的程序免费下载。解释:数码管动态显示,其实就是
    发表于 08-07 17:33 13次下载
    使用<b class='flag-5'>数码管</b><b class='flag-5'>动态显示</b>123456的<b class='flag-5'>程序</b>免费下载

    使用51单片机设计数码管动态显示的电路图和程序及资料说明

    数码管的静态显示,是指定某一个或者几个数码管,然后显示数据。动态显示方式,所谓
    发表于 07-15 17:39 6次下载
    使用51单片机设计<b class='flag-5'>数码管</b><b class='flag-5'>动态显示</b>的电路图和<b class='flag-5'>程序</b>及资料说明

    FPGA入门系列实验教程之使用FPGA实现数码管动态显示的资料免费下载

    实现开发板上 8 个数码管动态显示 0~7。通过这个实验,掌握采用 Verilog HDL语言编程实现 7 段数码管
    发表于 06-12 16:32 15次下载
    FPGA入门系列实验教程之使用FPGA<b class='flag-5'>实现</b><b class='flag-5'>数码管</b><b class='flag-5'>动态显示</b>的资料免费下载

    数码管动态显示的原理概述

    动态显示的特点是将所有数码管的段选线并联在起,由位选线控制是哪一位数码管有效。选亮数码管采用动态
    发表于 11-04 08:00 0次下载