Computer Science
탄탄한 기반 실력을 위한
전공과 이론 지식 모음
Today I Learned!
배웠으면 기록을 해야지
TIL 사진
Flutter 사진
Flutter로 모바일까지
거꾸로캠퍼스 코딩랩 Flutter 앱개발 강사
스파르타코딩클럽 즉문즉답 튜터
카카오테크캠퍼스 3기 학습코치
프로필 사진
박성민
임베디드 세계에
발을 들인 박치기 공룡
임베디드 사진
EMBEDDED SYSTEM
임베디드 SW와 HW, 이론부터 실전까지
ALGORITHM
알고리즘 해결 전략 기록
🎓
중앙대학교 소프트웨어학부
텔레칩스 차량용 임베디드 스쿨 3기
애플 개발자 아카데미 1기
깃허브 사진
GitHub
프로젝트 모아보기
Instagram
인스타그램 사진

Embedded System/MCU

[MCU] GPIO의 하드웨어 구조와 데이터시트, 침침한 눈을 곁들인

sm_amoled 2025. 10. 24. 00:03

STM32F429ZIT6 / NUCLEO-144 Boards 를 기준으로 작성되었습니다.

레퍼런스 메뉴얼 참고 링크

https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

실습을 하면서 계속 GPIO, GPIO 라는 키워드가 반복해서 나왔다. GPIO라는게 General Purpose Input / Output 이라는건 알고있었는데, 그래서 이게 정확히 어떤거냐? 라는 질문을 받아보니 말문이 턱 막히더라. 범용으로 사용한다는건 설정값들을 바꿔서 휘뚜루마뚜루 활용할 수 있다는건데, 어떤 원리로 읽고 쓰는지에 대해서는 정확히 모른채 그냥 HAL_GPIO_ReadPin, HAL_GPIO_WritePin 만 호출하고 있었다. 이번에 수업에서 GPIO를 다루는 김에 내가 확실히 동작 방식을 알 수 있도록 구조부터 회로까지 한 번 싹 잡아 정리해보려고 한다!

그래서 도대체 GPIO가 뭐냐?

레퍼런스 메뉴얼의 GPIO 부분을 살펴보자.

 

정확하게 그래서 GPIO가 뭐다! 라고 작성되어있지는 않다. 그냥 냅다 설명부터 박고있다. 내가 생각하는 GPIO의 정의는 여러 방식으로 설정해서 활용할 수 있는 I/O port 정도이다.

앞으로 위에 작성되어있는 GPIO의 여러 특징들에 대해 살펴보겠지만, 간략하게 짚고 넘어가자면

  • 현재 내가 사용하려는 STMF429ZIT6에는 GPIOA~GPIOK 까지 11개의 GPIO를 가지고 있다.
  • GPIO라는건 하나의 묶음(GPIOA, GPIOB, …)이 최대 16개의 I/O 를 가질 수 있다.
  • 하나의 GPIO에 묶여있더라도, 각각의 I/O 포트에 대해서 개별적으로 설정이 가능하다.
  • GPIO를 사용해서 Input, Output 을 처리하거나, 주변장치의 입출력 포트로 사용할 수 있다. (Alternate Function)
  • 2 CLK 만에 신호를 전환할 수 있다. (속도 사양)

흠 근데 진짜 궁금한 점이 생겼다. 분명 GPIO가 11개라고 했는데, 보드에는 핀이 144개 밖에 없고, GPIOH 부터는 PH0, PH1을 제외하고는 GPIO Pin이 제공되지 않는다. GPIO가 16개라면 핀이 176개여야 하는거 아닌가 ??? 🤨🤨🤨🤨
그래서 또 찾아봤더니, 같은 아키텍처에 대해서 I/O를 176개 제공하는 칩이 있고, 144개 제공하는 칩이 있는 것 같다. 그리고 내가 사용하는 보드는 144개의 pin을 제공하기 때문에 모든 GPIO를 사용할 수는 없고, GPIOA~ GPIOG + PH0, PH1까지 114개의 GPIO를 사용할 수 있다고 보면 된다.

앞으로 말하는 GPIO는 PA1, PA2 같은 단일 포트가 아닌, 
PA0 ~ PA15를 모두 합친 GPIOA를 말하는 것이다!

GPIO 의 레지스터

각각의 GPIO는 다음의 레지스터들을 가지고 있다. 모든 레지스터는 32bit로 구성됨!

I/O 포트를 설정할 수 있는 Configuration 레지스터

GPIO의 각 Port에 대해서 설정을 넣어줄 수 있는 레지스터들이다.

  • MODER [Mode Reg] : I/O 방향을 결정할 때 사용
    • Input Mode / Output Mode / AF (Alternate Function Mode) / Analog Mode
    • AF 모드를 선택하면 GPIO의 제어를 다른 peripheral 에게 맡길 수 있다.
    • Analog 모드를 선택하면 GPIO를 Analog 를 처리하는 peripheral 의 입출력 통로로 사용한다.
  • OTYPER [Output Type Reg] : Output 타입을 결정할 때 사용
    • Push-Pull / Open-Drain
  • OSPEEDR [Output Speed Reg] : 출력핀의 신호 속도를 결정할 때 사용
    • Low Speed / Medium Speed / High Speed / Very High Speed
  • PUPDR [Pull-Up Pull-Down Reg] : 내부 풀업/풀다운 저항의 활성화를 결정
    • no pull-up pull-down / pull-up / pull-down
    • 입력이 없을 때 (부유 상태) Low 상태 / High 상태를 결정

간단하게, 오른쪽의 I/O Configuration에서 내가 원하는 설정을 결정하고 MODER, OTYPER, OSPEEDR, PUPDR 레지스터의 port에 해당하는 bit에다가 설정에 대한 값을 넣어주면 된다.

각 레지스터에 대한 형태는 이런 방식으로 구성이 되어있다. 굳이 여기에서 모든 레지스터에 대해서 설명을 작성할 필요는 없을 것 같고, 아래 2개의 레지스터만 대표로 들고왔다.

 

여기에서 눈여겨 봐야할 점은

  • [중요] 각 레지스터는 GPIOB의 베이스 주소로부터 Address offset 만큼 떨어진 곳에 위치해있다. &GPIOB_OTYPER == GPIOB_BASE + 0x04
  • MODER 처럼 하나의 GPIO 포트가 2개의 bit을 사용하는 경우도 있다.
  • 만약에 PB7의 모드를 Output Mode로 두고싶다면 GPIOBMODER 레지스터에서 [15:14] bit에다가 10 이라는 값을 SET 해주면 된다.
  • OTYPER 레지스터처럼 포트가 할당되지 않은 Reserved 영역은 건드리는게 아니다.

CubeIDE에서 위 레지스터의 값들을 아주 간편하게 넣어줄 수 있다. GPIO 핀을 Pinout에서 설정하는 경우, 아래처럼 다양한 기능들을 사용할 수 있음을 확인할 수 있다. 여기에서 GPIO_Input, GPIO_Output, GPIO_Analog 는 MODE 레지스터를 통해 결정되는 사항이고, MODER가 AF에 해당하는 bit를 담고있는 경우에 ADC, ETH, TIM 등의 다양한 기능으로 활용할 수 있다. 이에 대해 더 자세한 내용은 잠시 뒤에서 확인해보자.

아래 사진을 보면 GPIO Pin 에 대해서 여러가지 모드와 설정들을 GUI로 넣어줄 수 있다. 여기에 값들을 넣는 것이 OTYPE 레지스터, OSPEED 레지스터, PUPD 레지스터에 값을 설정해주는 것을 의미한다.

실제로 IDE가 자동으로 생성해준 코드인 MX_GPIO_Init 쪽을 살펴보면, GPIO를 구성하는 레지스터에다가 이렇게 설정값들을 할당해서 넣어준 뒤에, HAL_GPIO_Init 이라는 함수를 통해 값들을 넣어주는 것을 볼 수 있다.

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

    ...

  /*Configure GPIO pin : PB7 */
  GPIO_InitStruct.Pin   = GPIO_PIN_7;
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull  = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

위 방식처럼 HAL을 사용하지 않고 직접 레지스터 주소를 사용해 Pin 에게 값을 넣어주고 싶다면 이렇게 시도해줄 수 있다.

// PB7을 GP Output으로 사용하고자 함
// GPIOB의 Base 주소 :    0x40020400 

// output mode로 설정
*((volatile uint32_t*) (0x40020400 + 0x00)) &= 0x00 << 7 * 2;
*((volatile uint32_t*) (0x40020400 + 0x00)) |= 0x01 << 7 * 2;

// pull-down으로 기본 값을 0으로 설정
*((volatile uint32_t*) (0x40020400 + 0x0C)) &= 0x00 << 7 * 2;
*((volatile uint32_t*) (0x40020400 + 0x0C)) |= 0x00 << 7 * 2;

실제로 HAL_GPIO_Init 함수를 열어보면 아래처럼 비트 연산으로 설정을 넣어주는 것을 볼 수 있다.

// HAL_GPIO_Init 함수 내부
        ...
// ***** GPIO의 모드가 ANALOG가 아닌 경우에 대해서
      if((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
      {
        /* Check the parameters */
        assert_param(IS_GPIO_PULL(GPIO_Init->Pull));

    /* Activate the Pull-up or Pull down resistor for the current IO */
// ***** 현재 GPIO의 PUPD 레지스터의 값을 가져와서
// ***** Bit 연산으로 내가 지정하려는 port의 모드 값을 변경하고
// ***** 다시 PUPD 레지스터의 값을 변경한다. 
        temp = GPIOx->PUPDR;
        temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U));
        temp |= ((GPIO_Init->Pull) << (position * 2U));
        GPIOx->PUPDR = temp;
      }
      ...

데이터 입출력을 위한 Data 레지스터

이 보드에서는 입력과 출력을 위한 레지스터를 각각 제공한다. 만약 GPIO 포트로 들어오는 값을 읽고싶다면 GPIO_IDR 의 해당 포트가 할당된 bit의 값이 얼마인지를 읽으면 된다. 반대로, 특정 GPIO 포트로 값을 내보내고 싶다면 or 포트로 나가는 값이 현재 무엇인지 알고싶다면 (어차피 0 아니면 1) GPIO_ODR 레지스터에서 해당 포트의 bit를 읽으면 된다.

 

  • IDR [Input Data Reg] : 핀의 현재 입력 상태 읽기
    • 읽기 전용 핀
    • 하위 16개의 bit만 사용한다.
  • ODR [Output Data Reg] : 핀의 현재 출력 상태 RW를 위해 사용
    • ODR을 읽어 출력 핀의 상태를 읽을 수 있고, ODR에 값을 써서 출력 상태를 설정할 수 있다.
    • 하위 16개의 bit만 사용한다.

Set/Reset 레지스터

그런데, GPIO의 출력을 제어하는 레지스터가 하나 더 있다! (대충 삐슝빠슝 효과음) 앞서 ODR 레지스터의 역할에 대해 ‘현재 출력 값을 읽기 위해 사용’ 한다는 문장에만 하이라이트를 그어둔 게 다 의미가 있었다.

우선 BSRR 의 기능을 한 번 보자. 아래 시트를 보면 32개의 bit에 대해 하나의 포트가 BS, BR을 하나씩 할당받아있다. 여기에서 PB7 에 Output으로 1을 보내고 싶다면 BSRR의 7번 bit에 1을 쓰면 되고, Output을 다시 0으로 초기화 하고싶다면 BSRR의 23번 bit에 1을 쓰면 된다.

 

  • BSRR [Bit Set Reset Reg] : 핀의 출력 상태 설정을 사용
    • 상위 16bit : Reset, 하위 16bit : Reset 을 위해 사용
    • Interrupt 상황에서의 Race Condition 등의 이슈가 있기 때문에 pin 출력 시 ODR 보다 BSRR이 더 나은 선택임.

Race Condition이 뭔데 씹덕아! 라고 할까봐 또 예시를 하나 쌈뽕하게 준비해왔다.

현재 ODR : 0001 0000 이라 하자.
그리고 7번 pin에 Output을 넣는 상황이라고 해보자.

1) ODR을 이용해 값을 작성하는 경우

    1. 레지스터에 ODR의 값을 가져옴
    r = 0001 0000

    2. 레지스터의 7번 pin에 신호를 1로 변경
    r |= 1000 0000

    3. ODR에 레지스터의 값을 대입
    ODR = r

2) ODR이 문제가 되는 상황

    1. 레지스터에 ODR의 값을 가져옴
    r = 0001 0000

    2. 레지스터의 7번 pin에 신호를 1로 변경
    r |= 1000 0000
    [여기에서 r의 값은 1001 0000]

    <이때 갑자기 Interrupt 발생!!>
    <IRQ가 호출되어 해결하는 과정에서>
    <ODR의 값이 0011 0000이 되어버렸슨>

    3. ODR에 레지스터의 값을 대입
    [여기에서 r의 값은 1001 0000]
    ODR = r

    ODR이 0011 0000 -> 1011 0000 이 되길 기대했는데
    맙소사 0011 0000 -> 1001 0000 이 되어버림! (**Race Condition**!)

3) BSRR을 사용하는 경우

    그냥 **값 대입 한 번에 바로 끝남**
    BSRR = 1000 0000

요런 상황을 방지하기 위해서 BSRR의 사용이 권장된다.

Locking 레지스터

  • LCKR [Lock Reg] : GPIO 설정을 잠가서 실수로 변경 방지
    • MODER, OTYPER, OSPEEDR, PUPDR, AFR 의 변경을 막을 수 있다.
    • ODR, BSRR을 통한 출력은 가능

Function Selection 레지스터

GPIO를 정말 GPIO로 만들어주는 레지스터라고 생각한다. 만약 이 Alternate Function Selection 레지스터에 Bit이 들어와있다면 단순히 Input/Output 으로서의 역할이 아니라 주변 Peripheral의 입출력을 위한 포트로 사용하겠다는 의미이다. 각 포트는 최대 16개의 Peripheral과 연결되어있다. 각각의 포트가 16개의 Peripheral 중에 하나를 선택하게 되기 때문에, 지정을 위해 하나의 포트 당 4개의 bit를 사용해야 한다. 그래서 총 64 bit가 필요해 레지스터도 2개나 할당받았다.

 

  • AFRH [Alternate Function Reg High] : 상위 8개 핀의 동작을 변경
  • AFRL [Alternate Function Reg Low] : 하위 8개 핀의 동작을 변경

그림으로 보면 약간 이런 느낌 ㅋㅋ. 다양한 Peripheral이 하나의 포트에 물려있고, 이걸 MUX를 이용해서 4개의 bit를 control로 활용해 Select 하는 형태라고 생각하면 된다.

표로 정리해서 간단하게 보면 아래와 같다. 이런거 정리는 지피티니가 참 잘해준단 말이지.

레지스터 분류 약어 용도 및 설명
Configuration 레지스터 MODER I/O 방향 결정 (Input/Output/AF/Analog)
  OTYPER Output 타입 결정 (Push-Pull/Open-Drain)
  OSPEEDR 출력 신호 속도 결정 (Low/Medium/High/Very High)
  PUPDR 내부 풀업/풀다운 저항 설정 (부유 상태 시 High/Low 결정)
Data 레지스터 IDR 핀의 입력 상태 읽기 (읽기 전용, 하위 16bit)
  ODR 핀의 출력 상태 읽기/쓰기 (하위 16bit)
Set/Reset 레지스터 BSRR 핀의 출력 상태 설정 (상위 16bit: Reset, 하위 16bit: Set)
※ Race Condition 방지로 ODR보다 권장    
Locking 레지스터 LCKR GPIO 설정 잠금 (Configuration 변경 방지, 출력은 가능)
Function Selection 레지스터 AFRH 상위 8개 핀의 Alternate Function 설정
  AFRL 하위 8개 핀의 Alternate Function 설정

내가 눈이 나쁜 줄 알았다.

 

잘 보면, GPIO_AFRLGPIOA~ GPIOK 인데, GPIO_AFRH 는 ~ GPIOJ 이다. 나는 처음에 내가 메뉴얼에서 오타를 찾은 줄 알았다. ㅋㅋㅋ 그런데 목차나 여기저기에 다 A~J로 되어있어서 엥엥엥??? 싶었다.

그래서 열심히 또 뭐가 이걸 이렇게 만든건지 이유를 찾아 헤맸는데, STM32F429의 DataSheet에서 답을 찾을 수 있었다. 데이터시트의 Pinouts and pin description 쪽을 확인해보면 GPIO의 모든 포트(PA0 ~ PK7)이 어떤 녀석들과 연결되어 Alternate Function 으로 사용할 수 있는지를 확인할 수 있다.

 

그런데 여기에서 GPIOK 의 영역으로 가보면 실제로 포트가 PK0 부터 PK7 까지 8개의 포트밖에 없고, 8~15는 아예 존재하지도 않는다. 아마도 물리적인 설계의 이유로 가장 마지막에 있는 8개의 포트는 제거해버린게 아닐까 추측된다. 그래서  PK8~ 

 

PK15 에 대한 AF를 가리키는 GPIO_AFRH 는 굳이 필요가 없으니 아예 제거해버린게 아닐까 싶다.

GPIO 회로도

제공되는 메뉴얼의 GPIO 회로도를 살펴보면 어떻게 값들이 들어오고 나가는지를 한 눈에 확인할 수 있다. 여기에서 내가 설정해줄 수 있는 다양한 Configuration (Alternate Function, MODE, PUPD)과 입출력 관련 설정(IDR, ODR, BSSR) 등이 어떻게 관여되고 있을지 짐작해볼 수 있다.

여전히 Push Pull, Open Drain 이라던가 Pull-Up, Pull-Down 에 대해서는 잘 감을 잡지 못하고 있다. 그런데 찾아보니 회로와 연관된 내용들이 조금 들어가있어서, 이 부분은 글도 길어졌으니 회로 파트로 따로 빼서 조만간 작성해 정리해볼 예정이다 😊


20251024 추가)

사용을 자제해야하는 GPIO 포트

 

GPIO 문서에서 내용들을 살펴보다보니 아래처럼 A 포트와 B 포트에 이미 특정 값들이 할당이 되어있는 것을 볼 수 있었다. 처음에는 그냥 대수롭지 않게 넘겼는데, 다시 보니깐 뭔가 수상한 값들이라 생각이 들어서 다시 한 번 찾아와서 해당 레지스터들이 어떤 역할을 하는 녀석들인지 찾아봤다.

 

SWJ는 JTAG와 직렬 와이어 디버그(Serial Wire Debug)를 하나의 포트로 결합할 수 있는 SWJ-DP라는 디버깅 인터페이스를 의미. 그냥 이게 디버그 모드로 빌드했을 때 Host(컴퓨터)와 연결되는 포트라고 생각하면 된다.

위 문서상으로는 모든 디버그 포트의 핀 (PA13, PA14, PA15, PB3, PB4) 가 MODER 에서 10 이라는 값을 가지는 것으로 보아, Alternate Function 모드로 설정되어 있음을 확인할 수 있었다. 혹시나 하는 마음에 모든 디버그 포트를 그냥 Pinout Configuration 파일에서 Output Mode로 지정 후 어떻게 되나 테스트를 해보았다.

 

 

오호라, 그랬더니 디버깅 실행 중에 HAL_Init() 까지는 잘 실행이 되다가, HAL_GPIO_Init() 이후에 갑자기 USB 선이 뽑힌 것처럼 Target 보드와의 연결이 끊어졌음(응답없음)으로 터미널에 로그가 나오면서 접속을 시도하다가 종료되는 것을 확인할 수 있었다.

이 GPIO 핀을 사용할 예정이라면 굉장히 유의할 것! 혹시나 핀이 모자란 경우에 + 디버깅이 완료된 경우에 사용하도록 내용이 작성되어있다.

ODR Write와 BSRR Write의 어셈블리 코드

ODR과 BSRR이 아토믹하니 뭐니 이야기가 있었는데, 그게 진짜로 적용되는지 확인해보려고 디스어셈블 해봤다.

 

GPIOB->ODR |= 1 << 14
	ldr r3, [pc, #24]     ; GPIOB의 주소를 r3에 올리기
	ldr r3, [r3, #20]     ; GPIOB->ODR의 값을 r3에 가져오기
	ldr r2, [pc, #20]     ; GPIOB의 주소를 r2로 가져오기
	orr.w r3, r3, #16384	; r3에다가 1 << 14를 OR 연산해넣기
	str r3, [r2, #20]	    ; GPIOB->ODR에 값 다시 대입하기

GPIOB->BSRR = 1 << 14
	ldr r3, [pc, #12]     ; GPIOB의 주소를 r3에 올리기
	mov.w r2, #16384      ; r2에 1 << 14 값을 담기
	str r2, [r3, #24]     ; GPIOB->BSRR에 값 대입하기

명령어의 개수로만 보자면 5 vs 3 으로, 40%의 차이가 난다. (사실 뭐 이거 하나가 그렇게 성능에 영향을 미치지는 않으니깐).

그런데 내가 생각할 때 중요한 포인트는 ODR을 사용하는 방식에서는 GPIOB→ODR의 값을 r3에 담고, 여기에 값을 쓴 다음 다시 GPIOB→ODR 에 담아준다는 것이고, BSRR 방식에서는 값을 만들어서 GPIOB->BSRR에 바로 넣어준다는 점이다. 아토믹한 방식의 장점이 여기에서 나오는 것 같다.


20251028 추가)

CLK 활성화

 

모든 회로에서 데이터를 처리하고 레지스터값을 업데이트하기 위해서는 CLK 신호가 필요하다. 우리의 GPIO에서는 AHB1 과 CLK이 연결되어 있으므로, GPIO를 사용할 때 이 CLK과의 연결을 활성화 해주어야 한다.

 

AHB1 CLK을 연결해주기 위해서는 RCC(Reset and Clock Controller) 의 AHB1과 관련된 Enabler를 건드리면 된다. 아래 이미지에서 우리가 사용하려는 GPIOB는 RCC_AHB1ENR[1] 에 들어있다. 해당 bit에 1을 넣어주면 됨.

 


251102 추가)

GPIO에서 5V 이상의 입력은 어떻게 처리하는가?

Open Drain 방식과 Push-Pull 방식의 차이에 대해서 공부해보다가 5V 이상의 입력을 GPIO가 어떻게 처리하는가에 대해서 찾아보고 정리하였다. 원래 글은 여기에서!

푸시풀과 오픈드레인은 출력과 관련된 회로. 그렇다면 입력은 어떻까? 3.3V 시스템 MCU에 5V 입력이 들어오면 문제가 발생할 수도 있을 것 같은데, 어떻게 처리하고 있는지가 궁금하다!

 

이게 궁금해서 다큐먼트들을 찾아봤는데, 놀랍게도 이미 본 적 있는 키워드들이였다! GPIO를 공부할 때 이 그림을 펼쳐놓고 분석을 했었는데, 제목을 보니 “Five-Volt Tolerance Port” 라고 떡하니 적혀있었다 ㅋㅋㅋ. 앞으로 문서에서처럼 Five-volt Tolerant 에 대해서 FT 라고 표현하겠다.

 

여기에서 $V_{DD\_FT}$ 와 Protection Diode, Schmitt Trigger 가 5V Tolerant를 위해 동작한다.

  • 슈미츠 트리거
    • FT Pin에 붙어있는 슈미츠 트리거는 5V까지 받을 수 있도록 설계가 되어있고, 3.3V와 5V 모두 High로 처리하도록 설계되었다.
    • 애초에 HIGH는 특정 전압이 아니라, “몇 V 이상인가?”를 기준으로 분류하기 때문에, 3.3V 시스템을 기준으로 5V는 모두 HIGH 영역에 속해서 이 전압을 소화할 수만 있다면 문제가 없다. LOW 신호도 0V니깐 호환됨. (3.3V 신호 → 5V 시스템 이였다면 문제가 되었겠지만)
    • FT의 슈미츠 트리거는 대략 7V 까지 버틸 수 있게 설계되었다(고 본 것 같음). 7V가 되기 전에 Protection 처리가 된다.
  • $V_{DD\_FT}$ 와 Protection Diode
    • 5V 정도의 신호야 그냥 안으로 흘려보내지만, 순간적으로 들어오는 높은 전압은 회로를 망가트릴 수 있기 때문에 보호 조치를 해주어야 한다. 그리고 $V_{DD\_FT}$는 입력되는 높은 전압으로부터 소자들을 보호하기 위해 존재한다.
    • $V_{DD\_FT}$가 5.5V 의 전압을 가지고 있다고 하자. 그리고 Diode에 전류가 흐르기 위해서는 0.7V 정도의 전압이 걸린다고 해보자.
    • 그러면 I/O 핀으로 6.2V 이상의 전류가 흘러들어오면 그 이상으로 전압이 상승하려고 하면 다이오드의 전압차가 0.7V가 되면서 (다이오드 Turn On!) Protection Diode 쪽으로 흘러서 $V_{DD\_FT}$ 에 의해 유입되는 신호의 전압이 6.2V 이상으로 오르지 못하도록 한다.
    • 위 과정으로 동작하는 전압 클램핑 덕분에 내부 전압이 위험한 전압 범위 내에 아슬아슬하게 유지하여 회로의 손상을 방지한다.

 

지속적으로 높은 전압이 입력으로 들어온다면 열 발생 등의 문제로 회로가 손상될 수 있다!! + Vdd로 전류가 들어가면서 회로 전체가 와르르맨션이 될 수도 있다. (물론 $V_{DD\_FT}$는 별개라고 아래에 달려있긴 한데, 그래도 보드는 하나의 보드니깐)

 

그리고 문서에도 입출력에 대해서 허용되는 전압에 대해서 작성해뒀다. 웃긴건 FT pin 으로 들어오는 최대전압은 꼭 지켜달라고 되어있다 ㅋㅋㅋㅋ. 최대치는 VDD+3.6V 라고 되어있는 것으로 보인다. 우리 시스템의 Vdd가 3.3V 이니깐, 대략 7V까지가 최대로 GPIO Pin으로 넣을 수 있는 전압이다. 주의할 점은 FT 처리가 되어있지 않은 GPIO핀인 TTa 핀은 4V 라는 것.

 

 

그렇다면 왜 모든 GPIO 핀에 5V에 대한 보호 조치를 하지 않았는가? 에 대해 궁금해서 찾아봤다.

 

  1. FT를 위해서는 3.3V 시스템보다 큰 트렌지스터를 사용해야한다. 근데 이게 트랜지스터의 크기가 커진다는건 누설전류가 많아진다는 것을 의미한다. 즉, 전력 소비가 늘어나기 때문에 저전력 시스템에서는 불리하다.
  2. 아날로그 데이터를 다루는 ADC 기능은 정밀해야한다. 그런데 FT를 위한 트랜지스터에서는 누설전류가 비교적 크게 발생하기 때문에 아날로그 값들이 영향을 받기 쉽다.
  3. 5V 시스템과 연결해야하는 핀은 I2C 통신, SPI 통신 같은 다른 시스템과 신호를 주고받는 기능을 위한 핀들이다. 모든 핀이 FT 특성을 가져야할 필요는 없다.
  4. 트랜지스터의 크기가 크다는 것은 차지하는 공간과 부품 크기가 커진다는 것이고, 비용 증가로 이어진다.

 

결국 Cost 문제!

 

샤라웃

이번 글은 거의 뭐 데이터시트와 레퍼런스메뉴얼만 보고 작성했다. 전체 구조를 이해하는데에 있어서는 클로드가 제일 많이 도와준 것 같다. 고마워 클로드야!

320x100