【三】【单片机】有关数码管的实验

静态数码管

段选

首先看74HC138译码器,我们通过控制P22,P23,P24来控制选择LED1,LED2,LED3......

P24,P23,P22三个不同的二进制数,组成一个十进制数。P24对应二进制的最高位,P23对应二进制的中间位,P22对应二进制的最低位。利用P24,P23,P22组成的二进制数转化为对应的十进制数,对应Y0,Y1,Y2...,Y7这八个位置,再对应LED灯段。

例如P24=1,P23=0,P22=0。对应的二进制数是100,十进制数是4,所以我们选择的是Y4对应的LED段,也就是LED5。

位选

段选完成后,再进行位选。段选的目的是为了选择哪一个LED灯段亮。位选的目的是让这个被选择的LED灯段亮什么数字。

一个LED灯段由八个LED灯组成,分别为a,b,c,d,e,f,g,dp。dp表示的是小数点。

位选是控制P00,P01,P02...,P07这八个位置的高低电平来控制八个LED灯的亮灭。

P00对应a,P01对应b,P02对应c,P03对应d,P04对应e,P05对应f,P06对应g,P07对应dp。

与之前控制LED灯亮灭不同的是,P00=1表示a亮,P00=0表示a灭。

段选表

LED灯段从左到右依次是8,7,6,5,4,3,2,1。我们习惯的是从左到右依次是1,2,3,4,5,6,7,8。

因此我们用Location表示从左到右的LED灯,Location=1表示左边第一个灯,Location=2表示左边第二个灯,以此类推。

Location=1,对应左边数第一个灯,对应LED8,对应Y7,对应十进制的7,对应二进制的111,对应P24=1,P23=1,P22=1。

Location=2,对应左边数第二个灯,对应LED7,对应Y6,对应十进制的6,对应二进制的110,对应P24=1,P23=1,P22=0。

Location=3,对应左边数第三个灯,对应LED6,对应Y5,对应十进制的5,对应二进制的101,对应P24=1,P23=0,P22=1。

Location=4,对应左边数第四个灯,对应LED5,对应Y4,对应十进制的4,对应二进制的100,对应P24=1,P23=0,P22=0。

Location=5,对应左边数第五个灯,对应LED4,对应Y3,对应十进制的3,对应二进制的011,对应P24=0,P23=1,P22=1。

Location=6,对应左边数第六个灯,对应LED3,对应Y2,对应十进制的2,对应二进制的010,对应P24=0,P23=1,P22=0。

Location=7,对应左边数第七个灯,对应LED2,对应Y1,对应十进制的1,对应二进制的001,对应P24=0,P23=0,P22=1。

Location=8,对应左边数第八个灯,对应LED1,对应Y0,对应十进制的0,对应二进制的000,对应P24=0,P23=0,P22=0。

可以使用swith case语句表示段选表。

位选表

用Number表示我们希望显示的数字。

Number=0,表示显示数字0,a,b,c,d,e,f灯全亮,g,dp不亮,对应P00=1,P01=1,P02=1,P03=1,P04=1,P05=1,P06=0,P07=0。对应P0=0b00111111=0x3F。

Number=1,表示显示数字1,b,c灯全亮a,d,e,f,g,dp不亮,对应P00=0,P01=1,P02=1,P03=0,P04=0,P05=0,P06=0,P07=0。对应P0=0b00000110=0x06。

Number=2,表示显示数字2,a,b,d,e,g灯全亮,c,f,dp不亮,对应P00=1,P01=1,P02=0,P03=1,P04=1,P05=0,P06=1,P07=0。对应P0=0b01011011=0x5B。

Number=3,表示显示数字3,a,b,c,d,g灯全亮,e,f,dp不亮,对应P00=1,P01=1,P02=1,P03=1,P04=0,P05=0,P06=1,P07=0。对应P0=0b01001111=0x4F。

Number=4,表示显示数字4,b,c,f,g灯全亮,a,d,e,dp不亮,对应P00=0,P01=1,P02=1,P03=0,P04=0,P05=1,P06=1,P07=0。对应P0=0b01100110=0x66 。

Number=5,表示显示数字5,a,c,d,f,g灯全亮,b,e,dp不亮,对应P00=1,P01=0,P02=1,P03=1,P04=0,P05=1,P06=1,P07=0。对应P0=0b01101101=0x6D。

Number=6,表示显示数字6,a,c,d,e,f,g灯全亮,b,dp不亮,对应P00=1,P01=0,P02=1,P03=1,P04=1,P05=1,P06=1,P07=0。对应P0=0b01111101=0x7D。

Number=7,表示显示数字7,a,b,c灯全亮,d,e,f,g,dp不亮,对应P00=1,P01=1,P02=1,P03=0,P04=0,P05=0,P06=0,P07=0。对应P0=0b00000111=0x07 。

Number=8,表示显示数字8,a,b,c,d,e,f,g灯全亮,dp不亮,对应P00=1,P01=1,P02=1,P03=1,P04=1,P05=1,P06=1,P07=0。对应P0=0b01111111=0x7F。

Number=9,表示显示数字9,a,b,c,d,f,g灯全亮,e,dp不亮,对应P00=1,P01=1,P02=1,P03=1,P04=0,P05=1,P06=1,P07=0。对应P0=0b01101111=0x6F。

因此可以用数组映射表示位选表。NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

 
#include <REGX52.H>
#include "Delay.h"
void test1(){//100=4 第五个数码管段被选中,显示数字6
        P2_4=1;
        P2_3=0;
        P2_2=0;
        P0=0x7D;//数字6
        while(1){
                
        }
}
void test2(){//100=5 第六个数码管段被选中,显示数字6
        P2_4=1;
        P2_3=0;
        P2_2=1;
        P0=0x7D;//数字6
        while(1){
                
        }
}


void Nixie(unsigned char Location,Number){
        switch(Location){//从左到右 依次1、2、3...
                case 1:P2_4=1;P2_3=1;P2_2=1;break;
                case 2:P2_4=1;P2_3=1;P2_2=0;break;
                case 3:P2_4=1;P2_3=0;P2_2=1;break;
                case 4:P2_4=1;P2_3=0;P2_2=0;break;
                case 5:P2_4=0;P2_3=1;P2_2=1;break;
                case 6:P2_4=0;P2_3=1;P2_2=0;break;
                case 7:P2_4=0;P2_3=0;P2_2=1;break;
                case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        
        P0=0x7D;//数字6
}
void test3(){
        Nixie(7,2);
        while(1){
                
        }
        
}
void test4(){
        Nixie(2,2);
        while(1){
                
        }
}

void Nixie1(unsigned char Location,Number){
        unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
        switch(Location){//从左到右 依次1、2、3...
                case 1:P2_4=1;P2_3=1;P2_2=1;break;
                case 2:P2_4=1;P2_3=1;P2_2=0;break;
                case 3:P2_4=1;P2_3=0;P2_2=1;break;
                case 4:P2_4=1;P2_3=0;P2_2=0;break;
                case 5:P2_4=0;P2_3=1;P2_2=1;break;
                case 6:P2_4=0;P2_3=1;P2_2=0;break;
                case 7:P2_4=0;P2_3=0;P2_2=1;break;
                case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        
        P0=NixieTable[Number];
}

void test5(){
        Nixie1(2,2);
        while(1){
                
        }
}
void test6(){
        Nixie1(8,9);
        while(1){
                
        }
}

void test7(){
        Nixie1(4,1);
        while(1){}
}
void main(){
//        test1();
//        test2();
//        test3();
//        test4();
//        test5();
//        test6();
        test7();
}

test1:

test2:

test3:

test4:

test5:

test6:

test7:

test1test2 函数

void test1(){//100=4 第五个数码管段被选中,显示数字6 P2_4=1; P2_3=0; P2_2=0; P0=0x7D;//数字6 while(1){ } } void test2(){//100=5 第六个数码管段被选中,显示数字6 P2_4=1; P2_3=0; P2_2=1; P0=0x7D;//数字6 while(1){ } }

test1test2 函数通过设置P2端口的不同位,选择第五个和第六个数码管段(指的是LED5,和LED6),并且通过将P0端口设置为0x7D来显示数字6。这两个函数都包含了一个无限循环,用于持续显示数字。

Nixie 函数

void Nixie(unsigned char Location,Number){ switch(Location){//从左到右 依次1、2、3... case 1:P2_4=1;P2_3=1;P2_2=1;break; case 2:P2_4=1;P2_3=1;P2_2=0;break; case 3:P2_4=1;P2_3=0;P2_2=1;break; case 4:P2_4=1;P2_3=0;P2_2=0;break; case 5:P2_4=0;P2_3=1;P2_2=1;break; case 6:P2_4=0;P2_3=1;P2_2=0;break; case 7:P2_4=0;P2_3=0;P2_2=1;break; case 8:P2_4=0;P2_3=0;P2_2=0;break; } P0=0x7D;//数字6 }

Nixie 函数接收两个参数LocationNumber,并根据Location的值来选择特定的数码管,Location指的是从左往右数第Location个数码管。然后,函数将P0端口设置为0x7D,显示数字6。

Nixie1 函数

void Nixie1(unsigned char Location,Number){ unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; switch(Location){//从左到右 依次1、2、3... case 1:P2_4=1;P2_3=1;P2_2=1;break; case 2:P2_4=1;P2_3=1;P2_2=0;break; case 3:P2_4=1;P2_3=0;P2_2=1;break; case 4:P2_4=1;P2_3=0;P2_2=0;break; case 5:P2_4=0;P2_3=1;P2_2=1;break; case 6:P2_4=0;P2_3=1;P2_2=0;break; case 7:P2_4=0;P2_3=0;P2_2=1;break; case 8:P2_4=0;P2_3=0;P2_2=0;break; } P0=NixieTable[Number]; }

Nixie1 函数是Nixie的扩展版本,允许显示0到9之间的任何数字。它使用NixieTable数组来存储每个数字对应的段码,并根据传入的Number参数显示相应的数字。

test3test4test5test6,和test7 函数

这些函数展示了如何使用NixieNixie1函数来控制数码管显示特定的数字。

动态数码管显示

main.c:

 
#include <REGX52.H>
#include "Delay.h"
#include "Nixie.h"
void test1(){
        while(1){
                Nixie(1,1);
                Nixie(2,2);
                Nixie(3,3);
        }
        
}

void main(){
        test1();
        
}

Nixie.c:

 
#include <REGX52.H>
#include "Delay.h"
void Nixie(unsigned char Location,Number){
        unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
        switch(Location){//从左到右 依次1、2、3...
                case 1:P2_4=1;P2_3=1;P2_2=1;break;
                case 2:P2_4=1;P2_3=1;P2_2=0;break;
                case 3:P2_4=1;P2_3=0;P2_2=1;break;
                case 4:P2_4=1;P2_3=0;P2_2=0;break;
                case 5:P2_4=0;P2_3=1;P2_2=1;break;
                case 6:P2_4=0;P2_3=1;P2_2=0;break;
                case 7:P2_4=0;P2_3=0;P2_2=1;break;
                case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        
        P0=NixieTable[Number];
//        Delay(1);
//        P0=0x00;
}

Delay.c:

 
void Delay(unsigned int xms)                //@11.0592MHz
{
        
        while(xms--){
        unsigned char i, j;

        
        i = 2;
        j = 199;
        do
        {
                while (--j);
        } while (--i);
        }

}

出现重影:

没有出现重影:

#include <REGX52.H> #include "Delay.h" void Nixie(unsigned char Location,Number){ unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; switch(Location){//从左到右 依次1、2、3... case 1:P2_4=1;P2_3=1;P2_2=1;break; case 2:P2_4=1;P2_3=1;P2_2=0;break; case 3:P2_4=1;P2_3=0;P2_2=1;break; case 4:P2_4=1;P2_3=0;P2_2=0;break; case 5:P2_4=0;P2_3=1;P2_2=1;break; case 6:P2_4=0;P2_3=1;P2_2=0;break; case 7:P2_4=0;P2_3=0;P2_2=1;break; case 8:P2_4=0;P2_3=0;P2_2=0;break; } P0=NixieTable[Number]; // Delay(1); // P0=0x00; }

这段代码是用于控制数码管显示的函数 Nixie,它负责根据给定的位置 Location 和数字 Number 来点亮相应的数码管。代码中包含了一个数码管编码表 NixieTable,用于将数字转换为相应的段码,并通过P2端口的某些位来选择数码管的特定段。

重影原因分析

根据这段代码,数码管出现重影可能是由于在切换不同的数码管显示内容时,之前的显示内容没有被及时清除,导致新的显示和旧的显示重叠,形成了重影。这通常发生在动态显示的情况下,即在多个数码管之间快速切换以给人一种同时显示的错觉。

段选,位选,段选,位选......在这种交替情形下,会发生,上一个的位选与下一个段选结合,导致上一个位选错位,出现重影。

解决办法

解决方法是在显示新的数字之前清除之前的显示,这可以通过短暂关闭所有段的显示来实现。在代码中,这一步骤已经以注释的形式给出:

// Delay(1); // 延时函数,用于在显示之间提供短暂的暂停

// P0=0x00; // 关闭所有段,清除显示内容

取消这两行代码的注释将启用延时和清除显示的操作。这样,在显示每个数字之前,数码管的所有段都会被关闭一小段时间,这有助于消除重影。

确保在每次更新数码管显示之后,都加入了足够的延时和清除操作,这样可以有效消除重影。在实际应用中,可能还需要调整延时的时长,以达到最佳的显示效果和消影效果。

加入一毫秒的延时是为了让灯光更亮。如果不加这一毫秒的延时,可以正常显示无重影的123,但是灯光的亮度会明显下降。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖精七七_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值