STM32F1与STM32CubeIDE编程实例-MAX7219驱动8位7段数码管(基于SPI)

MAX7219驱动8位7段数码管(基于SPI)

在前面的文章中,我们实现了纯GPIO方式通过MAX7219驱动8位7段数码管。由于MAX7219支持SPI、QSPI接口,最大支持10MHz的通信速率,因此可以通过SPI方式驱动MAX7219。在这里,将详细介绍如何实现MAX7219的SPI方式驱动。

在这里插入图片描述

在前面的文章中对MAX7219的驱动及使用做了详细的介绍,请参考:

1、MAX7219配置

开发环境搭建、系统时钟配置、调试配置及串口配置,请参考:

本次实例的MAX7219配置如下:

在这里插入图片描述

保存并生成代码。

2、MAX7219驱动实现

1)MAX7219驱动基本定义

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
/\*
\* max7219\_spi.h
\*
\* Created on: May 7, 2022
\* Author: jenson
\*/

#ifndef \_\_SPI\_MAX7219\_SPI\_H\_\_
#define \_\_SPI\_MAX7219\_SPI\_H\_\_

#include <stm32f1xx\_hal.h>
#include "main.h"
#include <stdio.h>
#include <stdbool.h>


#define MAX7219\_NOOP\_REGISTER 0x00
#define MAX7219\_DIGIT0\_REGISTER 0x01
#define MAX7219\_DIGIT1\_REGISTER 0x02
#define MAX7219\_DIGIT2\_REGISTER 0x03
#define MAX7219\_DIGIT3\_REGISTER 0x04
#define MAX7219\_DIGIT4\_REGISTER 0x05
#define MAX7219\_DIGIT5\_REGISTER 0x06
#define MAX7219\_DIGIT6\_REGISTER 0x07
#define MAX7219\_DIGIT7\_REGISTER 0x08

#define MAX7219\_DECODE\_MODE\_REGISTER 0x09
#define MAX7219\_INTENSITY\_REGISTER 0x0A
#define MAX7219\_SCAN\_LIMIT\_REGISTER 0x0B
#define MAX7219\_SHUTDOWN\_REGISTER 0x0C
#define MAX7219\_DISPLAY\_TEST\_REGISTER 0x0F

#define MAX7219\_INTENSITY\_MIN 0x00
#define MAX7219\_INTENSITY\_MAX 0x0F

#define MAX7219\_MAX\_DIAPLAY\_BUFFER\_LEN 32

typedef enum {
MAX7219_SCAN_DIGIT_0 = 0,
MAX7219_SCAN_DIGIT_0_1 = 1,
MAX7219_SCAN_DIGIT_0_2 = 2,
MAX7219_SCAN_DIGIT_0_3 = 3,
MAX7219_SCAN_DIGIT_0_4 = 4,
MAX7219_SCAN_DIGIT_0_5 = 5,
MAX7219_SCAN_DIGIT_0_6 = 6,
MAX7219_SCAN_DIGIT_0_7 = 7,
} max7219\_scan\_limit\_type\_t;

typedef enum {
MAX7219_NoDecode = 0,
MAX7219_DecodeFor0 = 1,
MAX7219_DecodeFor3_0 = 2,
MAX7219_DecodeFor7_0 = 3
} max7219\_decode\_mode\_t;

typedef enum {
MAX7219_OK = 0,
MAX7219_ERROR = 1,
MAX7219_UNSUPPORTED_CHAR = 2,
MAX7219_OUT_OF_RANGE = 3
} MAX7219_STATUS;

typedef struct {
uint16\_t id;
GPIO_TypeDef \*CS_GPIOx;
uint16\_t CS_Pin;
SPI_HandleTypeDef \*SPIx;
uint8\_t brightness;
uint8\_t \*display_buffer;
uint16\_t display_buffer_len;
uint8\_t digits;
} max7219\_t;

typedef enum {
MAX7219_ALIGN_RIGHT = 0, MAX7219_ALIGN_LEFT,
} max7219\_align\_t;

void max7219\_init(max7219\_t \*dev);
void max7219\_release(max7219\_t \*dev);

MAX7219_STATUS max7219\_set\_decode\_mode(max7219\_t \*dev,
max7219\_decode\_mode\_t mode);
void max7219\_set\_brightness(max7219\_t \*dev, uint8\_t level);

void max7219\_clear(max7219\_t \*dev);

void max7219\_turn\_on(max7219\_t \*dev);
void max7219\_turn\_off(max7219\_t \*dev);

void max7219\_test\_start(max7219\_t \*dev);
void max7219\_test\_stop(max7219\_t \*dev);

void max7219\_display\_digit\_at(max7219\_t \*dev, uint8\_t digit, uint8\_t data,
bool dot);

void max7219\_set\_display\_data(max7219\_t \*dev, const uint8\_t \*data);
void max7219\_display(max7219\_t \*dev, max7219\_align\_t align);

#endif /\* \_\_SPI\_MAX7219\_SPI\_H\_\_ \*/


2)MAX7219驱动辅助函数定义

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
/\*
\* max7219\_spi.c
\*
\* Created on: May 7, 2022
\* Author: jenson
\*/

#include "max7219\_spi.h"
#include <stdbool.h>
#include <stdio.h>
#include "shift\_out.h"
#if 1
static uint8\_t __display_buffer[MAX7219_MAX_DIAPLAY_BUFFER_LEN] = { 0x00 };
static const uint8\_t __s_max7219_digits[] = { 0x00, // Clear
0x7E, // 0
0x30, // 1
0x6D, // 2
0x79, // 3
0x33, // 4
0x5B, // 5
0x5F, // 6
0x70, // 7
0x7F, // 8
0x7B, // 9
0x77, // A
0x1F, // b
0x0D, // c
0x4E, // C
0x3D, // d
0x6F, // e
0x4F, // E
0x47, // F
0x1E, // h
0x37, // H
0x06, // I
0x38, // J
0x0E, // L
0x15, // n
0x1D, // o
0x67, // P
0x05, // r
// S - same as 5
0x1C, // u
0x3E, // U
0x3B, // y
// Z - same as 2
0x63, // \*
0x01, // -
};

void \_\_max7219\_cs\_low(max7219\_t \*dev);
void \_\_max7219\_cs\_high(max7219\_t \*dev);

void \_\_max7219\_write(max7219\_t \*dev, int8\_t reg_number, int8\_t data);

void \_\_max7219\_display\_mix(max7219\_t \*dev);

void \_\_max7219\_cs\_low(max7219\_t \*dev) {
HAL\_GPIO\_WritePin(dev->CS_GPIOx, dev->CS_Pin, GPIO_PIN_RESET);
}

void \_\_max7219\_cs\_high(max7219\_t \*dev) {
HAL\_GPIO\_WritePin(dev->CS_GPIOx, dev->CS_Pin, GPIO_PIN_SET);
}

void \_\_max7219\_write(max7219\_t \*dev, int8\_t reg_number, int8\_t data) {
uint8\_t message[2] = { 0 };
message[0] = reg_number;
message[1] = data;
\_\_max7219\_cs\_low(dev);
HAL\_SPI\_Transmit(dev->SPIx, (uint8\_t\*) message, 2, 100);
\_\_max7219\_cs\_high(dev);
}

3)MAX7219驱动定义实现

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
void max7219\_display\_digit\_at(max7219\_t \*dev, uint8\_t digit, uint8\_t data,
bool dot) {
uint8\_t value_to_send;

if (digit > dev->digits || digit < 0) {
return;
}
switch (data) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
value_to_send = __s_max7219_digits[data + 1];
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value_to_send = __s_max7219_digits[data - 47];
break;
case ' ':
value_to_send = __s_max7219_digits[0];
break;
case 'a':
case 'A':
value_to_send = __s_max7219_digits[11];
break;
case 'b':
case 'B':
value_to_send = __s_max7219_digits[12];
break;
case 'c':
value_to_send = __s_max7219_digits[13];
break;
case 'C':
value_to_send = __s_max7219_digits[14];
break;
case 'd':
case 'D':
value_to_send = __s_max7219_digits[15];
break;
case 'e':
value_to_send = __s_max7219_digits[16];
break;
case 'E':
value_to_send = __s_max7219_digits[17];
break;
case 'F':
case 'f':
value_to_send = __s_max7219_digits[18];
break;
case 'h':
value_to_send = __s_max7219_digits[19];
break;
case 'H':
value_to_send = __s_max7219_digits[20];
break;
case 'i':
case 'I':
value_to_send = __s_max7219_digits[21];
break;
case 'j':
case 'J':
value_to_send = __s_max7219_digits[22];
break;
case 'l':
case 'L':
value_to_send = __s_max7219_digits[23];
break;
case 'n':
case 'N':
value_to_send = __s_max7219_digits[24];
break;
case 'o':
case 'O':
value_to_send = __s_max7219_digits[25];
break;
case 'p':
case 'P':
value_to_send = __s_max7219_digits[26];
break;
case 'r':
case 'R':
value_to_send = __s_max7219_digits[27];
break;
case 's':
case 'S':
value_to_send = __s_max7219_digits[6];
break;
case 'u':
value_to_send = __s_max7219_digits[28];
break;
case 'U':
value_to_send = __s_max7219_digits[29];
break;
case 'y':
case 'Y':
value_to_send = __s_max7219_digits[30];
break;
case 'z':
case 'Z':
value_to_send = __s_max7219_digits[3];
break;
case '\*':
value_to_send = __s_max7219_digits[31];
break;
case '-':
value_to_send = __s_max7219_digits[32];
break;
default:
return;
break;
}
value_to_send |= dot ? 0x80 : 0x00;

\_\_max7219\_write(dev, digit, value_to_send);
}

void max7219\_init(max7219\_t \*dev) {

dev->display_buffer = __display_buffer;
dev->display_buffer_len = 16;
\_\_max7219\_write(dev, MAX7219_SCAN_LIMIT_REGISTER, MAX7219_SCAN_DIGIT_0_7);
\_\_max7219\_write(dev, MAX7219_DECODE_MODE_REGISTER, MAX7219_NoDecode);
max7219\_turn\_on(dev);
max7219\_test\_stop(dev);
max7219\_clear(dev);
max7219\_set\_brightness(dev, dev->brightness);
}

void max7219\_release(max7219\_t \*dev) {

}

MAX7219_STATUS max7219\_set\_decode\_mode(max7219\_t \*dev,
max7219\_decode\_mode\_t mode) {
if (mode > 4) {
return MAX7219_ERROR;
}
\_\_max7219\_write(dev, MAX7219_DECODE_MODE_REGISTER, mode);
return MAX7219_OK;
}

void max7219\_clear(max7219\_t \*dev) {
for (uint8\_t i = 1; i <= dev->digits; i++) {
\_\_max7219\_write(dev, i, 0x00);
}
memset(dev->display_buffer, ' ', MAX7219_MAX_DIAPLAY_BUFFER_LEN);
}

void max7219\_turn\_on(max7219\_t \*dev) {
\_\_max7219\_write(dev, MAX7219_SHUTDOWN_REGISTER, 0x01);
}

void max7219\_turn\_off(max7219\_t \*dev) {
\_\_max7219\_write(dev, MAX7219_SHUTDOWN_REGISTER, 0x00);
}

void max7219\_test\_start(max7219\_t \*dev) {
\_\_max7219\_write(dev, MAX7219_DISPLAY_TEST_REGISTER, 0x01);
}

void max7219\_test\_stop(max7219\_t \*dev) {
\_\_max7219\_write(dev, MAX7219_DISPLAY_TEST_REGISTER, 0x00);
}

void max7219\_set\_brightness(max7219\_t \*dev, uint8\_t level) {
dev->brightness = level & 0x0F;
\_\_max7219\_write(dev, MAX7219_INTENSITY_REGISTER, dev->brightness);
}

void max7219\_set\_display\_data(max7219\_t \*dev, const uint8\_t \*data) {
size\_t len = strlen(data);
if (len > 0 && len < MAX7219_MAX_DIAPLAY_BUFFER_LEN) {
memset(dev->display_buffer, ' ', MAX7219_MAX_DIAPLAY_BUFFER_LEN);
dev->display_buffer_len = len;
memcpy(dev->display_buffer, data, len);
}
}

void max7219\_display(max7219\_t \*dev, max7219\_align\_t align) {
uint8\_t buffer_len = dev->display_buffer_len;
uint8\_t offset = 0;
uint8\_t dot = 0;
uint8\_t commas = 0;

for (uint8\_t i = 0; i < buffer_len; i++) {
if (dev->display_buffer[i] == '.' || dev->display_buffer[i] == ',') {
commas++;
}
}

switch (align) {
case MAX7219_ALIGN_RIGHT:
offset = dev->digits - buffer_len + commas;
offset %= dev->digits;
break;
case MAX7219_ALIGN_LEFT:
offset = 0;
break;
default:
return;

}

uint8\_t data;
for (uint8\_t i = 0; i < buffer_len;) {
data = dev->display_buffer[i];
if (dev->display_buffer[i + 1] == '.'
|| dev->display_buffer[i + 1] == ',') {
dot = 1;
i++;
} else {
dot = 0;
}

max7219\_display\_digit\_at(dev, dev->digits - (offset++), data, dot);
i++;
if (offset > dev->digits) { // 超出位数截断
break;
}
}
}

3、MAX7219驱动测试

main.c文件中添加如下代码:

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
/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include <stdio.h>
#include "max7219\_spi/max7219\_spi.h"
/\* USER CODE END Includes \*/

/\* USER CODE BEGIN PV \*/
max7219\_t max7219;
uint8\_t display_buffer[16];
/\* USER CODE END PV \*/

int main(void)
{
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_USART1\_UART\_Init();
/\* USER CODE BEGIN 2 \*/

max7219.CS_GPIOx = MAX7219_CS_GPIO_Port;
max7219.CS_Pin = MAX7219_CS_Pin;
max7219.display_buffer = NULL;
max7219.SPIx = &hspi1;
printf("\*\*\*\*STM32CubeIDE:Max7219 8bits LED(SPI)\*\*\*\*\r\n");


max7219.id = 1;
max7219.digits = 8;
max7219.brightness = 3;

max7219\_init(&max7219);

max7219\_set\_display\_data(&max7219, "-.-.-.-.-.-.-.-.");
max7219\_display(&max7219, MAX7219_ALIGN_RIGHT);
HAL\_Delay(1000);
max7219\_clear(&max7219);
printf("display 1\r\n");
max7219\_set\_display\_data(&max7219, "8.8.8.8.8.8.8.8.");
max7219\_display(&max7219, MAX7219_ALIGN_RIGHT);
HAL\_Delay(1000);
max7219\_clear(&max7219);
printf("display 2\r\n");
max7219\_set\_display\_data(&max7219, "-3.1415");
max7219\_display(&max7219, MAX7219_ALIGN_RIGHT);
printf("display 3\r\n");
/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/

/\* USER CODE BEGIN 3 \*/

}
/\* USER CODE END 3 \*/
}

文章来源: https://iotsmart.blog.csdn.net/article/details/125636671