八段数码管原理

单个数码管本质就是LED的排列组合,你也可以自己用八个LED组合试一试,分为共阴和共阳两种,共阳的3、8引脚就是接正极,共阴接地(电阻别忘了)

arduino esp32 74hc595驱动 8位数码管_单片机

arduino esp32 74hc595驱动 8位数码管_引脚_02


比如让g、dp两个led不亮,其余的都亮,看起来是啥??就是0嘛,其它的类推嘛

arduino esp32 74hc595驱动 8位数码管_引脚_03


上图下方第三个管脚为dp

多位数码管原理是一样的,都是那八个管脚,只是多了几个选通管脚:1、2、3、4,指定哪个亮啥就亮啥,以人眼无法识别的高频率变换的时候,你以为每一个都以不同的状态同时亮,其实不是的。

数码管其实可以直接使用Arduino上别人写好的库函数,想直接看这个直接跳到最后即可

万用表测试数码管好坏

一位数码管

万用表调节到二极管挡位,如果是共阴管,就把黑表笔COM端接数码管3(或8)管脚,用红表笔一个个去测试a~dp,都亮就是好的,有一个不亮就是那个小LED烧坏了。。

四位数码管

万用表调节到二极管挡位,如果是共阳管,就把红表笔接1~4其中一个,假设先测试第1个一位数码管,然后用黑表笔测试a ~dp,都亮了说明第1个一位数码管是好的,然后测试第2个一位数码管,就把 红表笔接在2上,然后黑表笔测试a ~ dp管脚,依次类推
经过测试:我发现我的第1、4个一位数码管存在“坏道”!!!

管脚分配

arduino esp32 74hc595驱动 8位数码管_引脚_04


管脚图说明 由于8266只有12个GPIO,但是有的GPIO无法使用,

GPIO0引脚在开发板运行中需要一直保持高电平状态。
GPIO2引脚 在NodeMCU开发板启动时是不能连接低电平的
GPIO6~GPIO 11被用于连接开发板的闪存,
GPIO15引脚在开发板运行中一直保持低电平状态。因此请不要使用GPIO15引脚来读取开关状态或进行I²C通讯。
于是我打算这样分配

int  a= D10;
int  b= D9; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;
int  dp= D0;

但是发现D9不知名原因维持在0.3V。。。于是取消dp,改成这样

int  a= D10;
int  b= D0;
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;

arduino esp32 74hc595驱动 8位数码管_负逻辑_05

代码

点亮全部管脚

/*
 * 四位共阳数码管测试,
 * 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
 * 0等效为LOW,1等效为HIGH,经测试有效
 */
int  a= D10;
int  b= D0; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;


void setup() {
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
}


void loop() {
  digitalWrite(a,0);
  digitalWrite(b,0);
  digitalWrite(c,0);
  digitalWrite(d,0);
  digitalWrite(e,0);
  digitalWrite(f,0);
  digitalWrite(g,0);
}

加个鸡蛋,点亮0

/*
 * 四位共阳数码管测试,
 * 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
 * 0等效为LOW,1等效为HIGH,经测试有效
 */
int  a= D10;
int  b= D0; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;


void setup() {
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
}


void loop() {
  digitalWrite(a,0);
  digitalWrite(b,0);
  digitalWrite(c,0);
  digitalWrite(d,0);
  digitalWrite(e,0);
  digitalWrite(f,0);
  digitalWrite(g,1);
}

加鸡蛋不过瘾??全家福来一套吧

/*
提前将0~9对应的管脚序列存到数组中,然后一个循环输出
最后结果就是0~9之间循环变换
*/
int  a= D10;
int  b= D0; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;

int light[10][8] = {
//a  b  c  d  e  f  g  dp
{0, 0, 0, 0, 0, 0, 1, 1},    
{1, 0, 0, 1, 1, 1, 1, 1},    
{0, 0, 1, 0, 0, 1, 0, 1},    
{0, 0, 0, 0, 1, 1, 0, 1},     
{1, 0, 0, 1, 1, 0, 0, 1},     
{0, 1, 0, 0, 1, 0, 0, 1},    
{0, 1, 0, 0, 0, 0, 0, 1},    
{0, 0, 0, 1, 1, 1, 1, 1},     
{0, 0, 0, 0, 0, 0, 0, 1},     
{0, 0, 0, 0, 1, 0, 0, 1},    
};


void setup() {
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
}


void loop() {
  for(int i = 0; i<10;i++){
    digitalWrite(a,light[i][0]);
    digitalWrite(b,light[i][1]);
    digitalWrite(c,light[i][2]);
    digitalWrite(d,light[i][3]);
    digitalWrite(e,light[i][4]);
    digitalWrite(f,light[i][5]);
    digitalWrite(g,light[i][6]);
    delay(300);
  }

}

封装一下函数

/*
 * 四位共阳数码管测试,
 * 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
 */
int  a= D10;
int  b= D0; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;
int delayTime = 500;    //延迟时间ms

int light[10][8] = {
//a  b  c  d  e  f  g  dp
{0, 0, 0, 0, 0, 0, 1, 1},    
{1, 0, 0, 1, 1, 1, 1, 1},    
{0, 0, 1, 0, 0, 1, 0, 1},    
{0, 0, 0, 0, 1, 1, 0, 1},     
{1, 0, 0, 1, 1, 0, 0, 1},     
{0, 1, 0, 0, 1, 0, 0, 1},    
{0, 1, 0, 0, 0, 0, 0, 1},    
{0, 0, 0, 1, 1, 1, 1, 1},     
{0, 0, 0, 0, 0, 0, 0, 1},     
{0, 0, 0, 0, 1, 0, 0, 1},    
};

void lightControl(int i){
  digitalWrite(a,light[i][0]);
  digitalWrite(b,light[i][1]);
  digitalWrite(c,light[i][2]);
  digitalWrite(d,light[i][3]);
  digitalWrite(e,light[i][4]);
  digitalWrite(f,light[i][5]);
  digitalWrite(g,light[i][6]);
  delay(delayTime); //不延时也是可以的,但是变化比较快
}

void setup() {
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
}


void loop() {
  for(int i = 0; i<10;i++){
   lightControl(i);
  }
}
/*其中,loop还可以这样写
void loop() {
  static int i = 0; //没有static就一直是0
   lightControl(i);
   i++;
   i = i %9;
}
*/

二位数码管不同步

上面的演示都是只能所有管子显示同一个数字,那我想显示52、13、14怎么办????
其实思路很简单,先让一个管子显示5,然后让另一个管子同时显示2,单独为每个管子引9根线,两个管子就18根,那4个不就是36???我8266没有那么多孔啊。。。。。
在这种思路上稍微改进一丢丢,只增加一根控制线来实现,一次只亮一个管子,假设两只管子A、B,让A先显示5,然后关掉A,打开B,显示2,你说这不是同时显示啊!!!但是如果提高频率呢???人眼都是傻瓜,我亮灭的频率到达阈值之后,人眼就无法分辨其实A、B是一个亮的同时另一个是灭的(有没有感觉自己的眼睛好蠢)

先控制一位数码管的亮灭

这里只在上面的程序修改了一丢丢,加了一个控制引脚,效果就是A管只有在偶数才亮!!

/*
 * 四位共阳数码管测试,
 * 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
 * 用D4控制一位数码管是否显示
 */
int  a= D10;
int  b= D0; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;
int delayTime = 500;    //延迟时间ms
int led1 = D4;  //GPIO2

int light[10][8] = {
//a  b  c  d  e  f  g  dp
{0, 0, 0, 0, 0, 0, 1, 1},    
{1, 0, 0, 1, 1, 1, 1, 1},    
{0, 0, 1, 0, 0, 1, 0, 1},    
{0, 0, 0, 0, 1, 1, 0, 1},     
{1, 0, 0, 1, 1, 0, 0, 1},     
{0, 1, 0, 0, 1, 0, 0, 1},    
{0, 1, 0, 0, 0, 0, 0, 1},    
{0, 0, 0, 1, 1, 1, 1, 1},     
{0, 0, 0, 0, 0, 0, 0, 1},     
{0, 0, 0, 0, 1, 0, 0, 1},    
};

void lightControl(int i){
  //i只能取0~9
  digitalWrite(a,light[i][0]);
  digitalWrite(b,light[i][1]);
  digitalWrite(c,light[i][2]);
  digitalWrite(d,light[i][3]);
  digitalWrite(e,light[i][4]);
  digitalWrite(f,light[i][5]);
  digitalWrite(g,light[i][6]);
  delay(delayTime); //不延时也是可以的,但是变化比较快
}

void setup() {
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(led1,OUTPUT);
}


void loop() {
  static int i = 0; //没有static就一直是0
  if(i%2==0)
  { 
    digitalWrite(led1,1);
    }
  else
  {
    digitalWrite(led1,0);
    }
  lightControl(i);
   i++;
   i = i %9;
}

两位数码管~爱你

这里又增加了一根控制线,用来控制B管的亮灭
这里A、B就可以显示不同的数字了

/*
 * 四位共阳数码管测试,
 * 2、3端口接3.3V,a~g各端口为负逻辑,0低电平为亮,1为灭
 */
int  a= D10;
int  b= D0; 
int  c= D7;
int  d= D6;
int  e= D5;
int  f= D2;
int  g= D1;
int delayTime = 500;    //延迟时间ms
int led1 = D4;  //GPIO2
int led2 = D9;  //GPIO3,最低点位还是0.3V,不过测试后发现能控制LED

int light[10][8] = {
//a  b  c  d  e  f  g  dp
{0, 0, 0, 0, 0, 0, 1, 1},    
{1, 0, 0, 1, 1, 1, 1, 1},    
{0, 0, 1, 0, 0, 1, 0, 1},    
{0, 0, 0, 0, 1, 1, 0, 1},     
{1, 0, 0, 1, 1, 0, 0, 1},     
{0, 1, 0, 0, 1, 0, 0, 1},    
{0, 1, 0, 0, 0, 0, 0, 1},    
{0, 0, 0, 1, 1, 1, 1, 1},     
{0, 0, 0, 0, 0, 0, 0, 1},     
{0, 0, 0, 0, 1, 0, 0, 1},    
};

void lightControl(int i){
  //i只能取0~9
  digitalWrite(a,light[i][0]);
  digitalWrite(b,light[i][1]);
  digitalWrite(c,light[i][2]);
  digitalWrite(d,light[i][3]);
  digitalWrite(e,light[i][4]);
  digitalWrite(f,light[i][5]);
  digitalWrite(g,light[i][6]);
  delay(delayTime); //不延时也是可以的,但是变化比较快
}

void setup() {
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  pinMode(e,OUTPUT);
  pinMode(f,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
}

//loop中切勿delay。。否则你会发现你傻了,这灯一闪一闪的
void loop() {
  static int i = 0; //没有static就一直是0
  if(i%2==0)
  { //A管显示5,B管灭
    digitalWrite(led1,1);
    digitalWrite(led2,0);
    lightControl(5);
    }
  else
  {//B管显示2,A管灭
  digitalWrite(led1,0);
  digitalWrite(led2,1);
  lightControl(2);
  }
   i++;
   i = i %2;
}

你说这看起来很傻逼卡顿啊,我这不是为了演示才调大delayTime嘛,你把它调小一点试试!!!200?100?50??究竟多小最好??根据不正常理论显示,最佳的时间应该是刚好不让你察觉到闪烁,我则是设为10,慢慢调试呗

改进

你说我不想自己写0~9对应的引脚01分配,那怎么办??也不想每次都设置那么多东西,这个世界上大部分问题都有人遇到过了,百度之后你会发现肯定有大佬写好了库函数,调用一下就行,见参考2怎么下SevSeg
这个库可以应用到1~4个数码管上,其实你也可以把上面的两位数码管的简单封装一下