欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用8266学习单片机-6-八段数码管显示数字?时间?金钱?闹钟?从一位八段数码管到四位-网络同步时钟

程序员文章站 2024-02-26 09:39:10
...

八段数码管原理

单个数码管本质就是LED的排列组合,你也可以自己用八个LED组合试一试,分为共阴和共阳两种,共阳的3、8引脚就是接正极,共阴接地(电阻别忘了)
用8266学习单片机-6-八段数码管显示数字?时间?金钱?闹钟?从一位八段数码管到四位-网络同步时钟
比如让g、dp两个led不亮,其余的都亮,看起来是啥??就是0嘛,其它的类推嘛
用8266学习单片机-6-八段数码管显示数字?时间?金钱?闹钟?从一位八段数码管到四位-网络同步时钟
上图下方第三个管脚为dp
多位数码管原理是一样的,都是那八个管脚,只是多了几个选通管脚:1、2、3、4,指定哪个亮啥就亮啥,以人眼无法识别的高频率变换的时候,你以为每一个都以不同的状态同时亮,其实不是的。
数码管其实可以直接使用Arduino上别人写好的库函数,想直接看这个直接跳到最后即可

万用表测试数码管好坏

一位数码管

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

四位数码管

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

管脚分配

用8266学习单片机-6-八段数码管显示数字?时间?金钱?闹钟?从一位八段数码管到四位-网络同步时钟
管脚图说明
由于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;

用8266学习单片机-6-八段数码管显示数字?时间?金钱?闹钟?从一位八段数码管到四位-网络同步时钟

代码

点亮全部管脚

/*
 * 四位共阳数码管测试,
 * 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个数码管上,其实你也可以把上面的两位数码管的简单封装一下

参考

  • 单管 https://blog.csdn.net/TonyIOT/article/details/82490703
  • 库 https://blog.csdn.net/TonyIOT/article/details/82490703
  • https://blog.csdn.net/weixin_43031092/article/details/106771413
  • 网络对时 https://blog.csdn.net/Cloud_1234_5678/article/details/84346087
相关标签: Node MCU 单片机