普中开源电子分享网

 找回密码
 立即注册
搜索
查看: 4416|回复: 9

数码管显示两位以上的数

 关闭 [复制链接]

2

主题

5

帖子

29

积分

新手上路

Rank: 1

积分
29
发表于 2018-1-21 01:52:38 | 显示全部楼层 |阅读模式
哪位大神知道数码管怎么能显示两位以上的数,如78,113等
回复

使用道具 举报

20

主题

1344

帖子

8377

积分

论坛元老

Rank: 8Rank: 8

积分
8377
发表于 2018-1-22 08:22:26 | 显示全部楼层
从程序上看,绝大多数数码管都只能一次亮一个。
但从现像上看,所有的程序又可以让眼睛看到每次都是多个数码管在亮。
为什么呢?
因为这个显示,利用了生理学的知识:视觉暂留。即,只要这些数码管亮灭时间很短,眼睛分辨不出谁在亮,谁是灭的,就认为都是亮的。
生活中有很多这样的例子:电影,一次只有一幅静止画面,为什么我们认为是动态的呢?因为每幅画面只亮了很短的时间,眼睛在大脑里还留有那个画面,串联起来,就是动画了。电视画面、显示器画面、手机画面,无一不是利用这样的原理。
所以,你根本不需要“真正”让数码管同时亮多个。
不是做不到,是那样做会使用太多的I/O口,那么其它事儿,单片机就做不了了。
找点书看看吧,网上的例程也非常多。
给你一个普中的例程:
/*******************************************************************************
* 实 验 名                 : 动态显示数码管实验
* 使用的IO             : 数码管使用P0,P2.2,P2.3,P2.4
* 实验效果       : 数码管显示76543210。
* 注    意                 :
*******************************************************************************/
#include<reg51.h>

#define GPIO_DIG P0

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

unsigned char code DIG_CODE[17]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsigned char DisplayData[8];
//用来存放要显示的8位数的值
void DigDisplay(); //动态显示函数
/*******************************************************************************
* 函 数 名         : main
* 函数功能                   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main(void)
{
        unsigned char i;
        for(i=0;i<8;i++)
        {
                DisplayData[i]=DIG_CODE[i];       
        }
        while(1)
        {
                DigDisplay();
        }                               
}
/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能                   : 使用数码管显示
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void DigDisplay()
{
        unsigned char i;
        unsigned int j;
        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位       
                }
                GPIO_DIG=DisplayData[i];//发送段码
                j=10;                                                 //扫描间隔时间设定
                while(j--);       
                GPIO_DIG=0x00;//消隐
        }
}
回复 支持 反对

使用道具 举报

4

主题

36

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2018-1-22 09:23:20 | 显示全部楼层
其实一次只能显示一个数码管,否则太浪费I/O口,正如二楼大神所说。
我也有一个动态数码管三分钟倒计时程序(修改自交通灯):
接线方法:P0接数码管段选,P1.0接数码管位选A,P1.1接B,P1.2接C,J2(继电器)接P3.0。
/**************************************************************************************
*                              动态数码管三分钟倒计时                                                                              *
实现现象:下载程序后数码管第一位显示分钟,最后两位显示秒,倒计时结束后电磁继电器吸合。
注意事项:P0--数码管段选,P1.0--数码管位选A,P1.1--B,P1.2--C,J2(继电器)--P3.0                                                                                                                                                                  
***************************************************************************************/

#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;

#define GPIO_DIG   P0

sbit LSA=P1^0;
sbit LSB=P1^1;
sbit LSC=P1^2;
sbit jdq=P3^0;

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                                        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u8 DisplayData[8];
u8 Second;
u8 min;

/*******************************************************************************
* 函 数 名         : delay
* 函数功能                   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
        while(i--);       
}

/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能                   : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigDisplay()
{
        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位       
                }
                GPIO_DIG=DisplayData[i];//发送段码
                delay(100); //间隔一段时间扫描       
                P0=0x00;//消隐
        }
}
void Timer0Init()
{
        TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

        TH0=0XFC;        //给定时器赋初值,定时1ms
        TL0=0X18;       
        ET0=1;//打开定时器0中断允许
        EA=1;//打开总中断
        TR0=1;//打开定时器                       
}
/*******************************************************************************
* 函 数 名       : main
* 函数功能                 : 主函数
* 输    入       : 无
* 输    出             : 无
*******************************************************************************/
void main()
{       
        Second = 1;

        Timer0Init();

        while(1)
        {
                if(min == 4)
                {
                        min = 1;
                }

                if(min < 3)
                {
                        DisplayData[0] = smgduan[2 - min];
                        DisplayData[1] = 0x00;
                        DisplayData[2] = 0x00;
                        DisplayData[3] = 0x00;
                        DisplayData[4] = 0x00;
                        DisplayData[5] = 0x00;
                        DisplayData[6] = smgduan[(59 - Second) % 100 / 10];
                        DisplayData[7] = smgduan[(59 - Second) %10];
                        DigDisplay();

                        jdq = 1;
                }
                else
                {
                        jdq = 0;
                }
        }
}
void Timer0() interrupt 1
{
        static u16 i;
        TH0=0XFC;        //给定时器赋初值,定时1ms
        TL0=0X18;
        i++;
        if(i==1000)
        {
                i=0;
                Second ++;       
        }
        if(Second==60)       
        {
                Second=0;
                min ++;
        }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

4

主题

36

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2018-1-22 09:27:45 | 显示全部楼层
科技爱好者 发表于 2018-1-22 09:23
其实一次只能显示一个数码管,否则太浪费I/O口,正如二楼大神所说。
我也有一个动态数码管三分钟倒计时程 ...

继电器吸合一分钟后重启倒计时。
回复 支持 反对

使用道具 举报

1

主题

9

帖子

26

积分

新手上路

Rank: 1

积分
26
发表于 2018-1-22 15:58:08 | 显示全部楼层
首先,你需要知道一下你的两位晶体管上的段选和位选管脚分别接入的是单片机上面的p0到p几的端口,然后再来编写程序,其他的你参照我楼上大神,1L能显示8位数显,程序比较全面可以参考的
回复 支持 反对

使用道具 举报

2

主题

5

帖子

29

积分

新手上路

Rank: 1

积分
29
 楼主| 发表于 2018-1-22 21:02:15 | 显示全部楼层
HC6800-ES-V2.0 发表于 2018-1-22 08:22
从程序上看,绝大多数数码管都只能一次亮一个。
但从现像上看,所有的程序又可以让眼睛看到每次都是多个数 ...

你可能还不太明白我的意思,我的意思是,假如变量到一个整数是78(前提是我也不知道函数返回的是多大的整数,有可能是3位的,也有可能是4位的),如果得到是两位的整数,数码管只有两个亮,并显示对应的数。
回复 支持 反对

使用道具 举报

2

主题

5

帖子

29

积分

新手上路

Rank: 1

积分
29
 楼主| 发表于 2018-1-22 21:03:56 | 显示全部楼层
edison0745 发表于 2018-1-22 21:02
你可能还不太明白我的意思,我的意思是,假如变量到一个整数是78(前提是我也不知道函数返回的是多大的整 ...

按这种思路,这样的数码管怎么实现,有做过的经验分享下
回复 支持 反对

使用道具 举报

20

主题

1344

帖子

8377

积分

论坛元老

Rank: 8Rank: 8

积分
8377
发表于 2018-1-23 09:49:55 | 显示全部楼层
edison0745 发表于 2018-1-22 21:03
按这种思路,这样的数码管怎么实现,有做过的经验分享下

很简单嘛。
第一:函数返回了一个变量,取其值,判断它是三位或是两位。(简单吧,大于99就是三位,小于等于99就是两位)
第二:分别进入显示函数,该显示三位就是是三位的显示函数,该显示两位的就是两位的显示函数。
嗯,程序有点雍长!!!!!
再来:
第一:确定你的函数返回值,只会是三位及以内的值,即三位、两位、一位。
第二:首位为零时不显示。即小于100时,只显示两位,小于10时只显示一位。
嗯,这样编程好像比较麻烦哦。

看你喜欢那种,我喜欢第一种,虽然程序行数多,但结构化很明显,方便。第二种好像思路严谨,但判断很乱(我的感觉)。

你自己以后要把问题说清楚嘛,不是我一个人理解错误啥。
回复 支持 反对

使用道具 举报

2

主题

9

帖子

39

积分

新手上路

Rank: 1

积分
39
发表于 2018-1-24 11:17:32 | 显示全部楼层
根据下面这个程序:
#include<reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
u8 smgduan[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
                             0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};// &#182;&#206;&#209;&#161;

u8 smgwei[8]={0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c}; //&#206;&#187;&#209;&#161;

void delay(u16 i)
{
        while(i--);
}
void display()
{
        u8 i;
        for(i=0;i<8;i++)       
        {
                P0=smgduan[i];
                P2=smgwei[i];
                delay(200); //í¨1y&#184;&#196;±&#228;&#209;óê±ê±&#188;&#228;&#188;′&#191;éêμ&#207;&#214;&#182;ˉì&#172;é¨&#195;è
        }
}
void main()
{
        P0=0x00;
        while(1)
        {
                display();               
        }       
}得出的8个数码管分别显示是0~7,修改程序
#include<reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
u8 smgduan[]={ 0x7D,0x7F};// &#182;&#206;&#209;&#161;

u8 smgwei[]={0x00,0x04}; //&#206;&#187;&#209;&#161;

void delay(u16 i)
{
        while(i--);
}
void display()
{
        u8 i;
        for(i=0;i<2;i++)       
        {
                P0=smgduan[i];
                P2=smgwei[i];
                delay(200); //í¨1y&#184;&#196;±&#228;&#209;óê±ê±&#188;&#228;&#188;′&#191;éêμ&#207;&#214;&#182;ˉì&#172;é¨&#195;è
        }
}
void main()
{
        P0=0x00;
        while(1)
        {
                display();               
        }       
}即可实现你所说的要求,照此程序编译则会出现3,4,5,6位数字。
回复 支持 反对

使用道具 举报

2

主题

5

帖子

29

积分

新手上路

Rank: 1

积分
29
 楼主| 发表于 2018-1-25 23:29:00 | 显示全部楼层
本帖最后由 edison0745 于 2018-1-25 23:30 编辑

/*
此程序实现动态实现显示任意位整数
*/

#include <reg52.h>
#include <stdlib.h>
#include <stdio.h>

#define uchar unsigned char
#define uint unsigned int  //65535
        
/*
P0---->74HC245
P2^2-->138译码器的A脚
P2^3-->138译码器的B脚
P2^4-->138译码器的C脚
*/
#define led P0   
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;                                                        

               
//创建结构体变量datagroup
typedef struct
{
        uchar len;
        uchar array[8];        
}datagroup;

//延时
void delay(uint i)
{
        while(i--);
}
//数码管显示
void Digital_Display(datagroup dg)
{
        uchar i;
        for(i=0;i<dg.len;i++)
        {
                switch(i)
                {
                        case 7:
                                LSC=0;                        LSB=0;                        LSA=0;   //0--000
                                break;
                        case 6:
                                LSC=0;                        LSB=0;                        LSA=1;   //1--001
                                break;
                        case 5:
                                LSC=0;                        LSB=1;                        LSA=0;   //2--010
                                break;
                        case 4:
                                LSC=0;                        LSB=1;                        LSA=1;   //3--011
                                break;
                        case 3:
                                LSC=1;                        LSB=0;                        LSA=0;   //4--100
                                break;
                        case 2:
                                LSC=1;                        LSB=0;                        LSA=1;   //5--101
                                break;
                        case 1:
                                LSC=1;                        LSB=1;                        LSA=0;   //6--110
                                break;
                        case 0:
                                LSC=1;                        LSB=1;                        LSA=1;   //7--111
                                break;                                       
                }
                led=dg.array;  //显示整数
                delay(50);
                led=0x00;   //消影
        }
}

//一位一位提取整数函数,每一位整数存入数组中
datagroup retirve(uint num)
{   
        uchar code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
                                                        0x77,0x7c,0x39,0x5e,0x79,0x71}; //0~F码表,共阴
        datagroup dGroup; //定义结构休变量
        uchar ibit;    //
        uchar i=0;
  while (1)  
    {                                 
                          ibit=num % 10;  //除10取余,得到每一位整数,由低到高
        dGroup.array =smgduan[ibit];  //把没一位的整数所对应的段选码真值赋值给结构体数组
        num = num / 10;   //除10取整,一位一位的剔除,由低到高
        i++;  
        if (num == 0) break;  //当取整后的整数为0时,退出循环
    }  
                dGroup.len=i;   //赋值整数长度
                return dGroup;  //返回结构体
}

void main(void)
{
    uint number=6578;  //随机定义任一整数  
    datagroup dg;
                    
          while(1)
                {
                        number--;
                        dg=retirve(number);   //得到number整数的每一位所对应的段选码
                        Digital_Display(dg);        //发送到动态数码管显示                       
                        
                }
      
}

               


回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

站长推荐上一条 /1 下一条

Archiver|手机版|小黑屋|普中开源电子分享网 粤ICP备16123577号-2

GMT+8, 2024-4-25 01:03 , Processed in 0.100651 second(s), 31 queries .

Powered by 论坛搭建 X3.4

Copyright © 2001-2021, Tencent Cloud.

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