0x03 使用数码管显示数字(静态)

【目标】

  • 使用数码管显示数字

【所需素材】

  • 数码管一只 x 1
  • 270Ω左右电阻 x 8
图1 4位7段数码管

【基本原理】

数码管分不同位数的,一位到四位都有,这篇虽然用的是一个四位的数码管,但实现的是点亮一位数字。

接下来的几篇内容,将会通过驱动数码管,来熟悉下稍微复杂些的驱动原理。

我们来看一下一个四位数码管的原理图:

图2 4位7段数码管原理图

每位数字由7个LED组成,大多数市售数码管每位数字包含一个小数点,所以其实是8段,7段数码管只是习惯性的叫法。有的数码管还包含斜线等,可以拼成一些英文字母之类的,原理是一样的。

为方便区分我们把数码管上每段LED进行编号,如图2右上角所示。A-G加DP,一共8个LED。

但是8个LED用16个PIN显然太浪费了,所以把8个LED的正极或负极并联起来,8个LED共用一根正极或者负极,这样一位数字就是9个PIN。

共用一根正极的叫做共阳,共用一根负极的叫共阴。共阳极或共阴极指的就是图2中最下面的电路图中的DIG1-4,每一位数字都有一个共阴(阳)

通过控制数据PIN的高低电平,来实现点亮不同段的效果。

【硬件连接】

上图为共阴数码管链接,公共阴极接GND。

如果是共阳数码管,公共阳极接3.3 VCC。

树莓派数码管备注
211E段,串联270Ω电阻
222D段,串联270Ω电阻
233DP段,串联270Ω电阻
244C段,串联270Ω电阻
255G段,串联270Ω电阻
297B段,串联270Ω电阻
2810F段,串联270Ω电阻
2711A段,串联270Ω电阻
GND12Dig1,第一位数字共阴极

【程序实现】

#include <wiringPi.h>
#include <stdbool.h>

// 连接定义
#define SEG_A 27
#define SEG_B 29
#define SEG_C 24
#define SEG_D 22
#define SEG_E 21
#define SEG_F 28
#define SEG_G 25
#define SEG_DP 23

/*
 * 为了用8个LED来显示数字,我们定义一个数组来表示每个数字需要点亮哪几段。
 * 8段其实就是8个0或1的状态,比如为了显示数字0,我们需要点亮A、B、C、D、E、F这几段,关闭G段
 * 按A-G的顺序排列起来可以得到一个二进制数1111110,还有一个小数点我们放到最后一位D[0],
 * 这里我们把小数点位固定为0,后面显示的时候根据是否需要小数点,来置此位的状态。数字1-9以此类推。
*/
int matrix[10] = {
    0b11111100, // 0
    0b01100000, // 1
    0b11011010, // 2
    0b11110010, // 3
    0b01100110, // 4
    0b10110110, // 5
    0b10111110, // 6
    0b11100100, // 7
    0b11111110, // 8
    0b11110110 // 9
};

/*
 * 同时,我们还要把各段对应的PIN告诉程序
 * 按A-G-DP的顺序排列,方便我们程序处理
*/
int seg[8] = {
    SEG_A,
    SEG_B,
    SEG_C,
    SEG_D,
    SEG_E,
    SEG_F,
    SEG_G,
    SEG_DP
};

/*
 * 显示指定的数字
 * @param dig 要显示的数字 0-9
 * @param showDP 是否显示小数点 TRUE/FALSE
*/
void showDig(short num,bool showDP)
{
/*
 * 通过GPIO和硬件通信会用到大量的位操作,
 * 本函数的逻辑是8位(1字节)数据传输比较常用的操作方法,
 * 如果这段函数理解起来困难的话,后续的程序读起来也会很吃力。
*/
    short i, tmp;
    tmp = matrix[num];
    if(showDP)
        tmp |= 1;  // 将是否显示小数点的状态置与tmp[0]位

/*
 * 下面的for循环每循环一次,将tmp向左移一位,将每一位都位移到tmp[7],
 * 和0x80(二进制为10000000)进行位与运算比较,来判断1或0。
 * 如果是从低位开始发送,将0x80改成1,tmp<<=1改成tmp>>=1即可。
*/
    for (i=0;i<8;i++)
    {
        if((tmp&0x80) == 0x80)  // 将位移后的数据和0x80进行位与运算,如果得到的还是0x80,那么比较位tmp[7]为1,否则为0
        {  // 当相应位为1时,我们认为此位需要点亮
            digitalWrite(seg[i],HIGH);  // 共阴数码管为高电平点亮,共阳数码管为低电平点亮
        } else {
            digitalWrite(seg[i],LOW);
        }
        tmp<<=1;  // 左移一位
    }
}

int main(void)
{
    short num,i;

    wiringPiSetup();

    for(i=0;i<8;i++)
    {
        pinMode(seg[i], OUTPUT);
    }

    for(num=0;num<10;num++)
    {
        showDig(num,TRUE);
        delay(500);
    }

    return 0;
}

【实现效果】

发表评论

电子邮件地址不会被公开。 必填项已用*标注