3. 数码管静态显示:共阴/共阳数码管原理、段码表计算、单个数码管显示数字0-9

好,咱们今天来聊聊数码管。这东西在嵌入式开发里太常见了,电梯楼层计数器、电子钟、温度显示器……到处都有它的身影。我个人觉得,数码管是入门嵌入式显示最好的起点——它简单、直观,而且能让你真正理解“显示”这件事的本质。

3.1 共阴与共阳:两种“脾气”的数码管

先说说数码管的结构。一个数码管,说白了就是8个LED灯排成“8”字形,外加一个小数点。这8个LED的阳极或阴极被连在一起,就分出了两种类型。

共阴极数码管:所有LED的阴极连在一起,接GND。你要点亮哪一段,就给对应的阳极送高电平。说白了,就是“高电平点亮”。

共阳极数码管:所有LED的阳极连在一起,接VCC。你要点亮哪一段,就给对应的阴极送低电平。也就是“低电平点亮”。

嗯,这里要注意:千万别搞混了。我在项目中遇到过一位同事,把共阳的段码表用在共阴的数码管上,结果显示出来的数字全是乱的,排查了半天才发现是极性搞反了。你想想看,这多耽误事。

我曾经踩过的坑: 买数码管时,一定要确认是共阴还是共阳。有些商家标得不清楚,我建议你拿到手后,用万用表二极管档测一下:红表笔接某一段引脚,黑表笔接公共端,亮了就是共阴;反过来亮了就是共阳。

3.2 段码表计算:从“画图”到“编码”

段码表,说白了就是数字和LED段之间的对应关系。咱们先给数码管的8段编个号:从a到g,再加上小数点dp。通常的排列顺序是:a在上横,b在右上,c在右下,d在下横,e在左下,f在左上,g在中间横,dp在右下角。

怎么算段码?我教你一个笨办法——画图。拿张纸,画个“8”,然后对着数字0到9,把要亮的段涂黑,不亮的留白。然后按顺序写出二进制位,再转成十六进制。

举个例子,显示数字“0”:需要点亮a、b、c、d、e、f这6段,g和dp不亮。假设我们用的共阴极,高电平点亮。那么二进制就是:dp g f e d c b a = 0 0 1 1 1 1 1 1 = 0x3F。

如果是共阳极,那就反过来:低电平点亮,所以二进制是:1 1 0 0 0 0 0 0 = 0xC0。

你看,其实就是一个取反的关系。我个人习惯把共阴和共阳的段码表都算好,存成两个数组,用的时候直接查表,省得每次现算。

核心公式:
共阴段码 = 点亮段对应位写1,不亮写0,然后转十六进制。
共阳段码 = 对共阴段码按位取反。

3.3 0-9的段码表:直接拿来用

下面是我常用的段码表,共阴和共阳都有。你直接复制到代码里就行。

数字 共阴段码 (十六进制) 共阳段码 (十六进制) 点亮段
0 0x3F 0xC0 a,b,c,d,e,f
1 0x06 0xF9 b,c
2 0x5B 0xA4 a,b,d,e,g
3 0x4F 0xB0 a,b,c,d,g
4 0x66 0x99 b,c,f,g
5 0x6D 0x92 a,c,d,f,g
6 0x7D 0x82 a,c,d,e,f,g
7 0x07 0xF8 a,b,c
8 0x7F 0x80 a,b,c,d,e,f,g
9 0x6F 0x90 a,b,c,d,f,g
小技巧: 如果你记不住这些值,可以写个小程序自动生成。我当年就是用Excel的BIN2HEX函数算的,省了不少事。

3.4 单个数码管显示:代码实战

理论说完了,咱们来点实际的。下面是一个用51单片机控制共阴数码管显示0-9的例子。硬件连接很简单:数码管的a-g和dp分别接P0口的P0.0到P0.7,公共端接GND。

#include <reg51.h>

// 共阴数码管段码表
unsigned char code segCode[] = {
    0x3F, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F  // 9
};

void delay(unsigned int ms) {
    unsigned int i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 120; j++);
}

void main() {
    unsigned char i;
    while(1) {
        for(i = 0; i < 10; i++) {
            P0 = segCode[i];  // 输出段码
            delay(1000);      // 延时1秒
        }
    }
}

这段代码很简单:循环0到9,每次把对应的段码送到P0口,数码管就显示对应的数字了。延时1秒,方便你观察。

如果是共阳数码管,只需要把段码表换成共阳的那一套,然后注意公共端接VCC就行。代码逻辑完全一样。

注意: 实际项目中,数码管驱动电流可能不够,尤其是多个数码管同时亮的时候。我建议加个三极管或ULN2003来驱动,别直接怼在IO口上,容易烧引脚。

3.5 避坑指南:我踩过的几个雷

做这个实验,有几个地方容易出问题。我把自己踩过的坑列出来,你注意避开。

  • 段码顺序搞反: 我刚开始做的时候,把a和dp的位置搞反了,结果显示的数字全是镜像的。后来我养成了一个习惯:画个图,标好每个引脚对应的段,再写代码。
  • 共阴共阳搞混: 这个前面说过了,买回来先测一下,别偷懒。
  • 限流电阻忘加: 数码管每个段都需要串一个电阻,一般220Ω到470Ω。不加的话,LED电流太大,要么烧数码管,要么烧IO口。我见过有人直接接,结果数码管冒烟了……
  • 小数点处理: 段码表里一般把dp位放在最高位。如果你不需要小数点,记得把dp位置0,否则会多一个亮点。

好了,这一节的内容就到这儿。你先把单个数码管调通,能显示0到9,后面咱们再讲多位数码管的动态扫描。记住,基础打牢了,后面才走得稳。