静态数码管
段选
首先看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:
test1
和 test2
函数
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){
}
}
test1
和 test2
函数通过设置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
函数接收两个参数Location
和Number
,并根据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
参数显示相应的数字。
test3
,test4
,test5
,test6
,和test7
函数
这些函数展示了如何使用Nixie
和Nixie1
函数来控制数码管显示特定的数字。
动态数码管显示
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,但是灯光的亮度会明显下降。
结尾
最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!