使用Arduino控制两位数码管实现动态显示(不需要中断)

目的:

1、利用arduino控制一位共阳极数码管显示

2、利用arduino控制二位共阳极数码管显示

前言:

前段时间,在网上看到了一个视频,是关于二位数码管动态显示的视频,感觉很新奇,就想把它做出来,那段时间自己在网上找了很多的教学视频、资料。在学校里老师也教过关于数码管的显示问题,但是老师只用到了一位数码管的显示!可以说是非常简单的。后面自己也看了很多大佬控制二位数码管的程序,但是都卡在了中断程序这一关,我不懂中断程序怎么写,当然什么是中断程序,现在不理解没关系,办法总比问题多,本文将教你如何用arduino控制二位数码管动态显示,不涉及中断程序。我也是研究的好长一段时间才做出来的,发现弄懂了也就那么回事儿!我将利用类似中断的方式来做,但没有用到中断程序!再次声明!!!

  其实当你掌握了二位数码管的动态显示原理后,你就可以去控制多位数码管的显示了,你可以做一台电子时钟出来!或者其它什么好玩儿的东西!

那咱们开始吧!

一位数码管的显示

想要控制二位数码管,就要先知道控制一位数码管的显示的原理!

看到上面的数码管了吗?每一根都有字母表示,分别是a,b,c,d,e,f,g,h!!!每一根都是由一个led灯组成的!它的电路图是这样的!看下图(图中的dp和h都是一个意思,只是表示方式不一样,都代表数码管上面的小数点!)

 这是一张共阳的数码管内部接线图,就是由5V电源统一供电,然后接到a,b,c,d,e,f,g,dp对应的arduino引脚上面,例如:当a为低电平时,形成回路,那么a就亮!后面以此类推!

  这是一张共阴的数码管内部接线图,a,b,c,d,e,f,g,dp对应的arduino引脚上面,最后汇集到GND也就是负极,例如:当a为高电平时,形成回路,那么a就亮!后面以此类推!

所以不管是共阳还是共阴,都可以用程序来实现!这样,只要按照数码管上面的a,b,c,d,e,f,g,h对应的编号接到arduino对应的引脚,就可以啦!

例如我想让一个共阳极一位数码管显示7这个数字,那么我该怎么办呢?看下图吧!

由上图可知有三个led灯被点亮了(黄色部分),那么蓝色部分就是没有被点亮的部分!这样数字7就被显示出来了!来看看下面的这些数字吧!我刚刚说了,如果是共阳极数码管,那么a,b,c,d,e,f,g,h对应的引脚哪一个给低电平,哪一个就亮!所以你应该可以看懂下面这个表格了吧!(0就代表低电平,1就代表高电平)

 下面就是我用arduino控制的一位共阳数码管0~9的动态显示程序!这里我用到了数组!不是很难吧!

/*建立数组num
num[10][8]其中[10]表示在num数组里面有0~9共10个数列,
[8]表示每一个数列里面有8个位,每一位的数字都不一样,
0代表低电平,1代表高电平,我用的数码管是共阳的,所以只有当低电平时,
数码管对应的灯会亮
*/
int num[10][8]={
{0,0,0,0,0,0,1,1},//数字0
{1,0,0,1,1,1,1,1},//数字1
{0,0,1,0,0,1,0,1},//数字2
{0,0,0,0,1,1,0,1},//数字3
{1,0,0,1,1,0,0,1},//数字4
{0,1,0,0,1,0,0,1},//数字5
{0,1,0,0,0,0,0,1},//数字6
{0,0,0,1,1,1,1,1},//数字7
{0,0,0,0,0,0,0,1},//数字8
{0,0,0,0,1,0,0,1},//数字9
};

void setup()//子程序只走一遍
{
  pinMode(2,OUTPUT);//定义2号引脚为输出模式
  pinMode(3,OUTPUT);//定义3号引脚为输出模式
  pinMode(4,OUTPUT);//定义4号引脚为输出模式
  pinMode(5,OUTPUT);//定义5号引脚为输出模式
  pinMode(6,OUTPUT);//定义6号引脚为输出模式
  pinMode(7,OUTPUT);//定义7号引脚为输出模式
  pinMode(8,OUTPUT);//定义8号引脚为输出模式
  pinMode(9,OUTPUT);//定义9号引脚为输出模式
}

void loop()//主程序一直循环
{
 for(int i=0;i<=9;i++)//利用for循环来逐个显示i的数值0~9
 {
   digitalWrite(2,num[i][0]);//2号引脚显示数组里第i个数列里面abcdefgh中的a的值,也就是0这个位的值
   digitalWrite(3,num[i][1]);//3号引脚显示数组里第i个数列里面abcdefgh中的b的值,也就是1这个位的值
   digitalWrite(4,num[i][2]);//4号引脚显示数组里第i个数列里面abcdefgh中的c的值,也就是2这个位的值
   digitalWrite(5,num[i][3]);//5号引脚显示数组里第i个数列里面abcdefgh中的d的值,也就是3这个位的值
   digitalWrite(6,num[i][4]);//6号引脚显示数组里第i个数列里面abcdefgh中的e的值,也就是4这个位的值
   digitalWrite(7,num[i][5]);//7号引脚显示数组里第i个数列里面abcdefgh中的f的值,也就是5这个位的值
   digitalWrite(8,num[i][6]);//8号引脚显示数组里第i个数列里面abcdefgh中的g的值,也就是6这个位的值
   digitalWrite(9,num[i][7]);//9号引脚显示数组里第i个数列里面abcdefgh中的h的值,也就是7这个位的值
   delay(1000);//延时一秒
 }
}

结果显示出来的数字就是这样的!!!(这里我就截图啦,没有展示全部显示的画面!)

 二位数码管的显示

其实当你看懂一位数码管的程序控制之后,二位数码管也就不难啦!因为二位数码管的控制就是在一位数码管的程序上面进行了相应修改!重头戏开始了!

上图是我在网上找到的二位数码管共阳极的电路图!能看明白的哈!它的原理就是把两个一位数码管结合在一块,电路接在一起了!同时大家可以发现,它的共阳极公共端就变成了两个。

为什么要把两个数码管接在一块呢?其实是为了节省单片机的引脚占用!你想想看,一位数码管里面abcdefgh+公共端就要9个引脚了,对吧,如果再来一个数码管,不就要占用2*9=18个引脚了嘛!所以人们想到了这个办法,把它们俩接在一块儿!这样二位数码管就只要用到10个引脚了!节省下来的引脚你爱干嘛就干嘛!

我当时也是这样去认识二位数码管的,当时我就想,引脚是省下来了,那我该怎么编程呢?哈哈,难住了!我想让二位数码管以十进制的方式满十进一,这样二位数码管两个显示就不一样了!我在测试的时候就出现了下面的情况:

要么就是两个都显示一样的数字;要么一个不显示,一个显示;要么乱显示!都不正常!

那我是怎么解决的呢?看下图

 

 哎!我可以这样显示,先显示十位,然后显示个位!或者先显示个位,再显示十位!(其实个、十位的显示,就是公共端的切换,哪一个公共端有电,哪一个数码管就亮)这样总该可以了吧!但是一个问题又来了,如果我缓慢切换就会感觉很奇怪,要快速个、十位之间切换才行,也就是说个位和十位之间的切换要让人眼捕捉不到它俩在切换,看起来好像同时在显示一样(有点像分身因为你速度太快,感觉有好几个你在做不同的事情一样),实则是两者切换过快导致的效果(这里有一个专有名词:人眼暂留现象),还有一个问题,我该如何让它互换显示的同时又能够把十位和个位的数字进行变化呢?

也就是说我的主程序要实现4个功能:

1、快速切换十位、个位的显示

2、十位数字的变化

3、个位数字的变化

4、个位满十,十位就加一

咱们先一个个的来——1、快速切换十位、个位的显示

先看看程序吧!(切换十位、个位的显示——慢速)你可以看到这个程序里面我多加了两个子程序,分别是十位和个位的显示子程序!相应的我又加了g、s来分别表示个位和十位的变量的值!在引脚定义里面,我又加了个位和十位公共端设置为OUTPUT(输出模式)的程序!这样两者就可以相互切换了!

/*建立数组num
num[10][8]其中[10]表示在num数组里面有0~9共10个数列,
[8]表示每一个数列里面有8个位,每一位的数字都不一样,
0代表低电平,1代表高电平,我用的数码管是共阳的,所以只有当低电平时,
数码管对应的灯会亮
*/
int num[10][8]={
{0,0,0,0,0,0,1,1},//数字0
{1,0,0,1,1,1,1,1},//数字1
{0,0,1,0,0,1,0,1},//数字2
{0,0,0,0,1,1,0,1},//数字3
{1,0,0,1,1,0,0,1},//数字4
{0,1,0,0,1,0,0,1},//数字5
{0,1,0,0,0,0,0,1},//数字6
{0,0,0,1,1,1,1,1},//数字7
{0,0,0,0,0,0,0,1},//数字8
{0,0,0,0,1,0,0,1},//数字9
};

int g = 0;//定义g为个位变量的值初始化变量为0
int s = 0;//定义s为十位变量的值初始化变量为0

void setup()//子程序只走一遍
{
  pinMode(10,OUTPUT);//定义2号引脚为输出模式,用来控制十位公共端供电
  pinMode(11,OUTPUT);//定义2号引脚为输出模式,用来控制个位公共端供电
  
  
  pinMode(2,OUTPUT);//定义2号引脚为输出模式
  pinMode(3,OUTPUT);//定义3号引脚为输出模式
  pinMode(4,OUTPUT);//定义4号引脚为输出模式
  pinMode(5,OUTPUT);//定义5号引脚为输出模式
  pinMode(6,OUTPUT);//定义6号引脚为输出模式
  pinMode(7,OUTPUT);//定义7号引脚为输出模式
  pinMode(8,OUTPUT);//定义8号引脚为输出模式
  pinMode(9,OUTPUT);//定义9号引脚为输出模式
}

void shi()//十位显示的子程序
{
   digitalWrite(10,HIGH);//十位公共端通电
   digitalWrite(11,low);//个位公共端断电
   digitalWrite(2,num[s][0]);//2号引脚显示数组里第s个数列里面abcdefgh中的a的值,也就是0这个位的值
   digitalWrite(3,num[s][1]);//3号引脚显示数组里第s个数列里面abcdefgh中的b的值,也就是1这个位的值
   digitalWrite(4,num[s][2]);//4号引脚显示数组里第s个数列里面abcdefgh中的c的值,也就是2这个位的值
   digitalWrite(5,num[s][3]);//5号引脚显示数组里第s个数列里面abcdefgh中的d的值,也就是3这个位的值
   digitalWrite(6,num[s][4]);//6号引脚显示数组里第s个数列里面abcdefgh中的e的值,也就是4这个位的值
   digitalWrite(7,num[s][5]);//7号引脚显示数组里第s个数列里面abcdefgh中的f的值,也就是5这个位的值
   digitalWrite(8,num[s][6]);//8号引脚显示数组里第s个数列里面abcdefgh中的g的值,也就是6这个位的值
   digitalWrite(9,num[s][7]);//9号引脚显示数组里第s个数列里面abcdefgh中的h的值,也就是7这个位的值
   delay(1000);//延时1秒
}

void ge()//个位显示的子程序
{
   digitalWrite(11,HIGH);//个位公共端通电
   digitalWrite(10,low);//十位公共端断电
   digitalWrite(2,num[g][0]);//2号引脚显示数组里第g个数列里面abcdefgh中的a的值,也就是0这个位的值
   digitalWrite(3,num[g][1]);//3号引脚显示数组里第g个数列里面abcdefgh中的b的值,也就是1这个位的值
   digitalWrite(4,num[g][2]);//4号引脚显示数组里第g个数列里面abcdefgh中的c的值,也就是2这个位的值
   digitalWrite(5,num[g][3]);//5号引脚显示数组里第g个数列里面abcdefgh中的d的值,也就是3这个位的值
   digitalWrite(6,num[g][4]);//6号引脚显示数组里第g个数列里面abcdefgh中的e的值,也就是4这个位的值
   digitalWrite(7,num[g][5]);//7号引脚显示数组里第g个数列里面abcdefgh中的f的值,也就是5这个位的值
   digitalWrite(8,num[g][6]);//8号引脚显示数组里第g个数列里面abcdefgh中的g的值,也就是6这个位的值
   digitalWrite(9,num[g][7]);//9号引脚显示数组里第g个数列里面abcdefgh中的h的值,也就是7这个位的值
   delay(1000);//延时1秒
}

void loop()//主程序一直循环
{
  ge();//调用个位子程序显示
  shi();//调用十位子程序显示
}  

看看效果吧!

数码管个、十位慢速切换显示

从视频中我们可以看到,个位和十位的显示效果,如果我让这个二位数码管这样显示那肯定是行不通的,因为我们在市面上可以看到,没有一个多位数码管时钟是以这样的方式显示的!所以我们要加快这个二位数码管两者之间切换的速度,来达到我们人眼看不出它在切换的效果!相信你一定想到了,就是更改两者之间的延时!!!!

下面是我把延时由1000ms到500ms再到300ms最后到10ms的显示效果视频,我们一起来看一下效果!

个、十位快速显示测试

效果还是很明显的!发现当两者都为10毫秒的显示时长时,人眼就已经捕捉不到它俩在切换了!这样也就达到了我们想要的效果!

接下来要实现以下功能!

2、十位数字的变化

3、个位数字的变化

4、个位满十,十位就加一

其实剩下这三个功能相互联系的,当个位一个个加上去满十进位以后(个位的变化),十位就会发生变化,我们把之前那个程序里面的g这个个位变量每1秒就自加1,上面我们有讲到个位和十位都是显示10毫秒后就切换到另一个去显示,那么十位和个位我都加了10毫秒,也就是说当个位和十位都显示完一共用时20毫秒,那么1秒里面一共有50个20毫秒,那我就再定义一个变量来记录这个20毫秒显示的次数,当次数达到50次时,也就是说20*50=1000毫秒=1秒时,g这个个位变量就加1!然后当g=10的时候,s这个十位变量就自加1!g清零从新开始自加!往复循环就可以实现二位数码管的动态显示了,来看看程序吧!

完整版程序\/\/\/\/\/\/\/

/*建立数组num
num[10][8]其中[10]表示在num数组里面有0~9共10个数列,
[8]表示每一个数列里面有8个位,每一位的数字都不一样,
0代表低电平,1代表高电平,我用的数码管是共阳的,所以只有当低电平时,
数码管对应的灯会亮
*/
int num[10][8]={
{0,0,0,0,0,0,1,1},//数字0
{1,0,0,1,1,1,1,1},//数字1
{0,0,1,0,0,1,0,1},//数字2
{0,0,0,0,1,1,0,1},//数字3
{1,0,0,1,1,0,0,1},//数字4
{0,1,0,0,1,0,0,1},//数字5
{0,1,0,0,0,0,0,1},//数字6
{0,0,0,1,1,1,1,1},//数字7
{0,0,0,0,0,0,0,1},//数字8
{0,0,0,0,1,0,0,1},//数字9
};

int g = 0;//定义g为个位变量的值初始化变量为0
int s = 0;//定义s为十位变量的值初始化变量为0
int c = 0;//定义次数变量初始化为0

void setup()//子程序只走一遍
{
  pinMode(10,OUTPUT);//定义2号引脚为输出模式,用来控制十位公共端供电
  pinMode(11,OUTPUT);//定义2号引脚为输出模式,用来控制个位公共端供电
  
  
  pinMode(2,OUTPUT);//定义2号引脚为输出模式
  pinMode(3,OUTPUT);//定义3号引脚为输出模式
  pinMode(4,OUTPUT);//定义4号引脚为输出模式
  pinMode(5,OUTPUT);//定义5号引脚为输出模式
  pinMode(6,OUTPUT);//定义6号引脚为输出模式
  pinMode(7,OUTPUT);//定义7号引脚为输出模式
  pinMode(8,OUTPUT);//定义8号引脚为输出模式
  pinMode(9,OUTPUT);//定义9号引脚为输出模式
}

void shi()//十位显示的子程序
{
   digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
   digitalWrite(2,num[s][0]);//2号引脚显示数组里第s个数列里面abcdefgh中的a的值,也就是0这个位的值
   digitalWrite(3,num[s][1]);//3号引脚显示数组里第s个数列里面abcdefgh中的b的值,也就是1这个位的值
   digitalWrite(4,num[s][2]);//4号引脚显示数组里第s个数列里面abcdefgh中的c的值,也就是2这个位的值
   digitalWrite(5,num[s][3]);//5号引脚显示数组里第s个数列里面abcdefgh中的d的值,也就是3这个位的值
   digitalWrite(6,num[s][4]);//6号引脚显示数组里第s个数列里面abcdefgh中的e的值,也就是4这个位的值
   digitalWrite(7,num[s][5]);//7号引脚显示数组里第s个数列里面abcdefgh中的f的值,也就是5这个位的值
   digitalWrite(8,num[s][6]);//8号引脚显示数组里第s个数列里面abcdefgh中的g的值,也就是6这个位的值
   digitalWrite(9,num[s][7]);//9号引脚显示数组里第s个数列里面abcdefgh中的h的值,也就是7这个位的值
   delay(10);//延时10/1000秒
}

void ge()//个位显示的子程序
{
   digitalWrite(10,LOW);//个位公共端通电
   digitalWrite(11,HIGH);
   digitalWrite(2,num[g][0]);//2号引脚显示数组里第g个数列里面abcdefgh中的a的值,也就是0这个位的值
   digitalWrite(3,num[g][1]);//3号引脚显示数组里第g个数列里面abcdefgh中的b的值,也就是1这个位的值
   digitalWrite(4,num[g][2]);//4号引脚显示数组里第g个数列里面abcdefgh中的c的值,也就是2这个位的值
   digitalWrite(5,num[g][3]);//5号引脚显示数组里第g个数列里面abcdefgh中的d的值,也就是3这个位的值
   digitalWrite(6,num[g][4]);//6号引脚显示数组里第g个数列里面abcdefgh中的e的值,也就是4这个位的值
   digitalWrite(7,num[g][5]);//7号引脚显示数组里第g个数列里面abcdefgh中的f的值,也就是5这个位的值
   digitalWrite(8,num[g][6]);//8号引脚显示数组里第g个数列里面abcdefgh中的g的值,也就是6这个位的值
   digitalWrite(9,num[g][7]);//9号引脚显示数组里第g个数列里面abcdefgh中的h的值,也就是7这个位的值
   delay(10);//延时10/1000秒
}

void panc()//判断次数的子程序
{
  if(c==50)//当次数满足50次也就是满足1秒的时候
  {
    g++;//个位加1
    c=0;//记录的次数清零
  }
}

void pang()//判断个位的子程序
{
  if(g==10)//当个位等于10时
  {
    s++;//十位加1
    g=0;//个位清零
  }  
}

void pans()//判断十位的子程序
{
  if(s==10)//当十位等于10的时候,因为时二位数码管,在往上就没有数可以显示了
  {
    g=0;//所以个位清零
    s=0;//十位清零
    c=0;//次数清零
  }  
}

void loop()//主程序一直循环
{
  ge();//调用个位子程序显示
  shi();//调用十位子程序显示
  c++;//次数自加
  panc();//影响个位的子程序
  pang();//影响十位的子程序
  pans();//从零开始重新计时
}  

程序看起来还是挺多的,如果你看明白了,可以自己去试着将程序简化,如果你有更好控制二位数码管的想法,我们也可以一起交流,或者使用中断程序去实现!下面来看看视频效果!!!

二位数码管的动态显示

如果文章里涉及的一些文字有什么问题,也希望大家提出来!

物联沃分享整理
物联沃-IOTWORD物联网 » 使用Arduino控制两位数码管实现动态显示(不需要中断)

发表评论