LED0은 ON, LED1은 OFF 시키기 위한 코드를 설계해보겠습니다.
먼저 각 포트의 PIN 속성을 결정합니다. 이번 실습에서는 LED: PB[9:8]을 사용하므로 GPIOB_CRH 레지스터의 [7:0] 비트에 의해 타입이 설정됩니다. LED: PB[9:8]은 GPIOB_CRH 레지스터의 최하위 2bit에 의해 정해지게 됩니다. STM32의 GPIO 설정을 보면 아래와 같습니다.
실습에서는 Open drain 출력에 최대 제한 속도는 2MHz로 하였기 때문에 LED: PB[9:8] -> 0110으로 설정하고 실습을 진행했습니다.
STM32에서는 레지스터 주소를 직접 지정해 GPIO를 제어할 수 있다.
아래 코드는 GPIOB 포트의 8~15번 핀의 모드와 속도를 설정하는 제어 레지스터를 의미하며, 출력 데이터 레지스터로, 각 핀의 High(1)/Low(0) 상태를 결정한다.
#define GPIOB_CRH (*(int *)0x40010C04)
#define GPIOB_ODR (*(int *)0x40010C0C)
#include <device_driver.h>
// 여기에 사용자 임의의 define을 작성하시오
// define 앞에 () 빼면 우선 순위 문제가 생길 수 있음.
#define GPIOB_CRH (*(int *)0x40010C04)
#define GPIOB_ODR (*(int *)0x40010C0C)
void Main(void)
{
// 이 부분은 임의로 바꾸지 마시오
RCC_APB2ENR |= (1<<3);
// GPB[9:8]을 출력 모드로 설정하시오
// (*(int *)0x40010C04) = 0x00000066;
GPIOB_CRH = 0x00000066;
// GPB[9:8]에 LED0은 OFF, LED1은 ON 시키도록 설정하시오
// GPIOB_ODR (*(int *)0x40010C0C) = 0x00000200;
GPIOB_ODR = 0x00000200;
// 0x200으로 써도 됨
}
/*
if define가 없다면?
= 0x00000066;
= 0x00000200;
이런 코드를 실행하게 됨
*/
#include "device_driver.h"
void Main(void)
{
volatile int i;
Uart_Init(115200);
Uart_Printf("CMSIS Based Register Define\\n");
// 이 부분은 수정하지 말 것
RCC->APB2ENR |= (1<<3);
RCC->APB2ENR |= (1<<2);
// LED Pin을 출력으로 설정
// 0~7은 LOW 사용 0110으로 켜야하므로 6
GPIOA->CRL = 0x600;
for(;;)
{
// LED 모두 ON
GPIOA->ODR = 0x0;
for(i=0; i<0x40000; i++);
// LED 모두 OFF
GPIOA->ODR = 0x4;
for(i=0; i<0x40000; i++);
}
}
Logic Analyzer 보드의 0~7 포트에 와이어를 연결하여 해당 Channel에 파형을 측정할 수 있습니다. STM32 보드의 Reset Switch를 누른 상태로 Start를 누르면 아래와 같이 파형을 측정할 수 있습니다.
이때 Trigger 설정에서 Channel을 LED0으로 설정하고 Falling Edge부터 시작해 3초동안 Pulse를 측정하면 위와 같이 파형이 나오게 됩니다.
Channel을 LED4로 바꾸고 Logic Analyzer 보드의 4번에 와이어를 연결하여 다른 Channel에서 파형을 측정할 수 있습니다. 파형을 보면 LED가 반복적으로 ON/OFF 되는 것을 확인할 수 있습니다.
다음은 CMSIS 방식으로 LED를 켜는 프로그램을 알아보도록 하겠습니다. GPIOB는 GPIO_TypeDef 구조체 포인터에 정의되어 있고 CRH, CRL, IDR, ODR은 해당 구조체 안에 멤버입니다.
#include "device_driver.h"
/* LED0 -> ON, LED1 -> OFF */
void Main(void)
{
RCC->APB2ENR |= (1<<3);
GPIOB->CRH = 0x66<<0;
GPIOB->ODR = 0x1<<9;
}
코드에서 GPIOB->CRH = 0x66<<0 부분을 보면 GPIOB->CRH의 0번째 bit부터 01100110으로 만드는 것을 알 수 있습니다(Output, O/D). 또한 GPIOB->ODR 부분에서 GPIOB->ODR의 8번째 bit을 1로 만드는 것을 확인할 수 있습니다(LED0->on, LED1->off).