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

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

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

 

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

๋“œ๋ผ์ด๋ฒ„ ํŒŒ์ผ๋ช… : 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)๋กœ
// ๋ฐ˜์ „ ์‹œ์ผœ์ค€๋‹ค.

 

๐Ÿ’ก GPIO ์„ธํŒ…

GPIO Setting

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


Pin Name

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

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

GPIO Output Level 

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

 

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๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ํ•  ๋•Œ ํ•ด๋‹น ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

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

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

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

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

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์„ ์ง€์ •ํ•ด์ค˜์•ผ ํ•˜๋Š” ๋“ฏ ํ•˜๋‹ค. 
    }}

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

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

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);
		   }}

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

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

#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);
  }}

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

 

'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

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

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