查看: 809|回复: 0

[经验] 单片机数码管显示原理

[复制链接]
  • TA的每日心情
    无聊
    2018-11-16 10:48
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2020-6-12 10:18:42 | 显示全部楼层 |阅读模式
    分享到:
    小灯是一种简单的LED,给我们视觉效果只能通过亮和灭来表达简单信息。而这节课我们要来学习一种表达更加明确的器件,数码管。

    1、数码管的基本介绍
    先给大家提供一张原理图看一下,如图1所示。
    1.jpg
    图1 数码管原理图
    这是比较常见的数码管的原理图,我们板子上一共有6只数码管。前边有了LED小灯的学习,数码管学习就会轻松的多了。从图1能看出来,数码管共有a,b,c,d,e,f,g,dp这8个段,而实际上,这8个段每一段都是一个LED小灯,所以数码管就是由8个LED小灯所组成的。我们看一下数码管内部结构图。

    2.jpg
    图2 数码管结构图

    数码管分为共阳数码管和共阴数码管,所谓的共阴数码管就是8只LED小灯的阴极是接在一起的,也就是阴极是公共端,由阳极来控制小灯是否亮灭。同理,共阳数码管就是阳极是接到一起的,大家可以仔细研究下图1。细心的同学也会发现,数码管上边有2个com,实际上就是我们数码管的公共端。为什么有2 个,我个人认为,一方面有2个可以起到对称的效果,刚好是10个引脚,另外一个方面,公共端通过的电流较大,我们初中就学过,并联电路电流之和等于总电流,用2个com可以把公共电流平均到2个引脚上去,降低线路承受的电流。
    从我们板子的电路图上能看出来,我们所用的数码管是共阳数码管,如图所示。

    3.jpg
    图3 共阳数码管电路

    他们的com是接到了正极上,当然了,和LED小灯电路类似,也是由74HC138控制了三极管的导通来控制整个数码管的电流,我们先来看DS1这个数码管。原理图上可以看出来,控制DS1的三极管是Q17,控制Q17的引脚是LEDS0,对应到74HC138上边就是Y0端的输出。

    4.jpg
    图4 74HC138控制图

    我们现在的目的是让LEDS0这个引脚输出低电平,相信大家现在可以独立根据前边学到的内容把ADDR0,ADDR1,ADDR2,ADDR3,ENLED这4个输入状态写出来,现在大家不要偷懒,都去根据138的手册去写一下,不需要你记住这些结论,但是遇到就写一次,锻炼过几次后,遇到同类芯片自己就知道如何去解决问题了。

    数码管通常是用来显示数字的,我们板子上的6个数码管,习惯上我们称之为6位,那控制位选择的就是74HC138了。而数码管内部的8个LED小灯我们称之为数码管的段,那么数码管的段选择(即该段的亮灭)是通过P0口控制,经过74HC245驱动。

    2、数码管的真值表
    数码管的8个段,我们直接当成8个LED小灯来控制,那就是a、b、c、d、e、f、g、dp一共8个LED小灯。我们通过图1可以轻而易举的看出来,如果我们点亮b和c这两个LED小灯,也就是数码管的b段和c段,其他的所有的段都熄灭的话,就可以让数码管DS1显示一个数字1,那么这个时候实际上P0的值的二进制就是0b11111001,十六进制就是0xF9。那么我们写一个程序进去,看看让数码管显示一下看看。

        #include               //包含寄存器的库文件                  
        sbit  ADDR0 = P1^0;
        sbit  ADDR1 = P1^1;
        sbit  ADDR2 = P1^2;
        sbit  ADDR3 = P1^3;
        sbit  ENLED = P1^4;

        void  main()
        {
            unsigned char j = 0;
            unsigned int  i = 0;

            ENLED = 0;
            ADDR0 = 0;
            ADDR1 = 0;
             ADDR2 = 0;
            ADDR3 = 1;           //74HC138开启三极管Q17           
            while(1)             //程序死循环  
            {
                 P0 = 0xF9;      //打开数码管b和c段   
            }
    }

    大家把这个程序编译一下,下载到单片机里会发现,最右侧的数码管成功显示1这个数字。

    同样的方法,我们可以把其他的数字都成功的在数码管上显示出来,而数码管显示的数字对应给P0的赋值,我们叫做数码管的真值表。我们来列一下我们这个电路图的数码管真值表,注意,这个真值表里显示的数字都不带小数点。

    表1 数码管真值表
    数字
    0
    1
    2
    3
    4
    5
    6
    7
    真值表
    0xC0
    0xF9
    0xA4
    0xB0
    0x99
    0x92
    0x82
    0xF8
    数字
    8
    9
    A
    B
    C
    D
    E
    F
    真值表
    0x80
    0x90
    0x88
    0x83
    0xC6
    0xA1
    0x86
    0x8E

    大家可以把上边那个数码管显示1的那个程序中的P0的赋值随便修改成我们表5-1中的真值表里的数字试试看,把数码管显示的数字显示出来。

    3、数码管的静态显示
    从第三课我们学习74HC138以后,我们了解到74HC138同时一次只能让一个输出口为低电平,也就是在一个时刻内,我们只能让一个数码管显示,始终选通数码管并且可以根据我们的P0总线的信号来改变这个数码管的值,我们可以理解为数码管的静态显示。

    数码管静态显示是对应动态显示而言的,静态显示对于一两个数码管还行,多个数码管,静态显示实现的意义就没有了。这节课我们先用一个数码管的静态显示来实现一个简单的秒表,为下节课的动态显示打下基础。

    先来介绍一个51单片机的关键字code。我们前边课程定义变量的时候,一般用到unsigned char或者unsigned int这两个关键字,这样定义的变量都是放在我们的单片机的RAM中,我们在程序中可以随意去改变这个变量的值。但是还有一种常数,我们在程序中要使用,但是却不进行对这个值的改变,这种值我们可以加一个code关键字修饰一下,修饰完毕后,这个值就会存储到我们的程序空间flash中,这样可以大大节省我们单片机的RAM的使用量,毕竟我们的RAM空间比较小,而程序空间是很大的。比如我们现在要使用的数码管真值表,我们来看一下我们下边的这个程序。

    #include               //包含寄存器的库文件                  
    sbit  LED = P0^0;
    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
    };                  //用数组来存储数码管真值表,下一课详细介绍数组

    void main()
    {
        unsigned char counter = 0;
        unsigned char j = 0;

        ENLED = 0; ADDR0 = 0; ADDR1 = 0;
         ADDR2 = 0; ADDR3 = 1; P0 = 0XFF;  //74HC138和P0初始化部分

         TMOD = 0x01;                    //设置定时器0为模式1
         TH0  = 0xB8;
        TL0  = 0x00;                   //定时值初值
         TR0  = 1;                      //打开定时器0
        while(1)
        {
            if(1 == TF0)                 //判断定时器0是否溢出
            {
                TF0 = 0;
                TH0 = 0xB8;              //溢出后,重新赋值
                TL0 = 0x00;
                counter++;
                if(50 == counter)      //判断定时器0溢出是否达到50次
                {
                    counter = 0;        //counter清0,重新计数
                    P0 = LedChar[j++]; //把数组里的对应值送给P0
                    if(16 == j)         //当显示到F后,归0重新开始
                    {
                         j = 0;
                    }
                 }
             }
        }
    }

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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



    手机版|小黑屋|与非网

    GMT+8, 2025-1-13 10:44 , Processed in 0.116389 second(s), 16 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.