티스토리 뷰
AVR 입문 과정에서 했던것처럼 이번 글에서도 GPIO를 제어하여 LED를 깜빡이게 하는 방법에 대해서 설명하도록 하겠다.
가지고 있는 보드에 LED하나가 PC13핀에 연결되어 있다.
회로도에는 다음과 같이 연결되어 있다고 보여준다.
LED의 anode핀은 Vcc에 연결되어 있고, cathod 핀은 저항을 통해 칩의 PC13핀에 연결된다. 그렇다는 얘기는 PC13핀의 전압이 0일때 LED에 불이 들어온다는 뜻이다.
코드를 작성하기 전에 STM32F103 칩이 어떻게 생겼는지 전체 블럭도를 한번 훓어보기로 하자.
빨간색 박스로 표시되어 있는 부분이 가장 중요한 ARM core 블럭이다. 그림에서처럼 Bus Matrix를 통해서 Flash memory, SRAM, peripheral 블럭들과 연결되는 것을 볼 수 있다.
파란색 박스는 APB2 버스에 연결되어 있는 주변장치들이다. 어떤 블럭들이 연결되어 있는지 파악해본다.
초록색 박스또한 주변 장치들이 연결되어 있는데 APB1 버스에 연결되어 있다. 블럭도를 자세히 보면 알겠지만 APB1버스의 최대 속도는 APB2 버스의 절반인것으로 표시되어 있다. 상대적으로 느린 주변 장치들이 연결되어 있음을 예상할 수 있다.
요즘의 임베디드 시스템은 대부분 배터리로 동작되는 구조를 가지므로 전력 소비에 상당히 민감할 수 밖에 없다. 예를 들면 하드웨어 크기를 작게하기 위하여 수은전지로 동작 되도록 만들었다면 전력 소비량에 따라 몇년 동안 동작 될 수도 있지만, 아무생각 없이 시스템을 만들게 되면 몇달도 못가서 배터리가 수명을 다할 것이다. 따라서 꼭 필요한 시간에 꼭 필요한 블럭들만 동작 시키기록 신경을 써야 한다. 이러한 요구조건을 제공하기 위하여 기본적으로 각각의 peripheral 블럭들은 disable 된 상태로 동작된다.
따라서 특정 블럭을 사용하고자 할때는 반드시 그 블럭을 enable 시켜주는 동작을 제공하여야 한다.
STM32F103에서는 RCC라는 것을 이용하여 각각의 peripheral들을 제어할 수 있도록 한다.
Datasheet의 RCC관련 레지스터에 설명은 다음과 같이 되어 있다.
위의 블럭도를 보면 알겠지만 GPIOC블럭은 APB2 버스에 연결되어 있다. 따라서 RCC 레지스터 중에서 RCC_APB2ENR 레지스터를 찾아보면 IOPCEN 비트의 위치를 확인할 수 있다.
IOPCEN 비트값을 '1'로 만들면 해당 블럭에 클럭이 공급되면서 그 블럭이 정상적으로 동작될 수 있는 상태로 변환된다.
이제 GPIO_C 블럭이 정상 동작 될 수 있는 조건이 되었음으로 GPIO 블럭을 제어하여 원하는 핀을 output 모드로 설정하도록 하겠다.
GPIO 핀 모드를 설정하기 위하여 CR레지스터를 이용하는데 위의 그림에 보이는 것처럼 각 GPIO 포트당 16개의 핀이 할당되고 있음을 알 수 있다.
한 핀에 대해서 4비트값을 이용하여 모드 설정을 할 수 있다.
이번 예제 프로젝트에서는 MODE 비트값을 '10'으로 하고 CNF비트값을 '00'으로 설정하도록 하겠다.
원하는 핀을 output 모드로 설정하였다면, 해당 핀의 값을 제어하기 위하여 ODR 레지스터를 이용하면 된다.
LED가 PC13에 연결되어 있기 때문에 위의 그림에서처럼 13번 비트값을 0, 1로 만들면 LED를 점멸할 수 있다.
RCC와 GPIO 관련해서 자세한 내용은 datasheet를 참고하면 된다. 인터넷을 찾아봐도 dataseet만큼 자세히 설명되어 있는곳은 없으므로 최대한 datasheet 문서를 이용하기 바란다.
그럼 이제, 위에서 알아낸 내용을 가지고 GPIO 기능을 이용하여 실제 LED를 점멸 시키는 코드를 작성해 보도록 하겠다.
먼저, GPIO_C 모듈을 사용하기 위하여 RCC 레지스터를 이용하는 코드부터 만들어 본다.
헤더 파일과 그 안에 define 된 내용은 이 글의 마지막에 첨부된 파일을 참고하면 된다.
rcc_apb2enable()을 이용하여 APB2 버스에 연결되어 있는 블럭들을 enable 시키도록 한다.
다음으로는 GPIO의 모드 설정하는 코드를 만들어 본다.
Memory map에서 GPIO의 주소를 찾아보면 다음과 같이 되어 있다.
위의 그림에서 보다시피 0x40010800에서부터 GPIO가 시작되는데 각각의 크기가 0x400 인것을 알 수 있다.
따라서 헤더 파일에 다음과 같이 GPIO 레지스터의 base 주소와 offset값을 설정한다.
그리고, output 모드로 설정하는 코드는 다음과 같다.
Output 모드를 설정하기 위한 gpio_set_outmode() 함수는 GPIO 블럭을 지정하는 port와, 몇번째 핀을 output으로 설정할지 결정하는 pin과 모드를 설정하는 cfg, mode를 input argument로 받게 되어 있다.
6번 줄은 port가 몇번째인가에 따라 gpio 구조체의 포인터 주소를 계산하는 코드이다.
9번줄은 GPIO 레지스터중 모드를 설정하는 CR레지스터가 두개 있는데 그중에 어떤 레지스터를 사용해야 되는지 결정하기 위한 코드이다. 0~7까지는 하위 32비트 레지스터를 사용하고 8~15는 상위 32비트 레지스터를 사용하므로 입력으로 들어온 port를 8로 나눈 결과값에 따라 하위, 상위 레지스터를 선택하게 된다.
10번줄은 핀의 값에 따라 해당 위치의 4비트 값을 일단은 clear 하는 코드이다.
11번 줄은 cfg와 mode 값을 가지고 핀에 해당되는 4비트 값을 설정하는 코드이다.
12번 줄은 설정된 값을 레지스터에 써 주는 코드이다.
Output 모드로 설정된 핀의 값을 변하게 하는 것은 ODR레지스터를 이용해서 제어하면 된다.
gpio_out_toggle()을 이용하면 해당 핀을 토글 시킬 수 있게 된다.
그럼, 위의 3개 API를 이용해서 LED를 점멸시켜 보도록 하겠다.
delay() 함수는 정확한 시간을 지연시켜 주는 코드가 아니고, LED를 눈으로 보았을 때 토글 되는지 확인을 쉽게 하기 위하여 적당하게 설정된 값이다.
main()를 위와 같이 만들고 프로젝트를 빌드하여 보드에서 실행 시키면 PC13에 연결되어 있는 LED가 점멸하는 모습을 볼 수 있을 것이다.
'ARM Cortex-M' 카테고리의 다른 글
| UART (0) | 2017.02.18 |
|---|---|
| Clock 설정 (0) | 2017.02.17 |
| Start up 2 (6) | 2017.02.12 |
| Start up (17) | 2017.02.11 |
| 디버거/프로그래머 연결 (0) | 2017.02.11 |
gpio.zip