들어가며
이 글에서 다룰 예제는 버튼스위치를 이용해서 LED를 켜고 끄는 코드입니다. GPIO 입/출력 관련 설정을 하고 GPIO 데이터 레지스터에 접근하여 값을 읽기도 하고 쓰기도 합니다. 우리는 이 예제를 통해서 레지스터 설정과 접근 방법에 대한 기본을 이해할 수 있을 것입니다. 실습에 필요한 재료는 개발 보드 EK-TM4C123GXL 이고 별다른 추가 회로는 필요하지 않습니다.
이번 글에서는 GPIO 초기 설정 위주로 코드를 해설하고자 합니다.
예제 코드
#include "tm4c123gh6pm.h"
#include <stdint.h>
#define PF4 (*((volatile unsigned long *) 0x40025040)) // SW1
void Switch_Init(void)
{
volatile unsigned long delay;
SYSCTL_RCGC2_R |= 0x00000020;
delay = SYSCTL_RCGC2_R;
// SW1
GPIO_PORTF_AMSEL_R &= ~0x10;
GPIO_PORTF_PCTL_R &= ~0x000F0000;
GPIO_PORTF_DIR_R &= ~0x10;
GPIO_PORTF_AFSEL_R &= ~0x10;
GPIO_PORTF_DEN_R |= 0x10;
GPIO_PORTF_PUR_R |= 0x10;
}
unsigned long Switch_Input(void)
{
return PF4;
}
int main(void)
{
Switch_Init();
GPIO_PORTF_DIR_R |= 0x02;
GPIO_PORTF_DEN_R |= 0x02;
while(1)
{
if (Switch_Input())
{
PF1 = 0x02;
}
else
{
PF1 = 0x00;
}
}
return 0;
}
동작 정의하기
이 프로그램은 다음과 같은 매우 간단한 동작을 합니다.
- SW1 버튼을 누르면 LED가 켜진다.
- SW1 버튼에서 손을 떼면 LED가 꺼진다.
개발 보드 EK-TM4C123GXL에 준비된 SW1는 GPIOF4에 연결되어 있습니다. 그리고 LED는 GPIOF1에 연결된 것을 사용할 것입니다. 따라서 GPIO 핀 설정은 아래와 같이 이뤄져야 합니다.
- GPIOF4의 경우
- 디지털 핀으로 사용
- 아날로그 핀 비활성화
- 핀 기능을 GPIO로 설정
- 입력 핀으로 사용
- 풀 업 활성화 (자세한 내용은 풀 업 관련 설정을 참고)
- GPIOF1의 경우
- 디지털 핀으로 사용
- 아날로그 핀 비활서오하
- 핀 기능을 GPIO로 설정
- 출력 핀으로 사용
여기서 우리는 GPIOF4 핀 설정 과정에 대해서 자세히 살펴보도록 하겠습니다.
GPIO 초기화 하기
예제 코드의 Switch_Init()
함수에 정의된 GPIO 초기화 코드를 한 줄씩 해석해보겠습니다.
Run Mode Clock Gating Control Register 2
SYSCTL_RCGC2_R
레지스터는 Run 모드에서 이 레지스터에 할당된 각 주변 장치로 클럭 전달 여부를 제어합니다. SYSCTL_RCGC2_R
에 할당된 주변 장치는 GPIOA부터 GPIOF까지 그리고 UDMA, USB0입니다.
이 중 우리는 GPIOF를 사용하고자 하므로 레지스터에 값 0x00000020를 set 합니다.
SYSCTL_RCGC2_R |= 0x00000020;
중요한 것은 이 레지스터에 값을 주고 나면 값이 적용되기까지 3 시스템 클록의 지연 시간이 필요합니다. 따라서 곧바로 GPIOF 포트 설정을 하는 것이 아니라 적당한 지연을 발생시켜서 3 클록 이상의 시간을 벌도록 합니다. 예제 코드에서는 아래와 같은 의미 없는 코드를 사용하고 있습니다.
delay = SYSCTL_RCGC2_R;
GPIO Analog Mode Select
GPIO_PORTF_AMSEL_R
레지스터는 GPIOF 포트의 아날로그 입/출력 회로의 절연 여부를 제어합니다. 0이면 연결을 끊고, 1이면 연결합니다. 기본 값은 0입니다. 그래서 디지털 입/출력만 사용할 것이라면 굳이 설정해주지 않아도 될 것 같지만 확실히 하기 위해서 아래와 같이 사용하고자 하는 핀 설정 값을 clear 합니다.
GPIO_PORTF_AMSEL_R &= ~0x10;
GPIO Port Control
GPIO_PORTF_PCTL_R
레지스터는 GPIOF 포트의 기능을 설정할 수 있으며 GPIO_PORTF_AFSEL_R
레지스터와 함께 사용됩니다. 대부분의 핀은 기본 값이 0으로 기능이 GPIO로 설정되어 있습니다. 따라서 단순 GPIO를 사용하고자 한다면 굳이 초기화할 필요 없습니다. 그래도 확실히 하기 위해서 예제 코드에는 초기화 과정이 있습니다. GPIOF의 4번 핀을 GPIO 기능으로 사용하기 위해서 GPIO_PORTF_PCTL_R
레지스터의 PMC4 [16:19] 위치의 값을 모두 clear 합니다.
GPIO_PORTF_PCTL_R &= ~0x000F0000;
GPIO Direction
GPIO_PORTF_DIR_R
레지스터는 각 GPIO 핀의 입/출력 방향을 설정할 때 사용합니다. 0은 입력, 1은 출력입니다. 스위치로 사용할 핀이므로 4번째 비트를 clear 하여 입력으로 설정합니다.
GPIO_PORTF_DIR_R &= ~0x10;
GPIO Alternate Function Select
GPIO_PORTF_AFSEL_R
레지스터는 GPIO의 기능을 사용 여부를 설정합니다. 앞서 살펴봤던 GPIO Port Control 레지스터와 함께 사용됩니다. GPIOPCTL 레지스터에서 기능을 설정했다면, GPIOAFSEL 레지스터에서는 그 기능을 사용할 것인지를 결정하는 역할을 합니다. 0은 사용 안 함, 즉 GPIO로써 사용함을 의미하고, 1은 GPIOPCTL에서 설정한 기능을 사용하는 것을 의미합니다. 예제 코드에서는 GPIO로 사용하기 위해 4번째 비트를 clear 합니다.
GPIO_PORTF_AFSEL_R &= ~0x10;
GPIO Digital Enable
GPIO_PORTF_DEN_R
레지스터는 GPIO를 디지털 핀으로 사용함을 설정하는 역할을 합니다. 기본 값은 0으로 설정됩니다. 예제에서는 디지털 핀으로 사용할 것이기 때문에 1로 set 합니다. 만약 아래 목록에 있는 핀 설정 값을 바꾸기 위해서는 GPIOLOCK 레지스터와 GPIOCR 레지스터 설정 값을 변경해주어야 합니다.
우리가 사용하고자 하는 PF4는 위 리스트에 없으므로 바로 set 해주어도 됩니다.
GPIO_PORTF_DEN_R |= 0x10;
GPIO Pull-Up Select
GPIO_PORTF_PUR_R
은 GPIO 핀의 pull up 설정을 하는 레지스터입니다. 원래 제공되던 예제에는 없는 코드인데요, 개발 보드에 있는 SW1 스위치를 사용하기 위해서 추가한 코드입니다. 개발보드 회로도를 살펴보면 스위치 한쪽은 보드의 PF4에 연결되고 다른 한쪽은 GND에 연결되어 있습니다.
그래서 평상시에는 PF4에 High 신호가 입력되어야 하고, 버튼스위치를 누르면 Low 신호가 입력되는 게 정상입니다. 그러나 위 회로를 보면 스위치가 눌리지 않았을 때 USR_SW1 단자로 High 신호가 들어갈 전압이 없는 것을 알 수 있습니다. 그럴 때 사용하는 것이 풀 업(pull up) 저항입니다. 전원과 연결된 적당한 크기의 저항을 SW1 상단에 연결해준다면 평시에 High 신호가 USR_SW1 단자 쪽으로 들어가는 것을 확신할 수 있습니다. 그런데 굳이 회로를 추가하지 않아도 GPIOPUR
레지스터를 set 해주기만 해도 MCU 칩 내부에 있는 풀 업 저항이 연결됩니다. 스위치가 정상 동작하도록 코드에 set 하는 과정을 추가합니다.
GPIO_PORTF_PUR_R |= 0x10;
정리
여기까지가 스위치와 연결된 GPIO F 4번 핀의 초기 설정입니다. 이 과정을 요약하면 아래와 같습니다.
- 클럭 공급 설정
- 아날로그 사용 여부 설정
- 기능 설정
- 기능 사용 여부 설정
- 입/출력 설정
- 디지털 사용 여부 설정
- 풀 업 설정
설정 순서가 정해져 있는지는 잘 모르겠습니다. 위 과정에서 클럭 공급 설정을 제일 먼저 해줘야 하는 것 말고는 예제 코드와 똑같은 순서가 아니어도 된다고 생각합니다. 기회가 된다면 다른 글에서 설정 순서에 따른 결과를 비교해보도록 하겠습니다.
'연구 노트 > Embedded' 카테고리의 다른 글
어셈블리 파일 확장자 .s와 .S는 다르다. (2) | 2020.12.25 |
---|---|
[TM4C] ADC 초기화 과정 (0) | 2020.12.10 |
CCS 프로젝트 include 경로 설정 (4) | 2020.11.18 |
[Modulabs] 2020년 임베디드랩 시즌1 마지막 프로젝트 (0) | 2020.11.13 |
[TM4C] TivaWare 프로그래밍 모델 (0) | 2020.11.02 |