이글의 전부 또는 일부, 사진, 소스프로그램 등은 저작자의 동의 없이는 상업적인 사용을 금지합니다. 또한, 비상업적인 목적이라하더라도 출처를 밝히지 않고 게시하는 것은 금지합니다.



avr로 문자형 lcd를 제어하는 방법을 다뤘던 필자의 다른 글 http://mcus.tistory.com/35을 참고하시기 바랍니다.

그래픽 lcd 제어하는 방법도 크게 다르지 않습니다.

 

 

본 글에서 다루는 그래픽 lcd는 WS320240C로 제어칩으로 RA8835를 쓰고 있습니다. WS320240C는 20개의 입출력 핀을 가지고 있습니다. 앞의 글 RA8835 GLCD 제어하기(제1편)에서 제시했던 회로도를 다시 보겠습니다.

 

 

 

WS320240의 각 핀 기능은 다음 표와 같습니다.

 

Pin 

 Function

 Pin

 Function

 A0

11 

 /RD

 /CS

12 

 /WR

 DB0

13 

 /RST

 DB1

14 

 BLK

 DB2

15 

 BLA

 DB3

16 

 GND

 DB4

17 

 VEE

 DB5

18 

 VCC

 DB6

19 

 Vo

10 

 DB7

20 

 SEL1

 

SEL1 : 제어 방식을 결정하는 단자입니다. 이 단자가 0(low)이면 이 lcd는 8080 방식으로 제어해야 하고, 이 단자가 1(high)이면 6800 방식으로 제어해야 합니다. 위의 회로도에서 보듯이 본 글에서는 이 단자를 0으로 설정하여 8080 방식으로 동작시킵니다. 앞으로 설명하는 모든 내용은 8080 방식 제어 방법입니다. 약간의 수정만 하면 6800 방식으로 제어할 수도 있습니다.

 

A0 : DB0~DB7의 데이터가 무엇인지 결정하는 역할을 합니다. A0가 0(low)이면 DB0~DB7의 내용은 RA8835에 전달하는 명령이고, A0가 1(high)이면 DB0~DB7의 내용은 RA8835에 전달하는 데이터입니다.

 

/CS : Chip Select로 이 단자가 0(low)일 때에만 RA8835가 동작합니다. 이 단자가 1(high)일 때에는 다른 인터페이스 핀에 있는 데이터들은 RA8835에 아무런 영향을 미치지 않습니다. 따라서 명령을 전달하든 데이터를 전달하든 RA8835에 무엇을 전달하여면 이 단자를 0(low)로 해야 합니다.

 

DB0~DB7 : RA8835로 전달하는 명령 또는 데이터 단자입니다.

 

/RD : RA8835로부터 데이터를 가져 올 때에는 이 단자를 0으로 해야 합니다.

/WR : RA8835로 명령이나 데이터를 전달할 때에는 이 단자를 0으로 해야 합니다.

/RST : reset 단자입니다.

 

BLK : 백라이트 - 극입니다. GND와 연결해 놓았습니다.

BKA : 백라이트 +극입니다. VCC와 연결해 놓았습니다.

 

GND : ground 0V 단자입니다.

VEE : Vo에 공급하기 위해서 -23V를 공급합니다. 이 단자와 GND 사이에 반고정 저항을 연결하여 Vo에 공급함으로써 그래픽 lcd의 contrast를 조정합니다.

VCC : 전원 5V를 연결합니다.

Vo : lcd의 contrast를 조정하기 위한 전압을 공급합니다.

 

 

앞의 글 RA8835 GLCD 제어하기(제1편)에서 STM32CubeMX에서 GPIO를 설정할 때에 DB0~DB7에 PA0~PA7을 연결했고, A0는 PB12, /CS는 PB13, /RD는 PB14, /WR은 PB15에 연결했습니다. 그리고 초기값으로 PA0~PA7은 low를 , PB12~PB15는 high로 설정했습니다.

 

전원 투입 초기에 발생할 수 있는 전기적 잡음의 영향을 조금이라도 덜 받게하려고 /CS, /RD, /WR 신호의 초기값을 high로 했습니다.

 

본 글과에서는 STM32F103과 WD320240C만을 연결하므로 PA0부터 PA7까지를 다른 주변기기와 공유하지 않습니다. 이런 경우에는 프로그램 초기에서 /CS를 low로 해 놓은 채로 MCU와 그래픽 lcd가 PA를 이용해서 자료를 주고 받아도 상관이 없습니다. 그러나 PA0부터 PA7을 사용하는 다른 주변기기가 있다면 이런 방식으로 프로그래밍해서는 안됩니다. 범용성을 생각해서 본 글에서는 /CS를 제어하면서 MCU와 그래픽 lcd 간에 자료를 주고 받는 것으로 프로그래밍하겠습니다.

 

 

 

avr의 경우 어셈블리어로 프로그래밍하면서 클럭 수를 계산하여 시간을 맞추었습니다. STM32F103C8T6을 72MHz로 동작시키면 1사이클은 약 13.8ns가 됩니다. 원칙적으로는 이렇게 시간을 측정해서 위의 Timing Diagrams에 맞추어야 하겠지만, STM32는 C로 프로그래밍하다 보니 컴파일러가 어떤 코드를 생성할지도 모르겠고, 또 STM32의 명령어 실행에 각각 몇 클럭씩 소요되는지를 알아내어 시간을 계산하는 것도 만만치 않습니다. 그냥 순서대로 신호를 주면서 잘 실행되면 그 코드를 쓰기로 합니다.

 

위의 Timing Diagram을 보면 다음과 같은 순서로 신호를 제어하면 될 듯합니다. 앞에서 언급한대로 A0, CS, RD, WR 모두 초기값은 high입니다.

① A0, CS 설정

② RD, WR 신호 설정

③ DB0~DB7에 데이터 출력

④ RD, WR 신호 원상 회복

⑤ A0, CS 원상 회복

 

실제 코드는 약간 달리 다음과 같이 작성합니다.

① DB0~DB7에 데이터 출력

② A0, CS 설정

    CS는 low로, A0는 명령 전달이면 high, 데이터 전달이면 low

③ RD, WR 신호 설정

    MCU에서 RA8835로 보내는 것이면 WR은 low, RD는 high

    MCU가 RA8835로부터 자료를 가져오는 것이라면 WR은 high, RD는 low

④ RD, WR 신호 원상 회복

    RD, WR 모두 high

⑤ A0, CS 원상 회복

    A0, CS 모두 high

 

 

우선 RA8835로 명령을 전달하는 함수 GlcdWriteCommand(), RA8835로 데이터를 전달하는 함수 GlcdWriteData(), RA8835로부터 자료를 가져오는 함수 GlcdReadData() 함수를 만들어 봅니다.

각각의 함수를 HAL 드라이버를 이용하는 방법으로도 만들어 보고, GPIO를 직접 제어하는 방법으로도 만들어 본 다음 두 방법을 비교해 보도록 하겠습니다.

RA8835 GLCD 제어하기(제1편)에서 STMCubeMX 로 프로젝트를 만들 때에 각 핀에 라벨을 부여했습니다. 이에 따라 [inc] 폴더 내의 main.h에 다음과 같이 매크로가 생성되어 있을 것입니다.

#define LED_Pin GPIO_PIN_13
#define LED_GPIO_Port GPIOC
#define DB0_Pin GPIO_PIN_0
#define DB0_GPIO_Port GPIOA
#define DB1_Pin GPIO_PIN_1
#define DB1_GPIO_Port GPIOA
#define DB2_Pin GPIO_PIN_2
#define DB2_GPIO_Port GPIOA
#define DB3_Pin GPIO_PIN_3
#define DB3_GPIO_Port GPIOA
#define DB4_Pin GPIO_PIN_4
#define DB4_GPIO_Port GPIOA
#define DB5_Pin GPIO_PIN_5
#define DB5_GPIO_Port GPIOA
#define DB6_Pin GPIO_PIN_6
#define DB6_GPIO_Port GPIOA
#define DB7_Pin GPIO_PIN_7
#define DB7_GPIO_Port GPIOA
#define A0_Pin GPIO_PIN_12
#define A0_GPIO_Port GPIOB
#define CS_Pin GPIO_PIN_13
#define CS_GPIO_Port GPIOB
#define RD_Pin GPIO_PIN_14
#define RD_GPIO_Port GPIOB
#define WR_Pin GPIO_PIN_15
#define WR_GPIO_Port GPIOB



위의 매크로에 아래 부분에 다음과 같이 WS320240을 제어할 포트를 지정하는 매크로 두 개를 추가합니다.


/* USER CODE BEGIN Private defines */
#define WS320240_DATAPORT DB0_GPIO_Port
#define WS320240_CTRLPORT A0_GPIO_Port
/* USER CODE END Private defines */



이 매크로들을 사용해 함수들을 만들겠습니다.

[Inc] 폴더에 WS320240Display.h를 추가하고 그 안에 다음가 같이 매크로와 함수 원형을 추가합니다.

#define SED1335_DATAPORT  WS320240_DATAPORT
#define SED1335_CTRLPORT  WS320240_CTRLPORT
#define SED1335_A0_BIT    A0_Pin
#define SED1335_CS_BIT    CS_Pin
#define SED1335_RD_BIT    RD_Pin
#define SED1335_WR_BIT    WR_Pin
#define SED1335_RES_BIT   RESET_Pin

void GlcdWriteCommand(uint8_t cmd);
void GlcdWriteData(uint8_t data);
uint8_t GlcdReadData(void);
void SetDataportOutput();
void SetDataportInput();


그래픽 lcd인 WS320240C는 컨트롤러로 RA8835를 사용하고 있지만, 이 칩은 더 유명한 SED1335의 호환 칩이므로 매크로는 SED1335로 시작하는 것으로 사용하겠습니다.

이 GLCD를 제어하는 함수를 두 가지 방법으로 만들어 보겠습니다. 첫번째 방법은 HAL 드라이버를 이용하는 방법이고, 두번째 방법은 앞의 2편에 걸쳐 다루었던 GPIO 설정 방법을 활용하여 직접 GPIO를 제어하는 방법입니다.


1. HAL 드라이버를 사용하여 GPIO 제어하기

프로젝트의 [Drivers/STM32F1xx_HAL_Driver/Include] 폴더의 STM32F1xx_hal_gpio.h 파일에 GPIO를 제어하는데 사용할 구조체 GPIO_InitTypeDef와 많은 매크로 들이 정의되어 있습니다.

typedef struct
{
  uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.
                           This parameter can be any value of @ref GPIO_pins_define */

  uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.
                           This parameter can be a value of @ref GPIO_mode_define */

  uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
                           This parameter can be a value of @ref GPIO_pull_define */

  uint32_t Speed;     /*!< Specifies the speed for the selected pins.
                           This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;


위 구조체 멤버 Pin에 쓸 수 있는 값은 STM32F1xx_hal_gpio.h에 다음과 같이 정의되어 있습니다. 여러 핀을 제어하려면 OR 연산을 하면 됩니다.

#define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
#define GPIO_PIN_1                 ((uint16_t)0x0002)  /* Pin 1 selected    */
#define GPIO_PIN_2                 ((uint16_t)0x0004)  /* Pin 2 selected    */
#define GPIO_PIN_3                 ((uint16_t)0x0008)  /* Pin 3 selected    */
#define GPIO_PIN_4                 ((uint16_t)0x0010)  /* Pin 4 selected    */
#define GPIO_PIN_5                 ((uint16_t)0x0020)  /* Pin 5 selected    */
#define GPIO_PIN_6                 ((uint16_t)0x0040)  /* Pin 6 selected    */
#define GPIO_PIN_7                 ((uint16_t)0x0080)  /* Pin 7 selected    */
#define GPIO_PIN_8                 ((uint16_t)0x0100)  /* Pin 8 selected    */
#define GPIO_PIN_9                 ((uint16_t)0x0200)  /* Pin 9 selected    */
#define GPIO_PIN_10                ((uint16_t)0x0400)  /* Pin 10 selected   */
#define GPIO_PIN_11                ((uint16_t)0x0800)  /* Pin 11 selected   */
#define GPIO_PIN_12                ((uint16_t)0x1000)  /* Pin 12 selected   */
#define GPIO_PIN_13                ((uint16_t)0x2000)  /* Pin 13 selected   */
#define GPIO_PIN_14                ((uint16_t)0x4000)  /* Pin 14 selected   */
#define GPIO_PIN_15                ((uint16_t)0x8000)  /* Pin 15 selected   */
#define GPIO_PIN_All               ((uint16_t)0xFFFF)  /* All pins selected */



구조체 멤버 Mode에 쓸 수 있는 값은 STM32F1xx_hal_gpio.h에 다음과 같이 정의되어 있습니다.

#define  GPIO_MODE_INPUT                        0x00000000U   /*!< Input Floating Mode                   */
#define  GPIO_MODE_OUTPUT_PP                    0x00000001U   /*!< Output Push Pull Mode                 */
#define  GPIO_MODE_OUTPUT_OD                    0x00000011U   /*!< Output Open Drain Mode                */
#define  GPIO_MODE_AF_PP                        0x00000002U   /*!< Alternate Function Push Pull Mode     */
#define  GPIO_MODE_AF_OD                        0x00000012U   /*!< Alternate Function Open Drain Mode    */
#define  GPIO_MODE_AF_INPUT                     GPIO_MODE_INPUT          /*!< Alternate Function Input Mode         */

#define  GPIO_MODE_ANALOG                       0x00000003U   /*!< Analog Mode  */


구조체 멤버 Pull에 쓸 수 있는 값은 STM32F1xx_hal_gpio.h에 다음과 같이 정의되어 있습니다.

#define  GPIO_NOPULL        0x00000000U   /*!< No Pull-up or Pull-down activation  */
#define  GPIO_PULLUP        0x00000001U   /*!< Pull-up activation                  */
#define  GPIO_PULLDOWN      0x00000002U   /*!< Pull-down activation                */



위 구조체 멤버 Speed에 쓸 수 있는 값은 STM32F1xx_hal_gpio.h에 다음과 같이 정의되어 있습니다.

#define  GPIO_SPEED_FREQ_LOW              (GPIO_CRL_MODE0_1) /*!< Low speed */
#define  GPIO_SPEED_FREQ_MEDIUM           (GPIO_CRL_MODE0_0) /*!< Medium speed */
#define  GPIO_SPEED_FREQ_HIGH             (GPIO_CRL_MODE0)   /*!< High speed */

위의 매크로들의 내용을 보면 앞의 글에서 다룬 GPIOx_CRL, GPIOx_CRH 레지스터에 입력할 값이라는 것을 알 수 있습니다. 즉, 구조체 변수인 Mode, Pull, Speed 모두 GPIOx_CRL과 GPIOx_CRH의 CNF[1:0]과 Mode[1:0]에 기록할 값입니다.

STM32F1xx_hal_gpio.h에는 다음과 같은 GPIO 관련된 함수들도 정의되어 있습니다.

void  HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init);
void  HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin);
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);


함수의 이름을 보면 그 함수가 하는 동작을 짐작할 수 있습니다. 주의할 점은 HAL_GPIO_Init() 함수는 여러 핀을 같이 제어할 수 있지만, HAL_GPIO_ReadPin(), HAL_GPIO_WritePin(), HAL_GPIO_TogglePin() 함수 등은 한 번에 하나의 핀만 제어할 수 있습니다.

[Src] 폴더에 WS320240Display.c를 추가하고 그 안에 RA8835에 명령과 데이터를 보내고, 값을 읽어 오는 다음의 함수들을 만듭니다.

#include "STM32F1xx_hal.h"
#include "main.h"
#include "WS320240Display.h"

void GlcdWriteCommand(uint8_t cmd)
{
	SED1335_DATAPORT->ODR = cmd;                                //① DB0~DB7에 명령 출력
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_CS_BIT, RESET); //② 명령->A0 high, CS low
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_WR_BIT, RESET); //③ 쓰기->RD high, WR low
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_WR_BIT, SET);   //④ 신호 원상 회복 RD high, WR high 
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_CS_BIT, SET);   //⑤ A0, CS 원상 회복 A0 high, CS high
}

void GlcdWriteData(uint8_t data)
{
	SED1335_DATAPORT->ODR = data;                               //① DB0~DB7에 데이터 출력
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_CS_BIT, RESET); //② 데이터->CS low
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_A0_BIT, RESET); //          A0 low
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_WR_BIT, RESET); //③ 쓰기->RD high, WR low
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_WR_BIT, SET);   //④ 신호 원상 회복 RD high, WR high 
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_A0_BIT, SET);   //⑤ A0, CS 원상 회복 A0 high
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_CS_BIT, SET);   //                  CS high
}

uint8_t GlcdReadData(void)
{
	uint8_t data;

	SetDataportInput();                                         // PA0~PA7을 입력 모드로 설정
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_CS_BIT, RESET); //② CS low
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_RD_BIT, RESET); //③ 읽기->RD low, WR high
	data = SED1335_DATAPORT->IDR;
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_RD_BIT, SET);   //④ 신호 원상 회복 RD high, WR high 
	HAL_GPIO_WritePin(SED1335_CTRLPORT, SED1335_CS_BIT, SET);   //⑤ A0, CS 원상 회복 CS high
	SetDataportOutput();                                        // PA0~PA7을 출력 모드로 설정

	return data;
}

void SetDataportInput()
{
	  GPIO_InitTypeDef GPIO_InitStruct;

	  GPIO_InitStruct.Pin = DB0_Pin|DB1_Pin|DB2_Pin|DB3_Pin
	                          |DB4_Pin|DB5_Pin|DB6_Pin|DB7_Pin;
	  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	  GPIO_InitStruct.Pull = GPIO_NOPULL;
	  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	  HAL_GPIO_Init(WS320240_DATAPORT, &GPIO_InitStruct);
}

void SetDataportOutput()
{
	  GPIO_InitTypeDef GPIO_InitStruct;

	  GPIO_InitStruct.Pin = DB0_Pin|DB1_Pin|DB2_Pin|DB3_Pin
	                          |DB4_Pin|DB5_Pin|DB6_Pin|DB7_Pin;
	  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	  GPIO_InitStruct.Pull = GPIO_NOPULL;
	  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	  HAL_GPIO_Init(WS320240_DATAPORT, &GPIO_InitStruct);
}

 

 

 

2. GPIO 직접 제어하기

 

이번에는 HAL 드라이버를 쓰지 않고 직접 GPIO를 제어하도록 만드는 방법에 관하여 다루겠습니다.

#include "STM32F1xx_hal.h"
#include "main.h"
#include "WS320240Display.h"

void GlcdWriteCommand(uint8_t cmd)
{
	SED1335_DATAPORT->BRR = 0x00FF;             //① DB0~DB7 clear
	SED1335_DATAPORT->BSRR = cmd;               //   DB0~DB7에 명령 출력
	SED1335_CTRLPORT->BRR = SED1335_CS_BIT;     //② 명령 ->A0 high, CS low
	SED1335_CTRLPORT->BRR = SED1335_WR_BIT;     //③ 쓰기->RD high, WR low
	SED1335_CTRLPORT->BSRR = SED1335_WR_BIT;    //④ 신호 원상 회복 RD high, WR high 
	SED1335_CTRLPORT->BRR = SED1335_WR_BIT;     //⑤ A0, CS 원상 회복 A0 high, CS high
}

void GlcdWriteData(uint8_t data)
{
	SED1335_DATAPORT->BRR = 0x00FF;             //① DB0~DB7 clear
	SED1335_DATAPORT->BSRR = data;              //   DB0~DB7에 데이터 출력
	SED1335_CTRLPORT->BRR = SED1335_CS_BIT;     //② 데이터 ->CS low
	SED1335_CTRLPORT->BRR = SED1335_A0_BIT;     //           A0 low
	SED1335_CTRLPORT->BRR = SED1335_WR_BIT;     //③ 쓰기->RD high, WR low
	SED1335_CTRLPORT->BSRR = SED1335_WR_BIT;    //④ 신호 원상 회복 RD high, WR high 
	SED1335_CTRLPORT->BSRR = SED1335_A0_BIT;    //⑤ A0, CS 원상 회복 A0 high
	SED1335_CTRLPORT->BSRR = SED1335_CS_BIT;    //                  CS high
}

uint8_t GlcdReadData(void)
{
	uint8_t data;

	SED1335_DATAPORT->CRL = 0x44444444;         // PA0~PA7을 입력 모드로 설정
	SED1335_CTRLPORT->BRR = SED1335_CS_BIT;     //② CS low
	asm volatile("NOP");
	asm volatile("NOP");
	SED1335_CTRLPORT->BRR = SED1335_RD_BIT;     //③ 읽기->RD low, WR high
	asm volatile("NOP");
	asm volatile("NOP");
	asm volatile("NOP");
	asm volatile("NOP");
	asm volatile("NOP");
	asm volatile("NOP");
	data = SED1335_DATAPORT->IDR;
	SED1335_CTRLPORT->BSRR = SED1335_RD_BIT;    //④ 신호 원상 회복 RD high, WR high 
	SED1335_CTRLPORT->BSRR = SED1335_CS_BIT;    //⑤ A0, CS 원상 회복 CS high
	SED1335_DATAPORT->CRL = 0x22222222          // PA0~PA7을 출력 모드로 설정

	return data;
}

 

 사실 GlcdWriteCommand() 함수나 GlcdWriteData() 함수 등도 소스의 길이는 비슷해 보이지만, HAL 드라이버를 이용하는 경우는 함수를 호출하는 것이기 때문에 실제로 실행하는 시간은 더 걸립니다.


예를 들어 GPIO를 입력 상태로 만드는 경우 HAL 드라이버를 사용하려면 SetDataportInput() 함수를 호출하는데, SetDataportInput() 함수에서는 GPIOx_CRL과 GPIOx_CRH 레지스터에 디록할 값들을 설정한 다음에 HAL_GPIO_Init() 함수를 호출합니다.


이에 비하여 GPIO를 직접 제어하는 경우에는 SED1335_DATAPORT->CRL = 0x44444444 이 명령 하나로 끝납니다. GPIO를 입력 상태로 전환하는 과정이 너무 빨리 끝나서 데이터를 바로 읽으면 제 값을 가져오지 못합니다. 결국 여러 개의 NOP 명령을 넣어서 어느 정도 시간을 지연시킨 후에 값을 읽어야 제대로 된 값을 읽어 옵니다.

 

HAL 드라이버를 사용하는 것보다 직접 GPIO를 제어하면 실행 속도도 빠르고 코드도 간결해집니다. GPIO 뿐만 아니라 타이머, 인터럽트 등등 모든 기능 실행에서 MCU의 레지스터를 직접 제어하는 것이 유리한 면이 있습니다. 반면에 MCU에 관해 세밀하게 알고 있어야 하고, 소프트웨어 개발에 노력과 시간이 많이 들고 또한 유지, 관리가 어려워질 수도 있다는 문제점이 있습니다.

 

AVR은 초기화라고 할 것도 없이 바로 동작하지만, STM32는 처음 동작시키는 것 자체가 간단하지 않습니다. STMCubeMX로 프로젝트를 만들면 HAL 드라이버를 이용해서 아주 간단하게 MCU 초기화 등을 할 수 있습니다. 뿐만 아니라 HAL 드라이버가 제공해 주는 아주 다양하고 믿을 수 있는 기능들을 쉽게 쓸 수 있습니다. 더우기 칩 제조사가 강력히 지원한다는 의지를 보이고 추진하고 있습니다. 다만, HAL 드라이버 자체의 기능과 함수 등을 파악하는 것도 쉬운 일은 아닙니다. 게다가 HAL 드라이버에게만 의지하다가는 HAL 드라이버가 지원하지 않는 기능은 구현할 생각도 능력도 없어질 수도 있습니다.

 

어떤 방식으로 프로그래밍을 할 것인지는 프로그램을 만드는 사람의 생각과 취향에 따라 결정할 일이라고 봅니다. 필자는 주로 HAL 드라이버를 이용할 생각입니다만, 부분적으로 직접 제어 방식도 활용하겠습니다.

 

다음 글에서는 WS320240을 초기화하고 그래픽으로 영문과 한글을 출력하는 프로그램을 작성할 예정입니다.

블로그 이미지

엠쿠스

Microprocessor(STM32, AVR)로 무엇인가를 만들어 보고자 학습 중입니다.

,