文章目录
  1. 1. 最终效果
  2. 2. 硬件
  3. 3. 原理说明
  4. 4. 硬件连接
  5. 5. 代码
  6. 6. 性能改善
  7. 7. 源代码下载

这次我们用树莓派的GPIO口驱动数码管来显示数字,进而制作一个简单的电子钟,通过按钮来切换显示时间或日期。

最终效果

树莓派GPIO入门05-驱动数码管显示数字

硬件

  • 数码管一只。因为需要显示日期时间所以需要能显示4个数字的数码管,也称4位数码管。淘宝买1块多钱一只。注意数码管有共阳和共阴的。我这里使用的是共阳的。至于区别,下面的原理说明里会详细解释。
  • 杜邦线若干。
  • 面包板一块。
  • 按钮1只。

原理说明

  • 标准的数码管从显示内容上分7段和8段数码管两种。8段比7段多一个右下角的小数点。还有一些其他特殊的如可以显示米字形的数码管不在本文讨论范围内,其实原理都是一样的。
  • 8段数码管由8个发光二极管组成,其中7个用于组成数字,1个用于显示小数点。每一根的编号如下图的右上角所示(A-G,DP)。
    4位共阳8段数码管原理图
  • 数码管从电源极性上分共阳和共阴两种。解释一下,如果数码管上每一个独立的发光二极管都单独引出两根引脚,一根接正极(阳)一根接负极(阴),那么一个8段数码管就需要16根引脚来控制。但其实这8段数码管完全可以在内部共用一个阳级,只控制各段发光二极管的阴级联通即可,这就是共阳。反之亦然,叫共阴。共阳或共阴的每个8段数码管只需要引出9个引脚,1个阳(阴)级接到树莓派vcc(gnd)上,另外8个分别连到gpio口上,通过控制io口高低电平即可显示所需数字。比如一只共阳数码管想显示数字1,看LED编号图可知需要点亮b段和c段,其他全灭。那么连到共阳端引脚的io口输出高电平,连到引脚b、c的io口输出低电平,连到引脚a、d、e、f、g、dp的io口均输出高电平即可。写成代码就是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # 定义各段发光二极管对应的GPIO口
    LED_A = 26
    LED_B = 19
    LED_C = 13
    LED_D = 6
    LED_E = 5
    LED_F = 11
    LED_G = 9
    LED_DP = 10

    # 定义数码管共阳极对应的GPIO口
    VCC = 12

    # 避免闪烁,在输出数字字形信号前先拉低共阳端,关闭显示
    RPi.GPIO.output(VCC, False)

    # 输出数字1的字形信号
    RPi.GPIO.output(LED_A, True)
    RPi.GPIO.output(LED_B, False)
    RPi.GPIO.output(LED_C, False)
    RPi.GPIO.output(LED_D, True)
    RPi.GPIO.output(LED_E, True)
    RPi.GPIO.output(LED_F, True)
    RPi.GPIO.output(LED_G, True)
    RPi.GPIO.output(LED_DP, True)

    # 最后拉高共阳段,显示数字
    RPi.GPIO.output(VCC, True)
  • 本文使用的数码管是8段共阳4位(4个数字)数码管,型号是F3461BH。上面说了共阳数码管每个数字需要9个引脚来控制,那么4个数字就需要36个引脚吗?显然不现实,树莓派的io口也完全不够用。这就引出另一个概念,静态显示和动态扫描显示。

  • 静态显示,就是前面说的每一个数字需要占用8个io口,每多一个数字就需要额外的8个io口,如果数字位数不多,io口够用的话,这样做完全没问题。实际应用中往往需要显示多个数字,io口基本上是不够用的。这就需要动态扫描显示了。下面摘一段百度百科关于动态扫描显示的说明(稍有改动):

    数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划”a,b,c,d,e,f,g,dp”的同名端连在一起引出8个引脚,每个数字再单独引出共阳(阴)端,这样总引脚数就只要8 + 数字个数即可,本文使用的8段4位数码管正是引出了12个引脚。至于哪个引脚对应哪一段,哪几个引脚分别对应各数字的共阳(阴)端,就需要商家提供电路图了。当然也可以自己慢慢试,这不在本文讨论范围,大家可以自己摸索。当树莓派输出8个段信号时,所有数码管都会接收到相同的信号,但究竟是哪个数码管会显示出字形,取决于这个数码管对应的共阳(阴)极(后统称位选端)有无导通。所以我们只要将需要显示的数码管的位选端选通,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的位选端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。

  • 综上,比如我们想要在4位共阳数码管上显示1234这4个数字,要做的就是:

    1. 避免闪烁,在输出数字字形信号前先拉低所有4个共阳极,关闭所有显示。
    2. 拉低1号数码管的共阳极,关闭显示。
    3. 输出1号数码管上希望显示的数字字形信号。
    4. 只拉高1号数码管的共阳极,让1号数码管显示上面设置好的数字字形。
    5. 延时一段时间(1ms左右)
    6. 拉低1号数码管的共阳极,关闭显示。
    7. 输出2号数码管上希望显示的数字字形信号。
    8. 只拉高2号数码管的共阳极,让2号数码管显示上面设置好的数字字形。
    9. 延时一段时间(1ms左右)
    10. 拉低2号数码管的共阳极,关闭显示。
    11. 输出3号数码管上希望显示的数字字形信号。
    12. 只拉高3号数码管的共阳极,让3号数码管显示上面设置好的数字字形。
    13. 延时一段时间(1ms左右)
    14. 拉低3号数码管的共阳极,关闭显示。
    15. 输出4号数码管上希望显示的数字字形信号。
    16. 只拉高4号数码管的共阳极,让4号数码管显示上面设置好的数字字形。
    17. 延时一段时间(1ms左右)
    18. 返回step2,循环执行。
  • 取得日期和时间的方法不是本文的重点,大家自己看代码。

硬件连接

硬件连接图

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#!/usr/bin/env python
# encoding: utf-8

import RPi.GPIO
import time

# 定义单个数码管各段led对应的GPIO口
LED_A = 26
LED_B = 19
LED_C = 13
LED_D = 6
LED_E = 5
LED_F = 11
LED_G = 9
LED_DP = 10

# 定义1到4号数码管阳极对应的GPIO口
DIGIT1 = 12
DIGIT2 = 16
DIGIT3 = 20
DIGIT4 = 21

# 定义按钮输入的GPIO口
btn = 27

RPi.GPIO.setmode(RPi.GPIO.BCM)

RPi.GPIO.setup(LED_A, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_B, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_C, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_D, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_E, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_F, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_G, RPi.GPIO.OUT)
RPi.GPIO.setup(LED_DP, RPi.GPIO.OUT)
RPi.GPIO.setup(DIGIT1, RPi.GPIO.OUT)
RPi.GPIO.setup(DIGIT2, RPi.GPIO.OUT)
RPi.GPIO.setup(DIGIT3, RPi.GPIO.OUT)
RPi.GPIO.setup(DIGIT4, RPi.GPIO.OUT)

RPi.GPIO.output(DIGIT1, True)
RPi.GPIO.output(DIGIT2, True)
RPi.GPIO.output(DIGIT3, True)
RPi.GPIO.output(DIGIT4, True)

RPi.GPIO.setup(btn, RPi.GPIO.IN, pull_up_down=RPi.GPIO.PUD_UP)

# 指定no(1-4)号数码管显示数字num(0-9),第三个参数是显示不显示小数点(true/false
def showDigit(no, num, showDotPoint):
# 先将正极拉低,关掉显示
RPi.GPIO.output(DIGIT1, False)
RPi.GPIO.output(DIGIT2, False)
RPi.GPIO.output(DIGIT3, False)
RPi.GPIO.output(DIGIT4, False)

if (num == 0) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, False)
RPi.GPIO.output(LED_F, False)
RPi.GPIO.output(LED_G, True)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 1) :
RPi.GPIO.output(LED_A, True)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, True)
RPi.GPIO.output(LED_E, True)
RPi.GPIO.output(LED_F, True)
RPi.GPIO.output(LED_G, True)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 2) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, True)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, False)
RPi.GPIO.output(LED_F, True)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 3) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, True)
RPi.GPIO.output(LED_F, True)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 4) :
RPi.GPIO.output(LED_A, True)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, True)
RPi.GPIO.output(LED_E, True)
RPi.GPIO.output(LED_F, False)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 5) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, True)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, True)
RPi.GPIO.output(LED_F, False)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 6) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, True)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, False)
RPi.GPIO.output(LED_F, False)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 7) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, True)
RPi.GPIO.output(LED_E, True)
RPi.GPIO.output(LED_F, True)
RPi.GPIO.output(LED_G, True)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 8) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, False)
RPi.GPIO.output(LED_F, False)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)
elif (num == 9) :
RPi.GPIO.output(LED_A, False)
RPi.GPIO.output(LED_B, False)
RPi.GPIO.output(LED_C, False)
RPi.GPIO.output(LED_D, False)
RPi.GPIO.output(LED_E, True)
RPi.GPIO.output(LED_F, False)
RPi.GPIO.output(LED_G, False)
RPi.GPIO.output(LED_DP, not showDotPoint)

if (no == 1) :
RPi.GPIO.output(DIGIT1, True)
elif (no == 2) :
RPi.GPIO.output(DIGIT2, True)
elif (no == 3) :
RPi.GPIO.output(DIGIT3, True)
elif (no == 4) :
RPi.GPIO.output(DIGIT4, True)

try:
t=0.005
while True:
# 按钮按下时显示日期,否则显示时间
# 为了区别左右的数字,让第二个数码管的小数点显示出来
#(本来应该是一个冒号,我们这个数码管没有,就用小数点代替了)
if (RPi.GPIO.input(btn) == 1):
time.sleep(t)
showDigit(1, int(time.strftime("%H",time.localtime(time.time()))) / 10, False)
time.sleep(t)
showDigit(2, int(time.strftime("%H",time.localtime(time.time()))) % 10, True)
time.sleep(t)
showDigit(3, int(time.strftime("%M",time.localtime(time.time()))) / 10, False)
time.sleep(t)
showDigit(4, int(time.strftime("%M",time.localtime(time.time()))) % 10, False)
else:
time.sleep(t)
showDigit(1, int(time.strftime("%m",time.localtime(time.time()))) / 10, False)
time.sleep(t)
showDigit(2, int(time.strftime("%m",time.localtime(time.time()))) % 10, True)
time.sleep(t)
showDigit(3, int(time.strftime("%d",time.localtime(time.time()))) / 10, False)
time.sleep(t)
showDigit(4, int(time.strftime("%d",time.localtime(time.time()))) % 10, False)

except KeyboardInterrupt:
pass

# 最后清理GPIO口(不做也可以,建议每次程序结束时清理一下,好习惯)
RPi.GPIO.cleanup()

性能改善

当你照着这篇文章成功在数码管上显示出数字后,你可能会郁闷的发现数字有一点点闪烁,显示的不是非常稳定,这种情况在树莓派1代上更明显。

  • python库对gpio口不停操作时对cpu的占用率很高,而一旦cpu的占用率一高,就不能保证延时函数的准确性,而在动态扫描时延时的不准确会导致数码管的亮度不稳定,比如第一只数码管显示了2ms而第二只显示了1ms的话,第一只数码管的亮度就会略高于第二只数码管,而参差不齐的延时最后就表现为数字显示有闪烁的感觉。
  • python库本身翻转gpio口的效率就不高,有兴趣可以参照这个页面,有各种语言各种库对gpio的操作速度比较。比较结果是c的wiringPi库完胜其他方式。其实python库已经是表现不错的了,但还是被c甩了N条街。python翻转io口的频率在70kHz左右,而wiringPi则可以达到4MHz!这个已经是数量级上的差距了。
  • 抱着试一试的心情,我用c语言的wiringPi库把上面这个程序重写了一遍,代码是这个样子的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    #include <wiringPi.h>
    #include <unistd.h>
    #include <time.h>

    // 定义单个数码管各段led对应的GPIO口
    // 使用命令 "gpio readall" 来获取当前pi版本对应的各引脚的wiringPi和BCM的编号
    // 再本程序中应该使用wiringPi编号
    // 我的pi2 Mode B执行结果如下:(wPi列就是wiringPi编号)
    // 之前Python版本的代码使用的是BCM编号,所以在不改变硬件接线的情况下,我们需要把原来BCM编号改成对应的wiringPi编号。
    /*
    +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+
    | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
    +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
    | | | 3.3v | | | 1 || 2 | | | 5v | | |
    | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5V | | |
    | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | |
    | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 |
    | | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 |
    | 17 | 0 | GPIO. 0 | OUT | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 |
    | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | |
    | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
    | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 |
    | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | |
    | 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
    | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 |
    | | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 |
    | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
    | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | |
    | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 |
    | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | |
    | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
    | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 |
    | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 |
    +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
    | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
    +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+
    */


    #define LED_A 25 //BCM:26
    #define LED_B 24 //BCM:19
    #define LED_C 23 //BCM:13
    #define LED_D 22 //BCM:6
    #define LED_E 21 //BCM:5
    #define LED_F 14 //BCM:11
    #define LED_G 13 //BCM:9
    #define LED_DP 12 //BCM:10

    // 定义1到4号数码管阳极对应的GPIO口
    #define DIGIT1 26 //BCM:12
    #define DIGIT2 27 //BCM:16
    #define DIGIT3 28 //BCM:20
    #define DIGIT4 29 //BCM:21

    // 定义按钮输入的GPIO口
    #define btn 2 //BCM:27

    #define FALSE 0
    #define TRUE 1

    #define t 5000 //usleep延时长度(单位um微秒,1000um=1ms,1000ms=1s)

    // 指定no(1-4)号数码管显示数字num(0-9),第三个参数是显示不显示小数点(1/0)
    void showDigit(int no, int num, int showDotPoint);

    time_t now;
    struct tm *tm_now;

    int main (void) {
    wiringPiSetup () ;

    pinMode (LED_A, OUTPUT) ;
    pinMode (LED_B, OUTPUT) ;
    pinMode (LED_C, OUTPUT) ;
    pinMode (LED_D, OUTPUT) ;
    pinMode (LED_E, OUTPUT) ;
    pinMode (LED_F, OUTPUT) ;
    pinMode (LED_G, OUTPUT) ;
    pinMode (LED_DP, OUTPUT) ;

    pinMode (DIGIT1, OUTPUT) ;
    pinMode (DIGIT2, OUTPUT) ;
    pinMode (DIGIT3, OUTPUT) ;
    pinMode (DIGIT4, OUTPUT) ;

    pinMode (btn, INPUT) ;
    pullUpDnControl (btn, PUD_UP) ;

    digitalWrite (DIGIT1, HIGH) ;
    digitalWrite (DIGIT2, HIGH) ;
    digitalWrite (DIGIT3, HIGH) ;
    digitalWrite (DIGIT4, HIGH) ;

    for (; ; )
    {
    time(&now);
    tm_now=localtime(&now);

    // 按钮按下时显示日期,否则显示时间
    // 为了区别左右的数字,让第二个数码管的小数点显示出来
    //(本来应该是一个冒号,我们这个数码管没有,就用小数点代替了)
    if (digitalRead(btn) == HIGH) {
    usleep(t);
    showDigit(1, tm_now->tm_hour / 10, FALSE);
    usleep(t);
    showDigit(2, tm_now->tm_hour % 10, TRUE);
    usleep(t);
    showDigit(3, tm_now->tm_min / 10, FALSE);
    usleep(t);
    showDigit(4, tm_now->tm_min % 10, FALSE);
    } else {
    // 取得的月份和日期都是从0开始的,所以显示前需要加1
    usleep(t);
    showDigit(1, (tm_now->tm_mon+1) / 10, FALSE);
    usleep(t);
    showDigit(2, (tm_now->tm_mon+1) % 10, TRUE);
    usleep(t);
    showDigit(3, (tm_now->tm_mday+1) / 10, FALSE);
    usleep(t);
    showDigit(4, (tm_now->tm_mday+1) % 10, FALSE);
    }
    }
    return 0 ;
    }

    void showDigit(int no, int num, int showDotPoint) {
    // 先将正极拉低,关掉显示
    digitalWrite (DIGIT1, LOW) ;
    digitalWrite (DIGIT2, LOW) ;
    digitalWrite (DIGIT3, LOW) ;
    digitalWrite (DIGIT4, LOW) ;

    if (num == 0) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, LOW) ;
    digitalWrite (LED_F, LOW) ;
    digitalWrite (LED_G, HIGH) ;
    } else if (num == 1) {
    digitalWrite (LED_A, HIGH) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, HIGH) ;
    digitalWrite (LED_E, HIGH) ;
    digitalWrite (LED_F, HIGH) ;
    digitalWrite (LED_G, HIGH) ;
    } else if (num == 2) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, HIGH) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, LOW) ;
    digitalWrite (LED_F, HIGH) ;
    digitalWrite (LED_G, LOW) ;
    } else if (num == 3) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, HIGH) ;
    digitalWrite (LED_F, HIGH) ;
    digitalWrite (LED_G, LOW) ;
    } else if (num == 4) {
    digitalWrite (LED_A, HIGH) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, HIGH) ;
    digitalWrite (LED_E, HIGH) ;
    digitalWrite (LED_F, LOW) ;
    digitalWrite (LED_G, LOW) ;
    } else if (num == 5) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, HIGH) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, HIGH) ;
    digitalWrite (LED_F, LOW) ;
    digitalWrite (LED_G, LOW) ;
    } else if (num == 6) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, HIGH) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, LOW) ;
    digitalWrite (LED_F, LOW) ;
    digitalWrite (LED_G, LOW) ;
    } else if (num == 7) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, HIGH) ;
    digitalWrite (LED_E, HIGH) ;
    digitalWrite (LED_F, HIGH) ;
    digitalWrite (LED_G, HIGH) ;
    } else if (num == 8) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, LOW) ;
    digitalWrite (LED_F, LOW) ;
    digitalWrite (LED_G, LOW) ;
    } else if (num == 9) {
    digitalWrite (LED_A, LOW) ;
    digitalWrite (LED_B, LOW) ;
    digitalWrite (LED_C, LOW) ;
    digitalWrite (LED_D, LOW) ;
    digitalWrite (LED_E, HIGH) ;
    digitalWrite (LED_F, LOW) ;
    digitalWrite (LED_G, LOW) ;
    }

    if (showDotPoint == 1) {
    digitalWrite (LED_DP, LOW) ;
    } else {
    digitalWrite (LED_DP, HIGH) ;
    }

    if (no == 1) {
    digitalWrite (DIGIT1, HIGH) ;
    } else if (no == 2) {
    digitalWrite (DIGIT2, HIGH) ;
    } else if (no == 3) {
    digitalWrite (DIGIT3, HIGH) ;
    } else if (no == 4) {
    digitalWrite (DIGIT4, HIGH) ;
    }
    }
  • c的wiringPi库的安装和代码的编译执行方法请自行百度。

  • c语言测试结果是显示稳定了很多,但仍然有一点不稳定不仔细观察基本看不出来了。这个应该跟我代码的效率有关,逻辑应该还可以精简节省cpu资源。这个以后再试了。我们这个系列主要是让大家了解各种基本外设传感器的原理和使用方法。用c语言也只是做一点延伸,以后的教程还是以python为主。

源代码下载

点击下载Python源码
点击下载c源码

文章目录
  1. 1. 最终效果
  2. 2. 硬件
  3. 3. 原理说明
  4. 4. 硬件连接
  5. 5. 代码
  6. 6. 性能改善
  7. 7. 源代码下载