[MSP430] Digital I/O (GPIO)

pikamon·2020년 12월 17일
0

MSP430

목록 보기
4/13

본 글은 MSP430G2553 MCU를 기준으로 작성되었습니다.
세부적인 내용은 제품군마다 조금씩 다를 수 있습니다.


1. GPIO란?

GPIO란 General Purpose Input Output 약자로, 사용자가 SW를 통해 직접 용도와 동작을 정의할 수 있는 디지털 신호 핀을 의미한다.

MSP430에서는 GPIO를 GPIO 포트와 GPIO 핀으로 구분한다. 최대 8개의 GPIO 포트를 가질 수 있으며, 한 포트 당 최대 8개의 핀을 가질 수 있다. GPIO 포트와 핀의 수는 제품군마다 다르다.

MSP-EXP430G2ET 보드에는 20핀짜리 MSP430G2553 MCU가 붙어있으며, 아래 그림을 보면 총 2개의 GPIO 포트(P1, P2)와 총 16개의 GPIO 핀(P1.0~7, P2.0~7)이 있는 것을 볼 수 있다.

2. GPIO 핀 구조

아래 그림은 MSP430G2553 MCU의 P1.0에 해당하는 GPIO 회로이다.

지긋이 회로를 해석해보면 PxDIR에 의해 Direction이 설정되면서부터 PxOUT에 설정된 값이 핀 바깥(맨 오른쪽의 육각형 모양)으로 나가기까지, 혹은 외부로부터 들어온 신호가 PxIN 레지스터로 들어가기까지의 일련의 과정들을 살펴볼 수 있다.

눈에 띄는 점은, 그림 상단에 보면 제목이 'P1.0~2에 대한 핀 회로도'라고 나와 있는데, 이는 같은 GPIO라도 핀마다 구조가 조금씩 다르기 때문이다.

핀마다 회로가 다른 이유는 각 핀에 매핑되어 있는 Alternate Function이 각각 다르기 때문인데, 이를 테면 MSP430G2553 기준으로 P1.4 핀에는 JTAG Test Clock(TCK) 기능이, P1.5 핀에는 JTAG Test Mode Select(TMS) 기능이 AF로 매핑되어 있기 때문에, 각 기능에 따라 회로가 다를 수 밖에 없다.

물론 본 글에서는 AFIO가 아닌 GPIO로서 사용할 것이므로, 멀라두 댄당..

3. 관련 레지스터

GPIO 제어에서는 총 6개의 레지스터가 사용되며, 아래와 같다.

  • PxDIR - GPIO Direction Register
  • PxIN - GPIO Input Register
  • PxOUT - GPIO Output Register
  • PxREN - GPIO Pullup/Pulldown Resistor Enable Register
  • PxSEL - GPIO Function Select Register 1
  • PxSEL2 - GPIO Function Select Register 2

Px에서 x는 포트 번호를 뜻한다. P1 포트에 있는 핀을 다루고자 한다면 P1 레지스터를, P2 포트에 있는 핀을 다루고자 한다면 P2 레지스터를 이용한다.

각 레지스터의 길이는 16비트이지만, 포트 당 8개의 핀을 가지므로 하위 8비트만 사용된다. 하위 8비트에 MSB부터 LSB까지 순서대로 Px.7, Px.6, ..., Px.1, Px.0 핀이 매핑된다.

< P1 레지스터>
     7      6      5      4      3      2      1      0  
| P1.7 | P1.6 | P1.5 | P1.4 | P1.3 | P1.2 | P1.1 | P1.0 | 

< P2 레지스터>
     7      6      5      4      3      2      1      0  
| P2.7 | P2.6 | P2.5 | P2.4 | P2.3 | P2.2 | P2.1 | P2.0 | 

각 레지스터의 용도에 대해 알아보자.

1. PxDIR

GPIO의 방향을 설정하는 레지스터이다. 해당 핀의 자리에 비트가 0으로 설정되면 입력 모드로 설정되어 외부로부터의 전기 신호를 받아들일 준비가 되며, 비트가 1로 설정되면 출력 모드로 설정되어 외부로 전기 신호를 보낼 준비가 된다. 코드로 나타내면 아래와 같다.

P1DIR &= ~0x01; // P1.0 핀의 방향을 Input으로 설정
P2DIR |= 0x80;  // P2.7 핀의 방향을 Output으로 설정

2. PxIN

GPIO의 Direction이 Input으로 설정되면 GPIO 핀으로부터 들어온 신호가 값으로 변환되어 PxIN 레지스터에 저장된다. 예를 들어 P1.3 핀에 값이 들어왔다고 하면 아래와 같이 이용할 수 있다.

P1DIR &= ~0x08;              // P1.3을 Input으로 설정

if ((P1IN & 0x08) == 1)      // P1.3의 레벨이 HIGH이면 실행됨
{
	...
}
else if ((P1IN & 0x08) == 0) // P1.3의 레벨이 LOW이면 실행됨
{
	...
}

3. PxOUT

GPIO의 Direction이 Output으로 설정되면 PxOUT 레지스터에 저장된 값이 신호로 변환되어 GPIO 핀으로 출력된다. 예를 들어 P2.2 핀으로 HIGH를 출력하고 싶으면 아래와 같이 설정할 수 있다.

P2DIR |= 0x04; // P2.2를 Output으로 설정
P2OUT |= 0x01; // P2.2에 HIGH를 출력

4. PxREN

GPIO 핀의 풀업/풀다운을 설정하는 레지스터이다. PxREN 레지스터가 1로 설정되면 PxOUT 레지스터는 해당 핀을 풀업으로 설정할지 풀다운으로 설정할지를 나타내는 레지스터로 사용된다고 나와있다. 정확히는 모르겠지만, PxREN 레지스터가 활성화되면 출력 핀의 값을 풀업/풀다운 저항을 통해 구현하는 것 같다.

5. PxSEL, PxSEL2

해당 핀을 GPIO로 사용할지 AFIO로 사용할지를 설정하는 레지스터이다. 1로 설정하면 AFIO로 사용하겠다는 뜻이며, 0으로 설정하면 GPIO로 사용한다는 뜻이다.

PxSEL은 PxSEL이 있고 PxSEL2가 있는데, 하나의 핀에서 지원하는 AF가 많아지면서 SEL2 레지스터가 추가된 듯하다. 용도에 따라 매뉴얼을 참고하여 해당 레지스터를 설정하면 될 것 같다.

앞의 Basic Clock Module+ 글에서 본 레지스터를 사용하는 예제를 다룬 적이 있다. P1SEL 레지스터의 값을 0x11로 설정함으로써 P1.0, P1.4 핀으로부터 각각 ACLK, SMCLK이 출력되는 예제를 다루어보았다. 기억 안날까봐 아래에 코드를 가져왔다.

P1DIR |= 0x13; // P1.0, P1.1, P1.4를 output으로 설정
P1SEL |= 0x11; // P1.0, P1.4 핀을 AF로 설정

4. 예제

각 레지스터 설명에서 사용법을 언급하였으며, 간단히만 더 짚고 넘어가겠다.

  1. Output 핀 토글
  2. Input 핀 폴링에 의한 Output 핀 설정

1. Output 핀 토글

MSP-EXP430G2ET 보드에는 P1.0 핀에 LED(D1)가 연결되어 있어 핀을 HIGH로 설정하면 LED에 불이 들어오는 것을 볼 수 있다.

아래는 일정 주기마다 LED에 출력되는 값을 토글하여 LED를 점멸시키는 예제이다.

#include <msp430.h>

int main(void)
{
    volatile unsigned int i;
    WDTCTL = WDTPW | WDTHOLD; // 와치독 비활성화

    P1DIR |= 0x01;            // P1.0의 핀을 출력으로 설정

    while (1)
    {
        P1OUT ^= 0x01;        // P1.0 토글

        i = 50000;
        do (i--);
        while (i != 0);
    }
}

위의 코드를 실행시키면 LED가 일정 주기마다 점멸하는 것을 볼 수 있다.

2. Input 핀 폴링에 의한 Output 핀 설정

MSP-EXP430G2ET 보드에는 P1.3 핀에 버튼식 스위치가 연결되어 있어 버튼을 누르면 핀에 입력 신호가 들어가게 된다.

#include <msp430.h>

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // 와치독 비활성화

    P1DIR |= 0x01;              // P1.0의 핀을 출력으로 설정
    P1DIR &= ~0x08;             // P1.3의 핀을 입력으로 설정 (사실 안해줘도 됨)

    while (1)
    {
        if ((P1IN & 0x08) == 0) // P1.3 Button Push
        {
            P1OUT |= 0x01;      // P1.0 LED ON
        }
        else
        {
            P1OUT &= ~0x01;     // P1.0 LED OFF
        }
    }
}

버튼을 떼면 입력이 HIGH로 들어가다가 누르면 LOW로 들어간다. LED는 1로 설정되면 점등, 0으로 설정되면 소등된다.

부록. LED, Button 회로도

MSP-EXP430G2ET의 LED, Button 관련 회로도를 첨부하였다.

profile
개발자입니당 *^^* 깃허브 https://github.com/pikamonvvs

0개의 댓글