Arduino驱动4位数码管

Arduino驱动4位数码管

  • 昨天看到高中同学吐槽说被Arduino驱动数码管搞的满头大汗,不禁让我手痒痒。

  • 突然想到自己好像也有4位数码管,翻了翻,果然有,于是就拿来玩了。

  • 不过,好像驱动这个还是挺简单的吧!(确实挺简单的,只花了一个小时就封装好了函数)

参考网站:

基本原理

静态(只能保存单个数码管)

1.锁存器介绍
锁存器(Latch)是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制器与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。锁存器是利用电平控制数据的输入,它包括不带使能控制的锁存器和带使能控制的锁存器。

所谓锁存器,就是输出端的状态不会随输入端的状态变化而变化,仅在有锁存信号时输入的状态被保存到输出,直到下一个锁存信号到来时才改变。

2.138译码器(74HC138)介绍
74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL)系列。74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。
74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。

原理图:

这里写图片描述

这里写图片描述

动态显示

动态驱动显示就是使各个数码管轮流受控显示。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快态显示是一样的,能够节省大量的I/O端口,而且功耗更低。
一般的实例效果如下:

数码管引脚及接线

注意在共阳或共阴极引脚处要串联一个220欧姆(不要太大,不然灯不太亮)的电阻,再与Arduino的IO口相连,防止电流过大。

img

引脚定义

#define D_a 2
#define D_b 3
#define D_c 4
#define D_d 5
#define D_e 6
#define D_f 7
#define D_g 8
#define D_h 9

#define COM1 10
#define COM2 11
#define COM3 12
#define COM4 13

注意引脚要连续,一方面接线方便,一方面方便写代码

保存显示的数组

0表示亮灯,1表示熄灯,因为我的数码管为共阴极的,如果数码管不同的话,代码也可能不同。

bool型,减少内存。

后面如果有小数点则表示字母。

bool Digital_tube_number[18][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
  {0,0,0,1,0,0,0,0},//A10
  {0,0,0,0,0,0,0,0},//B11
  {0,1,1,0,0,0,1,0},//C12
  {0,0,0,0,0,0,1,0},//D13
  {0,1,1,0,0,0,0,0},//E14
  {0,1,1,1,0,0,0,0},//F15
  {0,1,0,0,0,0,1,0},//G16
  {1,1,1,1,1,1,1,0},//小数点.
};

后来新增:

bool Digital_tube_number[37][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
  {0,0,0,1,0,0,0,1},//A10
  {0,0,0,0,0,0,0,0},//B11
  {0,1,1,0,0,0,1,0},//C12
  {0,0,0,0,0,0,1,0},//D13
  {0,1,1,0,0,0,0,0},//E14
  {0,1,1,1,0,0,0,0},//F15
  {0,1,0,0,0,0,1,0},//G16
  {1,0,0,1,0,0,0,0},//H17
  {1,1,1,1,0,0,1,0},//I18
  {1,0,0,0,1,1,1,0},//J19
  {1,1,0,1,0,0,0,0},//K20
  {1,1,1,0,0,0,1,0},//L21
  {0,0,0,1,0,0,1,0},//M22
  {1,1,0,1,0,1,0,0},//N23
  {0,0,0,0,0,0,1,1},//O24
  {0,0,1,1,0,0,0,0},//P25
  {0,0,0,0,0,0,1,0},//Q26
  {0,0,0,1,0,0,0,0},//R27
  {0,1,0,0,1,0,0,0},//S28
  {0,1,1,1,0,0,1,0},//T29
  {1,0,0,0,0,0,1,1},//U30
  {1,0,0,0,0,0,1,0},//V31
  {1,1,1,1,1,1,0,0},//W32
  {1,1,1,1,1,1,0,0},//X33
  {1,1,1,1,1,1,0,0},//Y34
  {1,1,1,1,1,1,1,1},//不显示
  {1,1,1,1,1,1,1,0},//小数点36.
};

初始化

  for(int i=D_a;i<=D_h;i++){
    pinMode(i,OUTPUT);
  }
  for(int i=COM1;i<=COM4;i++){
    pinMode(i,OUTPUT);
  }

显示

单个管教及其显示

void Digital_tube_display(int com,int number)
{
  for(int i=COM1;i<=COM4;i++){
    digitalWrite(i,LOW);
  }
  switch(com){
    case 1:
      digitalWrite(COM1,HIGH);
      break;
    case 2:
      digitalWrite(COM2,HIGH);
      break;
    case 3:
      digitalWrite(COM3,HIGH);
      break;
    case 4:
      digitalWrite(COM4,HIGH);
      break;
  }
  for(int i=0;i<8;i++){
    digitalWrite(2+i,Digital_tube_number[number][i]);
  }
}

多个数码管同时亮(最多支持4个)

多个数码管可以同时亮,但是这样每个数码管只能显示相同的数字.

下例:最后全显示2。

  Digital_tube_display(1,5);
  delay(200);
  Digital_tube_display(2,14);
  delay(200);
  Digital_tube_display(3,1);
  delay(200);
  Digital_tube_display(4,2);//需要把Digital_tube_display里面的第一个循环(关闭所有COM)注释掉

另外一个例子:

void Digital_tube_display_sametime(int number)
{
  digitalWrite(COM1,HIGH);
  digitalWrite(COM2,HIGH);
  digitalWrite(COM3,HIGH);
  digitalWrite(COM4,HIGH);
  for(int i=0;i<8;i++){
    digitalWrite(2+i,Digital_tube_number[number][i]);
  }
}
//调用一下这个函数

动态显示

/* 动态显示
 * a数码管1显示,b数码管2显示,c数码管3显示,d数码管4显示,
 * time1视觉暂留最短时间(最短为6,time2动态时间
 */
void Digital_tube_dynamic_display(int a,int b,int c,int d,int time1,float time2)
{
  if(time1>6){
    time1 = 6;
  }
  for(int i=0;i<time2*250/time1;i++){
    Digital_tube_display(1,a);
    delay(time1);
    Digital_tube_display(2,b);
    delay(time1);
    Digital_tube_display(3,c);
    delay(time1);
    Digital_tube_display(4,d);
    delay(time1);
  }
}

动态调用实例:(1s改变一下)

  Digital_tube_dynamic_display(1,2,3,4,6,1);
  Digital_tube_dynamic_display(3,6,5,8,6,1);
  Digital_tube_dynamic_display(10,11,12,13,6,1);

全代码

#define D_a 2
#define D_b 3
#define D_c 4
#define D_d 5
#define D_e 6
#define D_f 7
#define D_g 8
#define D_h 9

#define COM1 10
#define COM2 11
#define COM3 12
#define COM4 13

bool Digital_tube_number[18][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
  {0,0,0,1,0,0,0,0},//A10
  {0,0,0,0,0,0,0,0},//B11
  {0,1,1,0,0,0,1,0},//C12
  {0,0,0,0,0,0,1,0},//D13
  {0,1,1,0,0,0,0,0},//E14
  {0,1,1,1,0,0,0,0},//F15
  {0,1,0,0,0,0,1,0},//G16
  {1,1,1,1,1,1,1,0},//小数点.
};

int delay_time = 2;

void setup() {
  // put your setup code here, to run once:
  for(int i=D_a;i<=D_h;i++){
    pinMode(i,OUTPUT);
  }
  for(int i=COM1;i<=COM4;i++){
    pinMode(i,OUTPUT);
  }
  Digital_tube_display_sametime(5);
}

void loop() {
  // put your main code here, to run repeatedly:
  /*Digital_tube_dynamic_display(1,2,3,4,6,1);
  Digital_tube_dynamic_display(3,6,5,8,6,1);
  Digital_tube_dynamic_display(10,11,12,13,6,1);*/
}

/* 动态显示
 * a数码管1显示,b数码管2显示,c数码管3显示,d数码管4显示,
 * time1视觉暂留最短时间,time2动态时间
 */
void Digital_tube_dynamic_display(int a,int b,int c,int d,int time1,float time2)
{
  if(time1>6){
    time1 = 6;
  }
  for(int i=0;i<time2*250/time1;i++){
    Digital_tube_display(1,a);
    delay(time1);
    Digital_tube_display(2,b);
    delay(time1);
    Digital_tube_display(3,c);
    delay(time1);
    Digital_tube_display(4,d);
    delay(time1);
  }
}
void Digital_tube_display_sametime(int number)
{
  digitalWrite(COM1,HIGH);
  digitalWrite(COM2,HIGH);
  digitalWrite(COM3,HIGH);
  digitalWrite(COM4,HIGH);
  for(int i=0;i<8;i++){
    digitalWrite(2+i,Digital_tube_number[number][i]);
  }
}

void Digital_tube_display(int com,int number)
{
  for(int i=COM1;i<=COM4;i++){
    digitalWrite(i,LOW);
  }
  switch(com){
    case 1:
      digitalWrite(COM1,HIGH);
      break;
    case 2:
      digitalWrite(COM2,HIGH);
      break;
    case 3:
      digitalWrite(COM3,HIGH);
      break;
    case 4:
      digitalWrite(COM4,HIGH);
      break;
  }
  for(int i=0;i<8;i++){
    digitalWrite(2+i,Digital_tube_number[number][i]);
  }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值