[STM32學習記錄-5] 優化STM32 GPIO設定函式

注意,本文的內容過於老舊,不建議實際使用,僅保留以作為參考用。

前言

在先前的[STM32學習記錄-3] 基本輸入與輸出教學-GPIO相關程式寫法中已經介紹過STM32設定GPIO的相關函式,但如果是常用Arduion的人一定不太習慣這種設定方式,畢竟每設定一個GPIO就要打4行程式,雖然可以複製貼上,但程式一多難免看起來混亂複雜,所以我自己寫了一些GPIO相關的函式,方便自己未來使用。

GPIO模式設定函式

程式如下:

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
/* Includes ------------------------------------------------------------------*/
#include "GPIO_mapping.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
// Pin Mode and Speed
#define OUT (0) // Output
#define IN (1) // Input

#define GPPP (0) // General purpose Push-Pull (Output)
#define GPOD (1) // General purpose Open-Drain (Output)
#define AFPP (2) // Alternate function Push-Pull (Output)
#define AFOD (3) // Alternate function Open-Drain (Output)

#define FL (0) // Floating (Input)
#define AN (1) // Analog (Input)
#define PD (2) // Pull-Down (Input)
#define PU (3) // Pull-Up (Input)

#define S2M (2) // 2MHz
#define S10M (10) // 10MHz
#define S50M (50) // 50MHz

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
* @brief Config a pin mode and speed.
* @param PortPin: select a pin to set.
* This parameter should be: 0 ~ 79
* 0~15:PA0~PA15; 16~31:PB0~PB15; 32~47:PC0~PC15;
* 48~63:PD0~PD15; 64~79:PE0~PE15
* @param INout: Input or Output.
* This parameter should be: 0(Output) or 1(Input).
* @param Mode: Pin mode.
* This parameter should be: 0~3.
* 0: GPPP or FL.
* 1: GPOD or AN.
* 2: AFPP or PD.
* 3: AFOD or PU.
* @param Speed: Pin speed.
* This parameter should be: 2, 10 or 50.
* 2: 2MHz.
* 10: 10MHz.
* 50: 50MHz.
* @retval None
*/
void Pin_Mod(u8 PortPin, u8 INout, u8 Mode, u8 Speed)
{
/* Structure Declarations */
GPIO_InitTypeDef GPIO_InitStructure;

// GPIO_Speed
switch(Speed)
{
case S2M: // S2M:2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
break;
case S10M: // S10M:10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
break;
case S50M: // S50M:50
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
break;
default:
break;
}

// GPIO_Mode
if(INout == OUT) // OUT:0
{
switch(Mode)
{
case GPPP: // GPPP:0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
break;
case GPOD: // GPOD:1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
break;
case AFPP: // AFPP:2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
break;
case AFOD: // AFOD:3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
break;
default:
break;
}
}
else if(INout == IN) // IN:1
{
switch(Mode)
{
case FL: // FL:0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
break;
case AN: // AN:1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
break;
case PD: // PD:2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
break;
case PU: // PU:3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
break;
default:
break;
}
}

// GPIO_Pin & GPIO_Init() function.
if(PortPin <= 15) // Port-A: 0~15
{
GPIO_InitStructure.GPIO_Pin = ((uint16_t)(0x0001 << PortPin));
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
else if(PortPin <= 31) // Port-B: 16~31
{
GPIO_InitStructure.GPIO_Pin = ((uint16_t)(0x0001 << (PortPin - 16)));
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
else if(PortPin <= 47) // Port-C: 32~47
{
GPIO_InitStructure.GPIO_Pin = ((uint16_t)(0x0001 << (PortPin - 32)));
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
else if(PortPin <= 63) // Port-D: 48~63
{
GPIO_InitStructure.GPIO_Pin = ((uint16_t)(0x0001 << (PortPin - 48)));
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
else if(PortPin <= 79) // Port-E: 64~79
{
GPIO_InitStructure.GPIO_Pin = ((uint16_t)(0x0001 << (PortPin - 64)));
GPIO_Init(GPIOE, &GPIO_InitStructure);
}
else /* Null */; // Out of range(0~79)
}

#undef OUT
#undef IN

#undef GPPP
#undef GPOD
#undef AFPP
#undef AFOD

#undef FL
#undef AN
#undef PD
#undef PU

#undef S2M
#undef S10M
#undef S50M

可以看到裡面就是增加了“void Pin_Mod(u8 PortPin, u8 INout, u8 Mode, u8 Speed)”此一函式。其用法如下:

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
/* STM32 Nucleo-64 board */
Pin_Mod(PA5, OUT, GPPP, S2M); // PA5: LED-user
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//GPIO_Init(GPIOA, &GPIO_InitStructure);

Pin_Mod(PC13, IN, FL, S2M); // PC13: Button-user
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//GPIO_Init(GPIOC, &GPIO_InitStructure);

/* USART */
Pin_Mod(PA2, OUT, AFPP, S50M); // PA2: USART2_TX
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//GPIO_Init(GPIOA, &GPIO_InitStructure);

Pin_Mod(PA3, IN, FL, S50M); // PA3: USART2_RX
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//GPIO_Init(GPIOA, &GPIO_InitStructure);

這樣的話就可以更簡單方便地設定GPIO了。

至於其引入的“GPIO_mapping.h”內容如下:(只適用於STM32F103RB,請依照自己的MCU腳位更改)

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
/**
******************************************************************************
* @file GPIO_mapping.h
* @author ZiTe
* @version V1.0.0
* @date 08-October-2019
* @brief Header for GPIO_Function.c module for STM32F103RB
******************************************************************************
* @attention
*
* This file is used ONLY for STM32F103RB(STM32 Nucleo-64 board).
*
******************************************************************************
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_MAPPING_H
#define __GPIO_MAPPING_H

/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/

/* STM32 Pin(Morpho) */
/*
* Default=Alternate functions Default
* MA=Main function(after reset)
* Remap=Alternate functions Remap
*/

// Port-A
#define PA0 (0) // WKUP/USART2_CTS/ADC12_IN0/TIM2_CH1_ETR
#define PA1 (1) // USART2_RTS/ADC12_IN1/TIM2_CH2
#define PA2 (2) // USART2_TX/ADC12_IN2/TIM2_CH3
#define PA3 (3) // USART2_RX/ADC12_IN3/TIM2_CH4
#define PA4 (4) // SPI1_NSS/USART2_CK/ADC12_IN4
#define PA5 (5) // SPI1_SCK/ADC12_IN5
#define PA6 (6) // SPI1_MISO/ADC12_IN6/TIM3_CH1;Remap:TIM1_BKIN
#define PA7 (7) // SPI1_MOSI/ADC12_IN7/TIM3_CH2;Remap:TIM1_CH1N
#define PA8 (8) // USART1_CK/TIM1_CH1/MCO
#define PA9 (9) // USART1_TX/TIM1_CH2
#define PA10 (10) // USART1_RX/TIM1_CH3
#define PA11 (11) // USART1_CTS/CANRX/USBDM/TIM1_CH4
#define PA12 (12) // USART1_RTS/CANTX/USBDP/TIM1_ETR
#define PA13 (13) // MA:JTMS/SWDIO;Remap:PA13
#define PA14 (14) // MA:JTCK/SWCLK;Remap:PA14
#define PA15 (15) // MA:JTDI;Remap:TIM2_CH1_ETR/ PA15/SPI1_NSS

// Port-B
#define PB0 (16) // ADC12_IN8/TIM3_CH3;Remap:TIM1_CH2N
#define PB1 (17) // ADC12_IN9/TIM3_CH4;Remap:TIM1_CH3N
#define PB2 (18) // MA:PB2/BOOT1
#define PB3 (19) // MA:JTDO;Remap:TIM2_CH2/PB3/TRACESWO/SPI1_SCK
#define PB4 (20) // MA:JNTRST;Remap:TIM3_CH1/PB4/SPI1_MISO
#define PB5 (21) // I2C1_SMBAl;Remap:TIM3_CH2/SPI1_MOSI
#define PB6 (22) // I2C1_SCL/TIM4_CH1;Remap:USART1_TX
#define PB7 (23) // I2C1_SDA/TIM4_CH2;Remap:USART1_RX
#define PB8 (24) // TIM4_CH3;Remap:I2C1_SCL/CANRX
#define PB9 (25) // TIM4_CH4;Remap:I2C1_SDA/CANTX
#define PB10 (26) // I2C2_SCL/USART3_TX;Remap:TIM2_CH3
#define PB11 (27) // I2C2_SDA/USART3_RX;Remap:TIM2_CH4
#define PB12 (28) // SPI2_NSS/I2C2_SMBAl/USART3_CK/TIM1_BKIN
#define PB13 (29) // SPI2_SCK/USART3_CTS/TIM1_CH1N
#define PB14 (30) // SPI2_MISO/USART3_RTS/TIM1_CH2N
#define PB15 (31) // SPI2_MOSI/TIM1_CH3N

// Port-C
#define PC0 (32) //
#define PC1 (33) //
#define PC2 (34) //
#define PC3 (35) //
#define PC4 (36) //
#define PC5 (37) //
#define PC6 (38) //
#define PC7 (39) //
#define PC8 (40) //
#define PC9 (41) //
#define PC10 (42) //
#define PC11 (43) //
#define PC12 (44) //
#define PC13 (45) //
#define PC14 (46) //
#define PC15 (47) //

// Port-D
#define PD0 (48) //
#define PD1 (49) //
#define PD2 (50) //
#define PD3 (51) //
#define PD4 (52) //
#define PD5 (53) //
#define PD6 (54) //
#define PD7 (55) //
#define PD8 (56) //
#define PD9 (57) //
#define PD10 (58) //
#define PD11 (59) //
#define PD12 (60) //
#define PD13 (61) //
#define PD14 (62) //
#define PD15 (63) //

// Port-E
#define PE0 (64) //
#define PE1 (65) //
#define PE2 (66) //
#define PE3 (67) //
#define PE4 (68) //
#define PE5 (69) //
#define PE6 (70) //
#define PE7 (71) //
#define PE8 (72) //
#define PE9 (73) //
#define PE10 (74) //
#define PE11 (75) //
#define PE12 (76) //
#define PE13 (77) //
#define PE14 (78) //
#define PE15 (79) //

/* Arduino Pin */
// Analog(CN8)
#define A0 (0) // PA0
#define A1 (1) // PA1
#define A2 (4) // PA4
#define A3 (16) // PB0
#define A4 (33) // PC1(or PB9,change by solder bridges)
#define A5 (32) // PC0(or PB8,change by solder bridges)

// Digital(CN9)
#define D0 (3) // PA3(USART2_RX)
#define D1 (2) // PA2(USART2_TX)
#define D2 (10) // PA10
#define D3 (19) // PB3(PWM)
#define D4 (21) // PB5
#define D5 (20) // PB4(PWM)
#define D6 (26) // PB10(PWM)
#define D7 (8) // PA8

// Digital(CN5)
#define D8 (9) // PA9
#define D9 (39) // PC7(PWM)
#define D10 (22) // PB6(PWM/CS)
#define D11 (7) // PA7(PWM/MOSI)
#define D12 (6) // PA6(MISO)
#define D13 (5) // PA5(SCK)
#define D14 (25) // PB9(SDA)
#define D15 (24) // PB8(SCL)

/* STM32 Nucleo-64 board */
#define Button_User (45) // PC13. B1. When push the button, the I/O is LOW value.
#define B1 (45)
#define LED_User (5) // PA5. LD2. When the I/O is HIGH value, the LED is on.
#define LD2 (5)

/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */

#endif /* __GPIO_MAPPING_H */

/********************************END OF FILE***********************************/

結語

這次簡單地分享了自己打的程式,不敢說自己的程式很完善、漂亮,但希望它有幫助到你。
如有問題或錯誤也歡迎提出討論!

注意,本文的內容過於老舊,不建議實際使用,僅保留以作為參考用。


留言可能不會立即顯示。若過了幾天仍未出現,請 Email 聯繫:)