找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6313|回复: 3
打印 上一主题 下一主题
收起左侧

多位数码管动态扫描显示变化数据,并不停变化数值 大家能帮我解释一下这原理吗??

[复制链接]
跳转到指定楼层
楼主
ID:66137 发表于 2014-12-8 22:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个程序是开发板里面的一个,大家能帮我分析下这个程序的工作原理吗,先谢谢各位了。。程序如下,我一直都搞不懂.......

/****************************** (C) COPYRIGHT 2013 YQDZ **************************
* 文  件  名      : 999累加.C
* 作      者      : YQDZ
* 版      本      : V1.0
* 日      期      : 2013/07/07
* 主  控  MCU     : STC89C52RC
* 主      频      : 11.0592MHz
* 编  译  器      : Keil C51 V4.22
* 描      述      : 多位数码管动态扫描显示变化数据,并不停变化数值。V573需要用短
*                                        路帽短接到VCC,不用时需要移除。
*********************************************************************************/
#include"reg52.h"                                                                                 /* 调用头文件,单片机内部寄存器都定义在此,用的时候需要先调用 */

typedef        unsigned char UINT8;                                            /* 给unsigned char重新定义一个别名UINT8,用的时候直接写UINT8就可以 */
typedef unsigned int  UINT16;                                                        /* 给unsigned int重新定义一个别名UINT16,用的时候直接写UINT16就可以 */

/******************************** 引脚定义 **************************************
                        单片机                    74HC573
                        P00-P07              DB0-DB7
                         P22                                  LE1
                         P23                                  LE2

                         V573                                  VCC
*********************************************************************************/
#define DataPort P0                                                                         /* 定义数据端口,程序中遇到DataPort则用P0替换 */
sbit LE1 = P2^2;                                                                                /* 定义74HC573锁存使能端口 段锁存 */
sbit LE2 = P2^3;                                                                                /* 定义74HC573锁存使能端口 位锁存 */

UINT8 code DuanMa[ ] = { 0x3F,0x06,0x5B,0x4F,
                                             0x66,0x6D,0x7D,0x07,
                                             0x7F,0x6F };                                        /* 段码值0-9 */

UINT8 code WeiMa[] = { 0xFE,0xFD,0xFB,0xF7,
                                           0xEF,0xDF,0xBF,0x7F };                        /* 分别对应相应的数码管位码,决定哪个数码管被点亮 */

UINT8 TempData[8];                                                                                 /* 存储显示值 */

/*******************************************************************************
* 函  数  名      : DelayMs
* 描      述      : 毫秒延时.
* 输      入      : UINT8 Ms:
*                   要延时的Ms时间. Ms值范围为0-65535,数值越大延时时间越长
* 返      回      : 无.
*******************************************************************************/
void DelayMs( UINT16 Ms )
{
        UINT8 i;
         
        while (Ms--)
          {
            for ( i = 0; i < 114; i++ );                                        /* 循环114大概是1MS时间 */
          }
}

/*******************************************************************************
* 函  数  名      : Display
* 描      述      : 显示函数,用于动态扫描数码管
* 输      入      : UINT8 FirstBit:
*                                        要显示的位
*                                        UINT8 Num:
*                                        要显示的数码管的位数
* 返      回      : 无.
********************************************************************************/
void Display( UINT8 FirstBit, UINT8 Num )
{
        UINT8 i;
         
        for( i = 0; i < Num; i++ )
        {
                DataPort=0;                                                                           /* 清空数据,防止有交替重影 */
               LE1 = 1;                                                                             /* 段锁存 */
               LE1 = 0;

               DataPort = WeiMa[ i + FirstBit ];                                /* 取位码 */
               LE2 = 1;                                                                             /* 位锁存 */
               LE2 = 0;

               DataPort = TempData[ i ];                                                 /* 取显示数据,段码 */
               LE1 = 1;                                                                             /* 段锁存 */
               LE1 = 0;

                   DelayMs(5);                                                                         /* 扫描间隙延时,时间太长会闪烁,太短会造成重影 */
        }
}

/*******************************************************************************
* 函  数  名      : main
* 描      述      : 主函数
* 输      入      : 无.
* 返      回      : 无.
********************************************************************************/
void main (void)
{
        UINT16 Num;
         UINT16 j = 0;
         
        while( 1 )
    {
            j++;                                            /* 计数次数加1 */
                   if( j == 5 )                                                                      /* 检测当前数值显示了一小段时间后,需要显示的数值加1,实现数据显示的变化 */
            {
                        j = 0;                                      /* 计数重新开始 */
                          Num++;                                      /* 显示数据加 1 */
                          if( Num == 1000 )                                                        /* 用于显示0-999 */
                    Num = 0;                                    /* 重新从0开始显示 */

                }
               
                TempData[ 0 ] = DuanMa[ Num / 100 ];                        /* 计算显示数据对应段码的数据成员,如要显示68,则68/10=6  68%10 = 8 */
                   TempData[ 1 ] = DuanMa[ ( Num % 100 ) / 10 ];
                   TempData[ 2 ] = DuanMa[ ( Num % 100 ) % 10 ];
                   Display( 2, 3 );                                /* 调用显示程序 */
        }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:836364 发表于 2020-11-3 20:45 | 只看该作者
首先你得明白动态扫描的工作原理,这个多位数码管一般分为两个东东,一个是数据位,另一是地址位,数据位主要是显示数字之类的东东的,而地址位是选择那个位置的led灯亮的
回复

使用道具 举报

板凳
ID:826942 发表于 2020-11-4 12:30 | 只看该作者
数码管显示的原理是快速的循环扫描显示数字,利用人眼睛视觉差达到同时显示的效果,比如显示268,就是在TempData[ 0 ]显示数字2,其他数码管不显示,延迟5毫秒后,在TempData[ 1 ]显示数字6,其他数码管不显示,延迟5毫秒后,在TempData[ 2]显示数字8,其他数码管不显示,延迟5毫秒后,又回到最开始的TempData[ 0 ]显示数字2,其他数码管不显示上,如此循环,因为显示刷新的频率快和人眼的视觉差的原因,你看到的就是268同时显示。
具体到数码管的显示上有分段选和位选,就是8位数码管显示那一个数码管,就是这段代码
UINT8 code WeiMa[] = { 0xFE,0xFD,0xFB,0xF7,
                                           0xEF,0xDF,0xBF,0x7F };                        /* 分别对应相应的数码管位码,决定哪个数码管被点亮 */
比如显示268,就是在TempData[ 0 ]显示数字2,这段就是选择点亮TempData[ 0 ],
UINT8 code DuanMa[ ] = { 0x3F,0x06,0x5B,0x4F,
                                             0x66,0x6D,0x7D,0x07,
                                             0x7F,0x6F };                                        /* 段码值0-9 */
这段就是决定在TempData[ 0 ]上显示的数字是2.
回复

使用道具 举报

地板
ID:213173 发表于 2020-11-4 12:44 | 只看该作者
把程序简化一下便于楼主理解
#include"reg52.h" /* 调用头文件,单片机内部寄存器都定义在此,用的时候需要先调用 */

typedef unsigned char UINT8;/* 给unsigned char重新定义一个别名UINT8,用的时候直接写UINT8就可以 */
typedef unsigned int  UINT16;/* 给unsigned int重新定义一个别名UINT16,用的时候直接写UINT16就可以 */

sbit LE1 = P2^2;   /* 定义74HC573锁存使能端口 段锁存 */
sbit LE2 = P2^3;   /* 定义74HC573锁存使能端口 位锁存 */

UINT8 code DuanMa[ ] = { 0x3F,0x06,0x5B,0x4F,
                         0x66,0x6D,0x7D,0x07,
                         0x7F,0x6F };  /* 段码值0-9 */
UINT8 code WeiMa[] = { 0xFE,0xFD,0xFB,0xF7,
                       0xEF,0xDF,0xBF,0x7F };/* 分别对应相应的数码管位码,决定哪个数码管被点亮 */
UINT8 TempData[8];   /* 存储显示值 */

void DelayMs(UINT16 Ms)
{
        UINT8 i;
        while (Ms--)
        {
                for(i=0;i<114;i++);/* 循环114大概是1MS时间 */
        }
}

void main (void)
{
        UINT16 Num=0,j=0;
        UINT8  i=0;
        while(1)
        {
                j++;
                if(j==1000)//约1秒
                {
                        j=0;
                        Num++;
                        if(Num==1000)
                                Num = 0;
                }//数据按十进制分解后保存在显示缓存中
                TempData[0] = DuanMa[Num/100%10];/* 计算显示数据对应段码的数据成员,如要显示68,则68/10=6  68%10 = 8 */
                TempData[1] = DuanMa[Num/10%10];
                TempData[2] = DuanMa[Num%10];

                P0=0x00;/* 清空数据,防止有交替重影 */
                LE1 = 1;   /* 段锁存 */
                LE1 = 0;
               
                P0=WeiMa[i];/* 取位码 */
                LE2 = 1;/* 位锁存 */
                LE2 = 0;
               
                P0=TempData[i]; /* 取显示数据,段码 */
                LE1 = 1;  /* 段锁存 */
                LE1 = 0;
                i++;
                if(i==3)
                        i=0;
                DelayMs(1);//控制主循环周期约1ms
        }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表