Toby's Study Blog
article thumbnail
Published 2023. 8. 13. 13:43
[stm32] GPIO ์‹ค์Šต embedded

1. ๐Ÿ’ก ์‹ค์Šต ๋ชฉํ‘œ

1. ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ์‹œ LD1 -> LD2 -> LD3 ์ˆœ์œผ๋กœ LED ์ ๋ฉธ์„ ON / OFF ์‹œํ‚จ๋‹ค. 
2. HAL_Delay ์‚ฌ์šฉ ์—†์ด LED๊ฐ€ ๊นœ๋นก๊ฑฐ๋ฆฌ๊ฒŒ ์„ค์ •ํ•œ๋‹ค.
3. ์‹ค์Šตํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ตฌ์กฐ์ฒด, ํฌ์ธํ„ฐ, ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

 

2. ๐Ÿ’ก ์ฃผ์š” ํ•จ์ˆ˜

๋“œ๋ผ์ด๋ฒ„ ํŒŒ์ผ๋ช… : stm32f4xx_hal.gpio.c 

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
//์™ธ๋ถ€ ์ธํ„ฐ๋ŸฝํŠธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ์จ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์™€ ๊ฐ™์€ ์™ธ๋ถ€ ์ธํ„ฐ๋ŸฝํŠธ ๋™์ž‘์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
// ์ถœ๋ ฅ ๋ชจ๋“œ(Output)๋กœ ์„ค์ •๋œ ํŠน์ • GPIO Pin์— ์–ด๋–ค ๊ฐ’์„ ์ถœ๋ ฅํ•  ๊ฒƒ์ธ์ง€ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. 
// (LED์˜ ๊ฒฝ์šฐ 1(High)์„ ์ „๋‹ฌํ•˜๋ฉด ์ ๋“ฑ, 0(Low)์„ ์ „๋‹ฌํ•˜๋ฉด ๊บผ์ง„๋‹ค.

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
// ์ถœ๋ ฅ ๋ชจ๋“œ(Output)์ผ ๋•Œ ํ•ด๋‹น ํ•€์— ์ „๋‹ฌ๋˜๊ณ  ์žˆ๋Š” ์‹ ํ˜ธ๋ฅผ 1(High)์ผ ๋•Œ 0(Low)๋กœ ๋ฐ˜๋Œ€๋กœ 0(Low)์ผ ๋•Œ 1(High)๋กœ
// ๋ฐ˜์ „ ์‹œ์ผœ์ค€๋‹ค.

 

3. ๐Ÿ’ก GPIO ์„ธํŒ…

GPIO Setting

STM32-429zi์˜ ๊ฒฝ์šฐ Green, Blue, Red 3๊ฐ€์ง€ LED๊ฐ€ ์žˆ์œผ๋ฉฐ GPIO์˜ ์ดˆ๊ธฐ ์„ค์ •๊ฐ’์€ ์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™๋‹ค.

3.1. Pin Name

Port๋Š” ํ•€์„ ๊ทธ๋ฃนํ™”ํ•œ ๊ฐœ๋…์ด๋ฉฐ(e.g. PA, PB) Pin Name์€ ํŠน์ • ํฌํŠธ์— ์†ํ•ด์žˆ๋Š” Pin์„ ์˜๋ฏธํ•œ๋‹ค. (e.g. PA0, PA1)

์•„๋ž˜ ๊ทธ๋ฆผ์—์„œ MCU -> LED๋กœ On/Off ์‹ ํ˜ธ(๋ฐ์ดํ„ฐ)๋ฅผ ์ „๋‹ฌํ•˜๋ฏ€๋กœ Output์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.  

3.2. GPIO Output Level 

GPIO Output Level์€ ์‹œ์Šคํ…œ์„ ์„ธํŒ… ํ›„ GPIO ํ•€์˜  ์ดˆ๊ธฐ ์ถœ๋ ฅ ์ƒํƒœ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ์ด๋‹ค.
Low - 0V(GND), High - 3.3V(VCC) 2๊ฐ€์ง€๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
(โ€ป ์ดˆ๊ธฐ ์ถœ๋ ฅ ์ƒํƒœ๋ฅผ ๊ผญ High๋กœ ์ฃผ์ง€ ์•Š์•„๋„ MCU์—์„œ ๋ฌธ์ œ์—†์ด ๋ฐ”๋กœ ์›ํ•  ๋•Œ ์ „๋ ฅ์„ ๊ณต๊ธ‰ํ•ด On/Off ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—
     ์ดˆ๊ธฐ ์„ค์ •์„ Low๋กœ ์„ค์ •ํ•ด๋„ ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.)  

 

3.3. GPIO mode 

GPIO๋Š” Input, Output, Alternate Function, Analog, External Interrupt, External Event๊ฐ€ ์žˆ์œผ๋ฉฐ 

์ธํ„ฐ๋ŸฝํŠธ์˜ ๊ฒฝ์šฐ์—๋Š” Rising Edge, Falling Edge๋กœ ์„ธ๋ถ€ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ

์ถœ๋ ฅ์˜ ๊ฒฝ์šฐ์—๋Š” Push Pull ๊ณผ Open Drain ๋ชจ๋“œ๋กœ ์„ธ๋ถ€ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์ด์ „ ์ด๋ก  ์ •๋ฆฌ ๊ธ€์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃจ์—ˆ์ง€๋งŒ Push Pull, Open Drain์€ ๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

1. Push Pull

- High๋ฅผ ์ฃผ๋ฉด 5V๊ฐ€ ๋‚˜์˜ค๊ณ , Low๋ฅผ ์ฃผ๋ฉด 0V๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

- ์ผ๋ฐ˜์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ์ž…์ถœ๋ ฅ์˜ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•œ๋‹ค.

2. Open Drain

-  High๋ฅผ ์ฃผ๋ฉด 0V๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. 

-  MCU์—์„œ๋Š” 5V๋ฅผ ์ฃผ๋Š”๋ฐ ์—ฐ๊ฒฐ๋˜๋Š” ์ „์ž ์žฅ์น˜๊ฐ€ 3.3V๋ฅผ ๋ฐ›์•„์•ผ ํ•  ๋•Œ ํ•ด๋‹น ๋ชจ๋“œ๋ฅผ ํ†ตํ•ด
   5V๊ฐ€ ๋“ค์–ด๊ฐ€์ง€ ์•Š๊ฒŒ ํ•˜๊ณ  ๋”ฐ๋กœ ์ €ํ•ญ์„ ํ†ตํ•ด 3.3V๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ํ•  ๋•Œ ํ•ด๋‹น ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

4. ๐Ÿ’ก ์‹ค์Šต ๊ฒฐ๊ณผ

https://github.com/Tobbyvv/stm32-project/tree/main/gpio

4.1. ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ์‹œ LD1 -> LD2 -> LD3 ์ˆœ์œผ๋กœ LED ์ ๋ฉธ์„ ON / OFF 

์™ธ๋ถ€ ์ธํ„ฐ๋ŸฝํŠธ ์ฒ˜๋ฆฌ์šฉ ํ”Œ๋ž˜๊ทธ ๋ณ€์ˆ˜๊ฐ€ true์ผ ๋•Œ(๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ)  state๊ฐ€ ์ฆ๊ฐ€ํ•˜๋ฉฐ
0, 1, 2 state์— ๋”ฐ๋ผ 1๋ฒˆ, 2๋ฒˆ 3๋ฒˆ LED๊ฐ€ ์ˆœํ™˜ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ ์ž…๋‹ˆ๋‹ค. 

<cpp />
static bool exti_flag = false; //๋ฒ„ํŠผ on/off ์ƒํƒœ ์ €์žฅ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์„ ์–ธ static uint8_t state = 0; //3๊ฐ€์ง€ LED ์ œ์–ด๋ฅผ ์œ„ํ•œ 0, 1, 2 ์ €์žฅ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์„ ์–ธ while (1) { /* USER CODE END WHILE */ if (exti_flag == true) { exti_flag = false; state++; //๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆด๋•Œ๋งˆ๋‹ค state๋ฅผ ์ฆ๊ฐ€์‹œํ‚ด state %= 3; //3์œผ๋กœ ๋‚˜๋ˆˆ ๋‚˜๋จธ์ง€ ๊ฐ’์„ ์ €์žฅํ•ด 0, 1, 2 ์ €์žฅ } switch(state){ case 0:{ HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); HAL_Delay(1000); //1์ดˆ๋งˆ๋‹ค Toggle(High -> Low, Low -> High) ๋˜๋„๋ก ์„ค์ • HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); break; } case 1:{ HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); HAL_Delay(1000); HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); break; } case 2:{ HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin); HAL_Delay(1000); break; }}}} void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_13) { //F429zi์˜ ๊ฒฝ์šฐ button์ด 13๋ฒˆ PIN์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค. exti_flag = true; //์ธํ„ฐ๋ŸฝํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” Pin์„ ์ง€์ •ํ•ด์ค˜์•ผ ํ•˜๋Š” ๋“ฏ ํ•˜๋‹ค. }}

4.2. HAL_Delay ์‚ฌ์šฉ ์—†์ด LED๊ฐ€ ๊นœ๋นก๊ฑฐ๋ฆฌ๊ฒŒ ์„ค์ •

๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ์˜ ์‹œ๊ฐ„๊ณผ ํ˜„์žฌ ์‹œ๊ฐ„์˜ ์ฐจ์ด๊ฐ€ 1์ดˆ๊ฐ€ ๋„˜์–ด๊ฐ€๋ฉด LED Toggle ๋˜๋„๋ก ์ž‘์„ฑ ํ•˜์˜€์œผ๋‚˜..
ํ•ด๋‹น ๋™์ž‘์€ LD3๋งŒ ๋™์ž‘ํ•˜์˜€๊ณ  LD1, LD2๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค...

<cpp />
static bool exti_flag = false; //๋ฒ„ํŠผ on/off ์ƒํƒœ ์ €์žฅ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์„ ์–ธ static uint8_t state = 0; //3๊ฐ€์ง€ LED ์ œ์–ด๋ฅผ ์œ„ํ•œ 0, 1, 2 ์ €์žฅ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์„ ์–ธ static uint32_t prev = 0; // ์ด์ „ ์‹œ๊ฐ„ #define D_TIME_MAX 1000 // ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ 1์ดˆ while (1) { /* USER CODE END WHILE */ if (exti_flag == true) { exti_flag = false; state++; state %= 3; } switch(state){ case 0:{ if (HAL_GetTick() - prev > D_TIME_MAX) { // 1์ดˆ๊ฐ€ ์ง€๋‚˜๋ฉด LED ํ† ๊ธ€ HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); prev = HAL_GetTick(); } else if(HAL_GetTick() - prev < D_TIME_MAX) { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); }}

4.3. ๊ตฌ์กฐ์ฒด, ํฌ์ธํ„ฐ, ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด ์ฝ”๋“œ๋ฅผ ์ •๋ฆฌ

๊ตฌ์กฐ์ฒด์™€ ํฌ์ธํ„ฐ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์‹ค์Šตํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

<cpp />
#include <stdio.h> #include <stdbool.h> #include "main.h" #include "app.h" static bool exti_flag = false; //๋ฒ„ํŠผ on/off ์ƒํƒœ ์ €์žฅ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์„ ์–ธ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { static uint32_t prev; volatile uint32_t curr; curr = HAL_GetTick(); //ํ˜„์žฌ ์‹œ๊ฐ„ ๊ฐ€์ ธ์˜ด if ((uint32_t)(curr - prev) > 150) { //๋ฒ„ํŠผ ๋™์ž‘ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ 0.15์ดˆ๋กœ ์ค‘๋ณต ์‹คํ–‰ ๋ฐฉ์ง€ if (GPIO_Pin == GPIO_PIN_13) { exti_flag = true; } prev = curr; //๋ฒ„ํŠผ ๋ˆ„๋ฅธ ์‹œ๊ฐ„ ์ €์žฅ }} #define D_TIME_MAX 500 //LED ๊นœ๋นก๊ฑฐ๋ฆผ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ 0.5์ดˆ #define D_LED_MAX 3 //LED ๊ฐฏ์ˆ˜ typedef struct { uint32_t prev; //์ด์ „ LED ํ† ๊ธ€ ์‹œ๊ฐ„ ์ €์žฅ void (*cbf)(void *, uint8_t); //ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ์„ ์–ธ(โ€ป LED Toggle ํ•จ์ˆ˜ ํ• ๋‹น์šฉ) } LED_TOGGLE_T; LED_TOGGLE_T gLedObj[D_LED_MAX]; //3๊ฐœ์˜ LED์˜ ํ† ๊ธ€ ๋™์ž‘์„ ๊ด€๋ฆฌํ• ๋ฐฐ์—ด ์„ ์–ธ void app_init(void) { // LED ํ† ๊ธ€ ํ•จ์ˆ˜ ๋ฐ ๊ตฌ์กฐ์ฒด ์ดˆ๊ธฐํ™” gLedObj[0].cbf = LD1_Toggle; gLedObj[1].cbf = LD2_Toggle; gLedObj[2].cbf = LD3_Toggle; for (uint8_t i=0; i<D_LED_MAX; i++) { if (gLedObj[i].cbf == NULL) while (1); //TOGGLE ํ•จ์ˆ˜ ํ• ๋‹น์ด ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ } //ํ• ๋‹น ๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ while๋ฌธ ์ข…๋ฃŒ } void app(void) { uint8_t state = 0; app_init(); while (1) { if (exti_flag == true) { exti_flag = false; state++; state %= D_LED_MAX; gLedObj[state].cbf((void *)&gLedObj[state], 0); //1.gLedObj[state], ์ฆ๊ฐ€๋œ ๋งค๊ฐœ๋ณ€์ˆ˜์— ํ•ด๋‹นํ•˜๋Š” ํ•จ์ˆ˜์™€ //2.๋จผ์ € 0์„ ์ „๋‹ฌํ•˜์—ฌ ๋‹ค๋ฅธ LED๋ฅผ ์ข…๋ฃŒ์‹œํ‚ด } gLedObj[state].cbf((void *)&gLedObj[state], 1); //1์„ ์ „๋‹ฌํ•˜์—ฌ ํ•ด๋‹น LED๋ฅผ ๊นœ๋นก๊ฑฐ๋ฆฌ๊ฒŒํ•จ }} // LD1 LED ํ† ๊ธ€ ํ•จ์ˆ˜ void LD1_Toggle(void *pArg, uint8_t op) { LED_TOGGLE_T *p = (LED_TOGGLE_T *)pArg; if (op == 1) { uint32_t curr = HAL_GetTick(); if (curr - p->prev > D_TIME_MAX) { HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); p->prev = curr; printf("%s\r\n", __func__); } } else { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); }} // LD2 LED ํ† ๊ธ€ ํ•จ์ˆ˜ void LD2_Toggle(void *pArg, uint8_t op) { LED_TOGGLE_T *p = (LED_TOGGLE_T *)pArg; if (op == 1) { uint32_t curr = HAL_GetTick(); if (curr - p->prev > D_TIME_MAX) { HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); p->prev = curr; printf("%s\r\n", __func__); } } else { HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); }} // LD3 LED ํ† ๊ธ€ ํ•จ์ˆ˜ void LD3_Toggle(void *pArg, uint8_t op) { LED_TOGGLE_T *p = (LED_TOGGLE_T *)pArg; if (op == 1) { uint32_t curr = HAL_GetTick(); if (curr - p->prev > D_TIME_MAX) { HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin); p->prev = curr; printf("%s\r\n", __func__); } } else { HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); }}

5. ๐Ÿ’ก ๊ฒฐ๊ณผ ์˜์ƒ

 

'embedded' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[stm32] UART ์‹ค์Šต  (0) 2023.08.30
[stm32] UART ์ด๋ก  ์ •๋ฆฌ  (0) 2023.08.16
[stm32] Timer ์‹ค์Šต  (0) 2023.08.16
[stm32] Timer ์ด๋ก  ์ •๋ฆฌ  (0) 2023.08.16
[stm32] GPIO ์ด๋ก  ์ •๋ฆฌ  (0) 2023.08.12
profile

Toby's Study Blog

@Toby12

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!

๊ฒ€์ƒ‰ ํƒœ๊ทธ