Arduino UNO 利用3个IO口 + TM1638+驱动8位数码管显示+24个独立按键

Arduino UNO 利用3个IO口 + TM1638+驱动8位数码管显示+24个独立按键


✨这几天没干什么事情,专门研究TM1638按键扫描功能。在之前使用TM1638作为数码管单独驱动显示,还是很顺利的,看到还自带按键扫描功能,这个非常不错,可以省掉3X8的矩阵键盘,虽然不一定能使用的上,差不多能把这个芯片的功能基本都榨干了,因为是使用的共阴数码管驱动,所以会有SEG8-SEG10的3个引脚没有使用到。

  • 🔖本实例编程没有使用库,后面有时间将移植到Keil开发的工程环境当中。
  • 🎉本程序仿真过程当中还存在bug,运行一段时间过后,数码管会不显示,有可能是软件自身的bug问题,但是不排除代码跑飞的问题,还有待完善的地方:按键需要按下一定时间才有数码管才有响应。
    在这里插入图片描述

⛳仿真说明

在这里插入图片描述- 程序编译没有问题
在这里插入图片描述

  • 加载文件
    在这里插入图片描述

  • 关于数码管驱动内容我就不做介绍了,主要讲解按键扫描功能。

✅键扫描和按键复用功能

  • 按键扫描矩阵为3×8bit,也就是3X8矩阵,一共24个独立按键,这个按键矩阵键盘需要注意一点就是K1、K2、K3,每条线上的按键1-8,9-16,17-24,三排按键只能单独触发,不支持组合按键。做应该也是可以做,需要深究算法,运算量会比较大,不打算去深究组合键了,有点复杂。24个独立按键基本上可以满足一般的需求了。值占用了单片机3个IO口。
  • 安装官方资料搭建3X8矩阵即可
    在这里插入图片描述
  • 按键扫描数据存储地址
    在这里插入图片描述

上面的这个数据存储地址关系,看了我好久,都没有搞明白,后只能通过调试,打印出每一位的具体值来进行解析。

  • Proteus里面将电路绘制出来。
    在这里插入图片描述
  • 扫描完K1,K2,K3读取到的是BYTE1—BYTE4字节,下面我将每个按键在按下后,读取的4个字节的数据都列出来,就一目了然了。
    1.分别按下K1这一排的按键,所记录的数据如下:
    在这里插入图片描述
  1. 从第一排按键数据,就可以看清楚后面的规律了,第二排K2的下的独立按键数据:

在这里插入图片描述
3. 按下第三排K3,独立按键的数据:
在这里插入图片描述

  • 粘贴一张合并的图片来看就能看出规律了

在这里插入图片描述

根据以上图表数据写代码就非常轻松了。

📝驱动代码

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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/\*
//TM1638
VCC → 5V
GND → GND
STROBE\_TM-----4
CLOCK\_TM------6
DIO\_TM -------7
\*/

#define DATA\_COMMAND 0X40
#define DISP\_COMMAND 0x80
#define ADDR\_COMMAND 0XC0
#define K1S1 1
#define K1S2 2
#define K1S3 3
#define K1S4 4
#define K1S5 5
#define K1S6 6
#define K1S7 7
#define K1S8 8

#define K2S1 9
#define K2S2 10
#define K2S3 11
#define K2S4 12
#define K2S5 13
#define K2S6 14
#define K2S7 15
#define K2S8 16

#define K3S1 17
#define K3S2 18
#define K3S3 19
#define K3S4 20
#define K3S5 21
#define K3S6 22
#define K3S7 23
#define K3S8 24

//TM1638模块引脚定义
int DIO = 7;
int CLK = 6;
int STB = 4; //这里定义了那三个脚
//共阴数码管显示代码
unsigned char tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
0x40,0x00
};
unsigned char num[8]; //各个数码管显示的值
void setup ()
{
Serial.begin(9600);
pinMode(STB,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(DIO,OUTPUT); //让三个脚都是输出状态
}
void loop()
{
unsigned char i,num;
init\_TM1638(); //初始化TM1638
for(i=0;i<8;i++)
Write\_DATA(i<<1,tab[16]); //初始化寄存器
while(1)
{
i=Read\_key(); //读按键值
Write\_DATA(3<<1,tab[i/10]);
Write\_DATA(4<<1,tab[i%10]);
Serial.println(i);
delay(1000);
}
}

void TM1638\_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
pinMode(DIO,OUTPUT);
for(i=0;i<8;i++)
{
digitalWrite(CLK,LOW);
if(DATA&0X01)
digitalWrite(DIO,HIGH);
else
digitalWrite(DIO,LOW);
DATA>>=1;
digitalWrite(CLK,HIGH);
}
}
unsigned char TM1638\_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;;
pinMode(DIO,INPUT);//设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
digitalWrite(CLK,LOW);
if(digitalRead(DIO)==HIGH)
temp|=0x80;
digitalWrite(CLK,HIGH);

}
return temp;
}
void Write\_COM(unsigned char cmd) //发送命令字
{
digitalWrite(STB,LOW);
TM1638\_Write(cmd);
digitalWrite(STB,HIGH);
}
unsigned char Read\_key(void)
{
unsigned char i,key_val[4],key=0;
digitalWrite(STB,LOW);
TM1638\_Write(0x42); //读键扫数据 命令
delayMicroseconds(2);//至少延时1微秒以上
for(i=0;i<4;i++)
{
key_val[i] =TM1638\_Read();
// Serial.print(key\_val[i]);Serial.print('-');
}
digitalWrite(STB,HIGH);// 拉高片选线,读键值结束.
if(key_val[0]!=0) //按键在KS1或KS2
{
switch(key_val[0])
{
case 1:
key=K3S1;
break;
case 2:
key=K2S1;
break;
case 4:
key=K1S1;
break;
case 16:
key=K3S5;
break;
case 32:
key=K2S5;
break;
case 64:
key=K1S5;
break;
}
}
else if(key_val[1]!=0) //按键在KS3或KS4
{
switch(key_val[1])
{
case 1:
key=K3S2;
break;
case 2:
key=K2S2;
break;
case 4:
key=K1S2;
break;
case 16:
key=K3S6;
break;
case 32:
key=K2S6;
break;
case 64:
key=K1S6;
break;
case 255:
init\_TM1638();
break;
}
}
else if(key_val[2]!=0) //按键在KS5或KS6
{
switch(key_val[2])
{
case 1:
key=K3S3;
break;
case 2:
key=K2S3;
break;
case 4:
key=K1S3;
break;
case 16:
key=K3S7;
break;
case 32:
key=K2S7;
break;
case 64:
key=K1S7;
break;
case 255:
init\_TM1638();
break;
}
}
else if(key_val[3]!=0) //按键在KS7或KS8
{
switch(key_val[3])
{
case 1:
key=K3S4;
break;
case 2:
key=K2S4;
break;
case 4:
key=K1S4;
break;
case 16:
key=K3S8;
break;
case 32:
key=K2S8;
break;
case 64:
key=K1S8;
break;
case 255:
init\_TM1638();
break;
}
}

return key;

}
void Write\_DATA(unsigned char add,unsigned char DATA)//指定地址写入数据
{
Write\_COM(0x44);//想固定地址写数据命令
digitalWrite(STB,LOW);
TM1638\_Write(0xc0|add);
TM1638\_Write(DATA);
digitalWrite(STB,HIGH);
}
void Write\_allLED(unsigned char LED_flag) //控制全部LED函数,LED\_flag表示各个LED状态
{
unsigned char i;
for(i=0;i<8;i++)
{
if(LED_flag&(1<<i))
Write\_DATA(2\*i+1,1);
else
Write\_DATA(2\*i+1,0);
}
}

//TM1638初始化函数
void init\_TM1638(void)
{
unsigned char i;
Write\_COM(0x8b); //亮度 (0x88-0x8f)8级亮度可调
Write\_COM(0x40); //采用地址自动加1
digitalWrite(STB,LOW); //
TM1638\_Write(0xc0); //设置起始地址
for(i=0;i<16;i++) //传送16个字节的数据
TM1638\_Write(0x00);
digitalWrite(STB,HIGH);
}

📚Proteus仿真和程序代码

1
2
3
链接:https://pan.baidu.com/s/1Xlom7glu\_01iIk7L4eHdvQ 
提取码:vefl

📗代码优化(更新时间:2022年4月30日00:07:35)

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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/\*
//TM1638
VCC → 5V
GND → GND
STROBE\_TM-----4
CLOCK\_TM------6
DIO\_TM -------7
\*/

#define DATA\_COMMAND 0X40
#define DISP\_COMMAND 0x80
#define ADDR\_COMMAND 0XC0
#define K1S1 1
#define K1S2 2
#define K1S3 3
#define K1S4 4
#define K1S5 5
#define K1S6 6
#define K1S7 7
#define K1S8 8

#define K2S1 9
#define K2S2 10
#define K2S3 11
#define K2S4 12
#define K2S5 13
#define K2S6 14
#define K2S7 15
#define K2S8 16

#define K3S1 17
#define K3S2 18
#define K3S3 19
#define K3S4 20
#define K3S5 21
#define K3S6 22
#define K3S7 23
#define K3S8 24

//TM1638模块引脚定义
int DIO = 7;
int CLK = 6;
int STB = 4; //这里定义了那三个脚
//共阴数码管显示代码
unsigned char tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
0x40,0x00
};
unsigned char num[8]; //各个数码管显示的值
void setup ()
{

Serial.begin(9600);
pinMode(STB,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(DIO,OUTPUT); //让三个脚都是输出状态

}
void loop()
{
unsigned char j,num;
static unsigned char i=0;
init\_TM1638(); //初始化TM1638
for(j=0;j<8;j++)
Write\_DATA(j<<1,tab[16]); //初始化寄存器
while(1){
num=Read\_key(); //读按键值
if(num >0){
if(num != i){
i=num;
Write\_DATA(3<<1,tab[i/10]);
Write\_DATA(4<<1,tab[i%10]);
Serial.println(i);
delay(210); //这个延时需要控制在200左右,太少时仿真出现闪屏,过大按键响应慢
}
}
if (num ==0) {
Write\_DATA(3<<1,tab[i/10]);
Write\_DATA(4<<1,tab[i%10]);
// Serial.println(i);
delay(210); //这个延时需要控制在200左右,太少时仿真出现闪屏,过大按键响应慢
}
}
}

void TM1638\_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
pinMode(DIO,OUTPUT);
for(i=0;i<8;i++)
{
digitalWrite(CLK,LOW);
if(DATA&0X01)
digitalWrite(DIO,HIGH);
else
digitalWrite(DIO,LOW);
DATA>>=1;
digitalWrite(CLK,HIGH);
}
}
unsigned char TM1638\_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;;
pinMode(DIO,INPUT);//设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
digitalWrite(CLK,LOW);
if(digitalRead(DIO)==HIGH)
temp|=0x80;
digitalWrite(CLK,HIGH);

}
return temp;
}
void Write\_COM(unsigned char cmd) //发送命令字
{
digitalWrite(STB,LOW);
TM1638\_Write(cmd);
digitalWrite(STB,HIGH);
}
unsigned char Read\_key(void)
{
unsigned char i,key_val[4],key=0;
digitalWrite(STB,LOW);
TM1638\_Write(0x42); //读键扫数据 命令
delayMicroseconds(2);//至少延时1微秒以上
for(i=0;i<4;i++)
{
key_val[i] =TM1638\_Read();
// Serial.print(key\_val[i]);Serial.print('-');
}
digitalWrite(STB,HIGH);// 拉高片选线,读键值结束.
if(key_val[0] >0) //按键在KS1或KS2
{
switch(key_val[0])
{
case 1:
key=K3S1;
break;
case 2:
key=K2S1;
break;
case 4:
key=K1S1;
break;
case 16:
key=K3S5;
break;
case 32:
key=K2S5;
break;
case 64:
key=K1S5;
break;
}
}
else if(key_val[1]>0) //按键在KS3或KS4
{
switch(key_val[1])
{
case 1:
key=K3S2;
break;
case 2:
key=K2S2;
break;
case 4:
key=K1S2;
break;
case 16:
key=K3S6;
break;
case 32:
key=K2S6;
break;
case 64:
key=K1S6;
break;
case 255:
init\_TM1638();
break;
}
}
else if(key_val[2]>0) //按键在KS5或KS6
{
switch(key_val[2])
{
case 1:
key=K3S3;
break;
case 2:
key=K2S3;
break;
case 4:
key=K1S3;
break;
case 16:
key=K3S7;
break;
case 32:
key=K2S7;
break;
case 64:
key=K1S7;
break;
case 255:
init\_TM1638();
break;
}
}
else if(key_val[3]>0) //按键在KS7或KS8
{
switch(key_val[3])
{
case 1:
key=K3S4;
break;
case 2:
key=K2S4;
break;
case 4:
key=K1S4;
break;
case 16:
key=K3S8;
break;
case 32:
key=K2S8;
break;
case 64:
key=K1S8;
break;
case 255:
init\_TM1638();
break;
}
}

return key;

}
void Write\_DATA(unsigned char add,unsigned char DATA)//指定地址写入数据
{
Write\_COM(0x44);//想固定地址写数据命令
digitalWrite(STB,LOW);
TM1638\_Write(0xc0|add);
TM1638\_Write(DATA);
digitalWrite(STB,HIGH);
}
void Write\_allLED(unsigned char LED_flag) //控制全部LED函数,LED\_flag表示各个LED状态
{
unsigned char i;
for(i=0;i<8;i++)
{
if(LED_flag&(1<<i))
Write\_DATA(2\*i+1,1);
else
Write\_DATA(2\*i+1,0);
}
}

//TM1638初始化函数
void init\_TM1638(void)
{
unsigned char i;
Write\_COM(0x8b); //亮度 (0x88-0x8f)8级亮度可调
Write\_COM(0x40); //采用地址自动加1
digitalWrite(STB,LOW); //
TM1638\_Write(0xc0); //设置起始地址
for(i=0;i<16;i++) //传送16个字节的数据
TM1638\_Write(0x00);
digitalWrite(STB,HIGH);
}

📖实物验证更新(2023-3-19)

  • 实物验证和仿真代码效果还是存在差异,根据实际效果,调整了按键扫描映射值,为在实际烧录测试发现,真正的按键扫描映射的值每一横排8个按键的数字和按键码对应的值不对,重新做了映射调整。已经验证的程序如下:
    在这里插入图片描述
  • 📍TM1638自制模块:https://oshwhub.com/perseverance51/tm1638-an-jian-shuo-ma-guan-mu
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/\*
//TM1638
VCC → 5V
GND → GND
STROBE\_TM-----4
CLOCK\_TM------6
DIO\_TM -------7
\*/

#define DATA\_COMMAND 0X40
#define DISP\_COMMAND 0x80
#define ADDR\_COMMAND 0XC0
#define K1S1 1
#define K1S2 2
#define K1S3 3
#define K1S4 4
#define K1S5 5
#define K1S6 6
#define K1S7 7
#define K1S8 8

#define K2S1 9
#define K2S2 10
#define K2S3 11
#define K2S4 12
#define K2S5 13
#define K2S6 14
#define K2S7 15
#define K2S8 16

#define K3S1 17
#define K3S2 18
#define K3S3 19
#define K3S4 20
#define K3S5 21
#define K3S6 22
#define K3S7 23
#define K3S8 24

unsigned char now_value = 0;

//TM1638模块引脚定义
int DIO = 8;
int CLK = 7;
int STB = 4; //这里定义了那三个脚
//共阴数码管显示代码
unsigned char tab[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,
0x40, 0x00
};
unsigned char num[8]; //各个数码管显示的值
void setup ()
{
Serial.begin(9600);
pinMode(STB, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(DIO, OUTPUT); //让三个脚都是输出状态
}
void loop()
{
unsigned char num;
init\_TM1638(); //初始化TM1638
for (num = 0; num < 8; num++)
Write\_DATA(num << 1, tab[16]); //初始化寄存器
while (1)
{
num = Read\_key(); //读按键值
if (num != 0)
{
if (num != now_value)
{
now_value = num;
Serial.println(now_value);
}
}
Write\_DATA(3 << 1, tab[now_value / 10]);
Write\_DATA(4 << 1, tab[now_value % 10]);

}
}

void TM1638\_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
pinMode(DIO, OUTPUT);
for (i = 0; i < 8; i++)
{
digitalWrite(CLK, LOW);
if (DATA & 0X01)
digitalWrite(DIO, HIGH);
else
digitalWrite(DIO, LOW);
DATA >>= 1;
digitalWrite(CLK, HIGH);
}
}
unsigned char TM1638\_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp = 0;;
pinMode(DIO, INPUT); //设置为输入
for (i = 0; i < 8; i++)
{
temp >>= 1;
digitalWrite(CLK, LOW);
if (digitalRead(DIO) == HIGH)
temp |= 0x80;
digitalWrite(CLK, HIGH);

}
return temp;
}
void Write\_COM(unsigned char cmd) //发送命令字
{
digitalWrite(STB, LOW);
TM1638\_Write(cmd);
digitalWrite(STB, HIGH);
}
unsigned char Read\_key(void)
{
unsigned char i, key_val[4], key = 0;
digitalWrite(STB, LOW);
TM1638\_Write(0x42); //读键扫数据 命令
delayMicroseconds(2);//至少延时1微秒以上
for (i = 0; i < 4; i++)
{
key_val[i] = TM1638\_Read();
// Serial.print(key\_val[i]);Serial.print('-');
}
digitalWrite(STB, HIGH); // 拉高片选线,读键值结束.
if (key_val[0] != 0) //按键在KS1或KS2
{
switch (key_val[0])
{
case 1:
key = K3S8;
break;
case 2:
key = K2S8;
break;
case 4:
key = K1S1;
break;
case 16:
key = K3S7 ;
break;
case 32:
key = K2S7 ;
break;
case 64:
key = K1S2;
break;
}
}
else if (key_val[1] != 0) //按键在KS3或KS4
{
switch (key_val[1])
{
case 1:
key = K3S6 ;
break;
case 2:
key = K2S6 ;
break;
case 4:
key = K1S3;//K1S3
break;
case 16:
key = K3S5 ;
break;
case 32:
key = K2S5 ;
break;
case 64:
key = K1S4;
break;
case 255:
init\_TM1638();
break;
}
}
else if (key_val[2] != 0) //按键在KS5或KS6
{
switch (key_val[2])
{
case 1:
key =K3S4;
break;
case 2:
key = K2S4 ;
break;
case 4:
key = K1S5;
break;
case 16:
key = K3S3 ;
break;
case 32:
key = K2S3 ;
break;
case 64:
key = K1S6;
break;
case 255:
init\_TM1638();
break;
}
}
else if (key_val[3] != 0) //按键在KS7或KS8
{
switch (key_val[3])
{
case 1:
key = K3S2 ;
break;
case 2:
key =K2S2 ;
break;
case 4:
key = K1S7 ;
break;
case 16:
key = K3S1 ;
break;
case 32:
key = K2S1;
break;
case 64:
key = K1S8;
break;
case 255:
init\_TM1638();
break;
}
}

return key;

}
void Write\_DATA(unsigned char add, unsigned char DATA) //指定地址写入数据
{
Write\_COM(0x44);//想固定地址写数据命令
digitalWrite(STB, LOW);
TM1638\_Write(0xc0 | add);
TM1638\_Write(DATA);
digitalWrite(STB, HIGH);
}
void Write\_allLED(unsigned char LED_flag) //控制全部LED函数,LED\_flag表示各个LED状态
{
unsigned char i;
for (i = 0; i < 8; i++)
{
if (LED_flag & (1 << i))
Write\_DATA(2 \* i + 1, 1);
else
Write\_DATA(2 \* i + 1, 0);
}
}

//TM1638初始化函数
void init\_TM1638(void)
{
unsigned char i;
Write\_COM(0x8b); //亮度 (0x88-0x8f)8级亮度可调
Write\_COM(0x40); //采用地址自动加1
digitalWrite(STB, LOW); //
TM1638\_Write(0xc0); //设置起始地址
for (i = 0; i < 16; i++) //传送16个字节的数据
TM1638\_Write(0x00);
digitalWrite(STB, HIGH);
}



涓滴之水终可磨损大石, 不是由于它力量大, 而是由于昼夜不舍的 滴坠。 只有勤奋不懈的努力才能够获得那些技巧, 因此, 我们可以确切地 说: 说: 不积跬步, 无以致千里。 —— 贝多芬