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


1. RA8835 초기화



RA8835를 초기화하는 과정은 상당히 복잡합니다. SED1335로 검색하면 인터넷 상에서 어렵지 않게 초기화 함수를 구할 수 있습니다. 매크로를 사용해서 초기화하면 초기화 과정을 좀 더 쉽게 이해할 수 있습니다. 다음과 같은 매크로들과 함수 원형들을 포함하는 헤더 파일 WS320240Display.h를 추가합니다.

/*
 * WS320240Display.h
 *
 *  Created on: 2018. 11. 18.
 *      Author: Jeong
 */

#ifndef WS320240DISPLAY_H_
#define 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

#define BITSPERBYTE					8
#define	CHARACTER_WIDTH				BITSPERBYTE
#define	CHARACTER_HEIGHT			8
#define	ASCII_FONTSIZE_X			8
#define	ASCII_FONTSIZE_Y			16
#define	ASCII_FONTSIZE				(ASCII_FONTSIZE_X * ASCII_FONTSIZE_Y / BITSPERBYTE)
#define	HANGEUL_FONTSIZE_X			(ASCII_FONTSIZE_X * 2)
#define	HANGEUL_FONTSIZE_Y			ASCII_FONTSIZE_Y
#define	HANGEUL_FONTSIZE			(HANGEUL_FONTSIZE_X * HANGEUL_FONTSIZE_Y / BITSPERBYTE)

#define	GLCD_RESOLUTION_X			320
#define	GLCD_RESOLUTION_Y			240
#define	SCREEN1_ADDR				0
#define	SCREEN2_ADDR				(GLCD_RESOLUTION_X / CHARACTER_WIDTH * GLCD_RESOLUTION_Y / CHARACTER_HEIGHT)

#define	SYSTEMSET_COMMAND			0x40
#define	SYSTEMSET_INTERNALCGRAM		0			// P1
#define	SYSTEMSET_EXTERNALCGRAM		1
#define	SYSTEMSET_CG32CHAR			0
#define	SYSTEMSET_CG64CHAR			2
#define	SYSTEMSET_HEIGHT8PIXEL		0
#define	SYSTEMSET_HEIGHT16PIXEL		4
#define	SYSTEMSET_SINGLEPANNEL		0
#define	SYSTEMSET_DUALPANNEL		8
#define	SYSTEMSET_TOPLINECORRECT	0
#define	SYSTEMSET_NOTOPLINECORRECT	0x20
#define	SYSTEMSET_LCD				0
#define	SYSTEMSET_TV				0x40
#define	SYSTEMSET_NORMAL			0
#define	SYSTEMSET_ADDITIONALSHIFT	0x80
#define	SYSTEMSET_FXVALUE			7			// P2
#define	SYSTEMSET_16LINEDRIVE		0
#define	SYSTEMSET_TWOFRAMEDRIVE		0x80
#define	SYSTEMSET_FYVALUE			7			// P3
#define	SYSTEMSET_CR				(GLCD_RESOLUTION_X / BITSPERBYTE - 1)		//P4
#define	SYSTEMSET_TCR				(SYSTEMSET_CR + 4)							// ((F_CPU / GLCD_RESOLUTION_Y / REFRESH_RATE - 1) / 9)	//P5
#define	SYSTEMSET_LF				GLCD_RESOLUTION_Y - 1						// P6
#define SYSTEMSET_APL   			((GLCD_RESOLUTION_X / BITSPERBYTE) % 256)	// P7
#define SYSTEMSET_APH   			((GLCD_RESOLUTION_X / BITSPERBYTE) / 256)	// P8

#define	SLEEPIN_COMMAND				0x53

#define	DISPLAY_COMMAND				0x58
#define	DISPLAY_OFF					0
#define	DISPLAY_ON					1
#define	DISPLAY_NOFLASH				1
#define	DISPLAY_FLASH32HZ			2
#define	DISPLAY_FLASH64HZ			3
#define	DISPLAY_FIRSTSCREEN_BIT		2
#define	DISPLAY_SECONDSCREEN_BIT	4
#define	DISPLAY_THIRDSCREEN_BIT		6

#define	SCROLL_COMMAND				0x44
#define SED1335_SAD1L	   			(SCREEN1_ADDR % 256)
#define SED1335_SAD1H   			(SCREEN1_ADDR / 256)
#define SED1335_SL1   				(GLCD_RESOLUTION_Y - 1)
#define SED1335_SAD2L   			(SCREEN2_ADDR % 256)
#define SED1335_SAD2H   			(SCREEN2_ADDR / 256)
#define SED1335_SL2   				(GLCD_RESOLUTION_Y - 1)

#define	CSRFORM_COMMAND				0x5D
#define	CSRFORM_CRX					7
#define	CSRFORM_CRY					7
#define	CSRFORM_UNDERBAR			0
#define	CSRFORM_BLOCK				0x80

#define	CSRDIR_COMMAND				0x4C
#define	CSRDIR_RIGHT				0
#define	CSRDIR_LEFT					1
#define	CSRDIR_UP					2
#define	CSRDIR_DOWN					3

#define	OVERLAY_COMMAND				0x5B
#define	OVERLAY_OR					0
#define	OVERLAY_EXOR				1
#define	OVERLAY_AND					2
#define	OVERLAY_PRIORITYOR			3
#define	OVERLAY_TEXTMODE			0x00
#define	OVERLAY_GRAPHICMODE			0x0C
#define	OVERLAY_TWOLAYER			0x00
#define	OVERLAY_THREELAYER			0x10

#define	CGRAMADR_COMMAND			0x5C
#define	CGRAM_SAGL					0x00
#define	CGRAM_SAGH					0x70

#define	HDOTSCR_COMMAND				0x5A

#define	CSRW_COMMAND				0X46		// cursor register write
#define	CSRR_COMMAND				0x47		// cursor register read
#define	MWRITE_COMMAND				0x42
#define	MREAD_COMMAND				0x43

#define	GRAPHICSTART				SCREEN2_ADDR

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

void GlcdInitialize(void);

#endif /* WS320240DISPLAY_H_ */



초기화 함수 GlcdInitialize() 함수를 WS320240Display.c에 추가합니다.

void GlcdInitialize(void)
{
	// SYSTEMSET COMMAND
	GlcdWriteCommand(SYSTEMSET_COMMAND);
	GlcdWriteData(0x10 | SYSTEMSET_INTERNALCGRAM | SYSTEMSET_CG32CHAR
				  | SYSTEMSET_HEIGHT8PIXEL | SYSTEMSET_SINGLEPANNEL
				  | SYSTEMSET_NOTOPLINECORRECT | SYSTEMSET_LCD | SYSTEMSET_NORMAL);
	GlcdWriteData(SYSTEMSET_TWOFRAMEDRIVE | SYSTEMSET_FXVALUE);
	GlcdWriteData(SYSTEMSET_FYVALUE);
	GlcdWriteData(SYSTEMSET_CR);
	GlcdWriteData(SYSTEMSET_TCR);
	GlcdWriteData(SYSTEMSET_LF);
	GlcdWriteData(SYSTEMSET_APL);
	GlcdWriteData(SYSTEMSET_APH);

	// SCROLL COMMAND
	GlcdWriteCommand(SCROLL_COMMAND);
	GlcdWriteData(0x00);
	GlcdWriteData(0x00);
	GlcdWriteData(GLCD_RESOLUTION_Y - 1);
	GlcdWriteData((GLCD_RESOLUTION_X / BITSPERBYTE * GLCD_RESOLUTION_Y / 8) % 256);
	GlcdWriteData((GLCD_RESOLUTION_X / BITSPERBYTE * GLCD_RESOLUTION_Y / 8) / 256);
	GlcdWriteData(GLCD_RESOLUTION_Y - 1);
	GlcdWriteData(0x00);
	GlcdWriteData(0x00);
	GlcdWriteData(0x00);
	GlcdWriteData(0x00);

	// HDOT SCR COMMAND
	GlcdWriteCommand(HDOTSCR_COMMAND);
	GlcdWriteData(0x00);

	// OVERLAY COMMAND
	GlcdWriteCommand(OVERLAY_COMMAND);
	GlcdWriteData(OVERLAY_TWOLAYER | OVERLAY_TEXTMODE | OVERLAY_OR);

	// CGRAM ADR COMMAND
	GlcdWriteCommand(CGRAMADR_COMMAND);
	GlcdWriteData(CGRAM_SAGL);
	GlcdWriteData(CGRAM_SAGH);

	// DISPLAY OFF COMMAND
	GlcdWriteCommand(DISPLAY_COMMAND | DISPLAY_OFF);
	GlcdWriteData((DISPLAY_NOFLASH << DISPLAY_FIRSTSCREEN_BIT) 
				| (DISPLAY_NOFLASH << DISPLAY_SECONDSCREEN_BIT) | DISPLAY_FLASH32HZ);

	// CLEAR DISPLAY
	GlcdClear();
	GlcdGraphicClear();

	// CURSOR FORMAT COMMAND
	GlcdWriteCommand(CSRFORM_COMMAND);
	GlcdWriteData(CSRFORM_CRX);
	GlcdWriteData(CSRFORM_BLOCK | CSRFORM_CRY);

	// CURSOR DIRECTION COMMAND
	GlcdWriteCommand(CSRDIR_COMMAND | CSRDIR_RIGHT);

	// DISPLAY ON COMMAND
	GlcdWriteCommand(DISPLAY_COMMAND | DISPLAY_ON);
	GlcdWriteData((DISPLAY_NOFLASH << DISPLAY_FIRSTSCREEN_BIT)
			      | (DISPLAY_NOFLASH << DISPLAY_SECONDSCREEN_BIT) | DISPLAY_FLASH32HZ);
}


위와 같이 초기화하면 하나의 패널에 SCREEN1과 SCREEN2에 출력할 수 있게 됩니다.


SCREEN1은 0번지부터 시작하며 내부의 CGROM에 있는 폰트를 사용해서 문자형으로 출력 가능합니다. 한 행당 40글자(40 = 320 / 8), 30행(30 = 240 / 8) 출력 가능합니다. 즉, 0번지에 문자 'A'에 해당하는 ASCII 코드 0x41을 저장하면 좌표 0열 0행에 문자 'A'가 출력됩니다. 40번지에 ASCII 코드 0x42를 저장하면 0열 1행에 문자 'B'가 출력됩니다. SCREEN1의 시작 번지 0은 매크로 SCREEN1_ADDR로 정의했습니다.


SCREEN2는 0x4B0번지부터 시작하며 그래픽으로 출력합니다. 0x4B0번지에 0xF0를 기록하면 최상단행의 가장 왼쪽에 점 4개가 출력됩니다. 0x4B1번지에 0xFF를 기록하면 최상단행의 왼쪽에서 8번째 점부터 8개의 점이 출력됩니다. SCREEN2의 시작 번지는 매크로 SCREEN2_ADDR로 지정했으며, 매크로 GRAPHICSTART도 같은 값을 갖도록 했습니다. 


SCREEN1과 SCREEN2에 츨력되는 내용들은 서로 OR 연산하도록 되어 있습니다.


커서는 7x7 크기를 갖으면서 깜빡 거리도록 설정했으며, 문자 출력 후에는 오른쪽으로 하나씩 이동합니다.





2. 기타 함수 만들기



RA8835를 제어하는데 필요한 다음의 함수 원형들을 WS320240Display.h에 추가합니다.

void GlcdClear(void);
void GlcdGraphicClear(void);
void GlcdSetCursorAddress(uint16_t address);
void GlcdGotoxy(uint8_t x,uint8_t y);
void GlcdPutchar(uint8_t ch);
void GlcdPuts(uint8_t *p);
void GlcdPutsGotoxy(uint16_t x, uint16_t y, uint8_t *p);
void GlcdGraphicGotoxy(uint16_t x, uint16_t y);
void GlcdGraphicPut16byteVert(uint8_t *p);
void GlcdGraphicPut16byteVertGotoxy(uint16_t x, uint16_t y, uint8_t *p);
void GlcdGraphicPut16x2byteVert(uint8_t *p);
void GlcdGraphicPut16x2byteVertGotoxy(uint16_t x, uint16_t y, uint8_t *p);


함수명을 보면 대체로 하는 일을 짐작할 수 있을 것입니다. 함수명에 Graphic이 들어 있는 함수들은 SCREEN2를 대상으로 그래픽 처리하는 함수이고, 그렇지 않은 함수들은 SCREEN1을 대상으로 문자 처리하는 함수들입니다.


GlcdGotoxy() 함수는 SCREEN1에서 좌표 (x, y)로 이동하는 함수이며, GlcdGraphicGotoxy() 함수는 SCREEN2에서 좌표 (x, y)로 이동하는 함수입니다. 당연히 SCREEN1의 좌표는 문자 단위이고, SCREEN2는 바이트 단위입니다.

GlcdGraphicPut16byteVert() 함수는 매개 변수 p가 가리키는 곳으로부터 16바이트만큼의 내용을 lcd에 수직 방향으로 출력하는 함수입니다. RA8835 메모리 구조에 따르면 한 바이트는 가로 방향으로 8점으로 출력됩니다. 즉, 이 함수는 8열 * 16행을 출력합니다


*p

 *(p + 1)

 *(p + 2)

 ...

 *(p + 15)


. 본 프로그램에서 사용하는 ASCII 문자들의 폰트 크기가 8열 * 16행입니다. 즉 ASCII 코드 0x00부터 0x7F에 해당하는 문자를 출력할 때에 이 함수를 사용합니다. GlcdGraphicPut16byteVert() 함수는 16바이트를 출력한 다음에 커서를 한 바이트만큼 옮겨서 다음 출력할 위치를 지정하도록 합니다.


GlcdGraphicPut16byteVertGotoxy() 함수는 GraphicGotoxy() 함수를 호출한 후에 GlcdGraphicPut16byteVert() 함수를 호출합니다. 즉, 그래픽 좌표 (x, y)로 이동한 후에 8열 * 16행의 폰트를 출력합니다.



GlcdGraphicPut16x2byteVert() 함수는 GlcdGraphicPut16byteVert() 함수를 두 번 호출합니다. 즉 16열 * 16행 의 공간에 매개 변수 p로부터 32바이트를 출력합니다. 본 프로그램에서는 한글을 16열 * 16행으로 출력할 것이므로, 한글을 출력할 때에 이 함수를 사용합니다.GlcdGraphicPut16x2byteVertGotoxy() 함수는 GraphicGotoxy() 함수를 호출한 후에 GlcdGraphicPut16x2byteVert() 함수를 호출합니다. 즉, 그래픽 좌표 (x, y)로 이동한 후에 16열 * 16행의 폰트를 출력합니다.

WS320240Display.c에 실제로 위 함수들을 구현합니다.

void GlcdClear(void)
{
	int i;

	GlcdSetCursorAddress(SCREEN1_ADDR);
	GlcdWriteCommand(MWRITE_COMMAND);
	for(i = 0;i < GLCD_RESOLUTION_X / CHARACTER_WIDTH * GLCD_RESOLUTION_Y / CHARACTER_HEIGHT;i++)
		GlcdWriteData(0x20);
	GlcdSetCursorAddress(SCREEN1_ADDR);
}

void GlcdGraphicClear(void)
{
	int i;

	GlcdSetCursorAddress(SCREEN2_ADDR);
	GlcdWriteCommand(MWRITE_COMMAND);
	for(i = 0;i < GLCD_RESOLUTION_X / CHARACTER_WIDTH * GLCD_RESOLUTION_Y;i++)
	GlcdWriteData(0x00);
	GlcdSetCursorAddress(SCREEN2_ADDR);
}

void GlcdSetCursorAddress(uint16_t address)
{
	GlcdWriteCommand(CSRW_COMMAND);
	GlcdWriteData(address & 0x00FF);
	GlcdWriteData(address >> 8);
}

void GlcdGotoxy(uint8_t x,uint8_t y)
{
	GlcdSetCursorAddress(y * (GLCD_RESOLUTION_X / BITSPERBYTE) + x);
}

void GlcdPutchar(uint8_t ch)
{
	GlcdWriteCommand(CSRDIR_COMMAND | CSRDIR_RIGHT);
	GlcdWriteCommand(MWRITE_COMMAND);
	GlcdWriteData(ch);
}

void GlcdPuts(uint8_t *p)
{
	uint8_t ch;

	while(1) {
		if((ch = *p++) == 0) break;
		GlcdPutchar(ch);
	}
}

void GlcdPutsGotoxy(uint16_t x, uint16_t y, uint8_t *p)
{
	GlcdGotoxy(x, y);
	GlcdPuts(p);
}

void GlcdGraphicGotoxy(uint16_t x,uint16_t y)
{
	GlcdSetCursorAddress(SCREEN2_ADDR + y * GLCD_RESOLUTION_X / BITSPERBYTE + x);
}

void GlcdGraphicPut16byteVert(uint8_t *p)
{
	unsigned short int addr;
	unsigned char ch;
	int i;

	GlcdWriteCommand(CSRR_COMMAND);
	addr = GlcdReadData();
	addr += (GlcdReadData() << 8);
	GlcdWriteCommand(CSRDIR_COMMAND | CSRDIR_DOWN);
	GlcdWriteCommand(MWRITE_COMMAND);
	for(i = 0 ;i < 16;i++) {
		ch = *p++;
		GlcdWriteData(ch);
	}
	GlcdSetCursorAddress(addr + 1);
}

void GlcdGraphicPut16byteVertGotoxy(uint16_t x, uint16_t y, uint8_t *p)
{
	GlcdGraphicGotoxy(x,y);
	GlcdGraphicPut16byteVert(p);
}

void GlcdGraphicPut16x2byteVert(uint8_t *p)
{
	GlcdGraphicPut16byteVert(p);
	GlcdGraphicPut16byteVert(p + 16);
}

void GlcdGraphicPut16x2byteVertGotoxy(uint16_t x, uint16_t y, uint8_t *p)
{
	GlcdGraphicGotoxy(x,y);
	GlcdGraphicPut16x2byteVert(p);
}


3. 영문자 및 한글 출력하기


[Inc] 폴더에 GlcdDisplay.h를 추가하고 다음의 함수 원형을 입력합니다.

void GlcdGraphicDisplayASCII(uint8_t ch);
void GlcdGraphicDisplayHangeulKSSM(uint16_t code);
void GlcdGraphicDisplayHangeulKSC5601(uint16_t code);
uint16_t KSC5601_KSSM(uint16_t code);
void GlcdGraphicPuts(uint8_t *ptr);
void GlcdGraphicPutsGotoxy(uint16_t x, uint16_t y, uint8_t *ptr);
void GlcdGraphicPutsKSSM(uint8_t *ptr);
void GlcdGraphicPutsKSSMGotoxy(uint16_t x, uint16_t y, uint8_t *ptr);

GlcdGraphicDisplayASCII() 함수는 매개 변수 ch에 해당하는 폰트를 찾아서 그래픽 화면에 8 x 16 크기로 영문자 한 글자를 그래픽 화면에 출력하는 함수입니다. 이 함수 내부에서는 앞에서 언급한 GlcdGraphic16byteVert() 함수를 호출합니다.


GlcdGraphicDisplayHangeulKSSM() 함수는 매개 변수 code에 해당하는 조합형 한글의 폰트를 조합하여 32바이트 크기의 배열 HanBuffer에 담아 한글 한 글자를 그래픽 화면에 출력니다. 이 함수의 내부에서 GlcdGraphic16x2byteVert() 함수를 호출합니다.


GlcdGraphicDisplayHangeulKS5601() 함수는 KSC5601_KSSM() 함수를 호출하여 KSC5601 코드의 한글을 조합형 한글로 변환한 다음, GlcdGraphicDisplayHangeulKSSM() 함수를 호출함으로써 KSC5601 코드의 한글 한 글자를 그래픽 화면에 출력합니다.


GlcdGraphicPuts() 함수는 매개 변수 p가 가리키는 곳에서부터 null을 만날 때까지 문자열을 그래픽 화면에 출력합니다. 이 함수는 매 바이트마다 최상위 비트가 1로 설정되어 있으면 한글로 간주하여 GlcdGraphicDisplayKSC5601() 함수를 호출하고, 그렇지 않으면 GlcdGraphicDisplayASCII() 함수를 호출합니다.

 

[Src] 폴더에 GlcdDisplay.c를 추가하고 다음의 함수들을 만듭니다.

#include "stm32f1xx_hal.h"
#include "stm32f1xx.h"
#include "WS320240Display.h"
#include "RA8835Font.h"
#include "GlcdDisplay.h"

void GlcdGraphicDisplayASCII(uint8_t ch)
{
	GlcdGraphicPut16byteVert((uint8_t *)ASCIIFont + ch * ASCII_FONTSIZE);
}

void GlcdGraphicDisplayHangeulKSSM(uint16_t code)		/* display a 16x16 Dot Korean */
{
	uint8_t i;
	uint8_t Chosung, Joongsung, Jongsung;
	uint8_t BulChosung, BulJoongsung,BulJongsung = 0, JongsungFlag;

	Chosung = *(ChosungTable + ((code >> 10) & 0x001F));
	Joongsung = *(JoongsungTable + ((code >> 5) & 0x001F));
	Jongsung = *(JongsungTable + (code & 0x001F));
	if(Jongsung == 0) {				// Jongsung not exist.
		JongsungFlag = 0;
		BulChosung = *(ChosungWithoutJongsungBul + Joongsung);
		if((Chosung == 1) || (Chosung == 16)) BulJoongsung = 0;
		else BulJoongsung = 1;
	}
	else {							// Jongsung exist.
		JongsungFlag = 1;
		BulChosung = *(ChosungWithJongsungBul + Joongsung);
		if((Chosung == 1) || (Chosung == 16)) BulJoongsung = 2;
		else BulJoongsung = 3;
		BulJongsung = *(JongsungBul + Joongsung);
	}
	for(i = 0;i < HANGEUL_FONTSIZE;i++)
		HanBuffer[i] = ChosungFont[BulChosung][Chosung][i];
	for(i = 0;i < HANGEUL_FONTSIZE;i++)
		HanBuffer[i] |= JoongsungFont[BulJoongsung][Joongsung][i];
	if(JongsungFlag) {
		for(i = 0;i < HANGEUL_FONTSIZE;i++)
		HanBuffer[i] |= JongsungFont[BulJongsung][Jongsung][i];
	}
	GlcdGraphicPut16x2byteVert(HanBuffer);
}

void GlcdGraphicDisplayHangeulKSC5601(uint16_t code)
{
	GlcdGraphicDisplayHangeulKSSM(KSC5601_KSSM(code));
}

uint16_t KSC5601_KSSM(uint16_t code)
{
	return *(KssmCodeTable + ((uint16_t)(code >> 8) - 0xB0) * (0xFE - 0xA0) + ((code & 0xFF) - 0xA1));
}

void GlcdGraphicPuts(uint8_t *p)
{
	uint8_t ch;
	uint16_t hancode;

	while(1) {
		if((ch = *p++) == 0) break;
		if(ch & 0x80) {
			hancode = *p++;
			hancode |= (ch << 8);
			GlcdGraphicDisplayHangeulKSC5601(hancode);
		}
		else GlcdGraphicDisplayASCII(ch);
	}
}

void GlcdGraphicPutsGotoxy(uint16_t x, uint16_t y, uint8_t *p)
{
	GlcdGraphicGotoxy(x,y);
	GlcdGraphicPuts(p);
}

void GlcdGraphicPutsKSSM(uint8_t *p)
{
	uint8_t ch;
	uint16_t hancode;

	while(1) {
		if((ch = *p++) == 0) break;
		if(ch & 0x80) {
			hancode = *p++;
			hancode |= (ch << 8);
			GlcdGraphicDisplayHangeulKSSM(hancode);
		}
		else GlcdGraphicDisplayASCII(ch);
	}
}

void GlcdGraphicPutsKSSMGotoxy(uint16_t x, uint16_t y, uint8_t *p)
{
	GlcdGraphicGotoxy(x,y);
	GlcdGraphicPutsKSSM(p);
}


WS320240Display.c 파일과 GlcdDisplay.c 파일을 따로 만든 이유가 있습니다. 하드웨어 의존적인 부분은 WS320240Display.c에 넣고 GlcdDisplay.c에는 하드웨어로부터 독립적인 루틴만 넣어서 다른 그래픽 lcd를 다루는 프로젝트에서도 가급적 수정없이 사용하고자 하는 의도입니다.


위 소스 프로그램 GlcdDisplay.c에서 포함하는 파일 RA8835Font.h는 다음과 같은 내용을 포함하고 있습니다.


#define KSC5601_HANGEUL_SU		2350
#define ASCII_FONT_SU			128
#define CHOSUNG_BUL_SU			8
#define CHOSUNG_SU			 	20
#define JOONGSUNG_BUL_SU		4
#define JOONGSUNG_SU			22
#define JONGSUNG_BUL_SU			4
#define JONGSUNG_SU				28

//#define KSC5601_MSB_MIN			0xB0
//#define KSC5601_MSB_MAX			0xC8
//#define KSC5601_LSB_MIN			0xA1
//#define KSC5601_LSB_MAX			0xFE

extern unsigned char HanBuffer[HANGEUL_FONTSIZE];

extern const unsigned char ChosungTable[];
extern const unsigned char JoongsungTable[];
extern const unsigned char JongsungTable[];
extern const unsigned char ChosungWithoutJongsungBul[];
extern const unsigned char ChosungWithJongsungBul[];
extern const unsigned char JongsungBul[];
extern const unsigned short int KssmCodeTable[];
extern const unsigned char ASCIIFont[][ASCII_FONTSIZE];
// CHOSUNG_FONT: //8벌 * 20자 * 32
extern const unsigned char ChosungFont[][CHOSUNG_SU][HANGEUL_FONTSIZE];
// JOONGSUNG_FONT:    //4벌 * 22자 * 32
extern const unsigned char JoongsungFont[][JOONGSUNG_SU][HANGEUL_FONTSIZE];
//JONGSUNG_FONT: //4벌 * 28자 * 32
extern const unsigned char JongsungFont[][JONGSUNG_SU][HANGEUL_FONTSIZE];

 

실제 Font는 RA8835Font.c에 있습니다. 너무 내용이 길고 설명할 필요가 없는 부분이라 본문에 적지 않습니다. 첨부한 압축 파일에 포함되어 있습니다.




4. TIM2를 이용한 LED 깜빡이기




LED를 깜빡이게 하려고 TIM2를 설정해 두었습니다. 두 군데만 손보면 LED를 깜빡이게 할 수 있습니다.
먼저 [Src] 폴더 아래에 있는 stm32f1xx_it.c를 열어서 TIM2_IRQHandler() 함수를 찾습니다. 이 함수를 다음과 같이 수정합니다.

void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */
  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}



HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); 부분만 추가로 입력하면 됩니다.

[Src] 폴더 아래의 main.c 파일을 열어서 다음과 같이 코드를 추가하여 영문자 및 한글을 출력하고 TIM2를 활성화 사킵니다. 우선 다음 주석문이 있는 곳에다 필요한 파일을 포함시키는 다음의 두 행을 입력합니다.

/* USER CODE BEGIN Includes */
#include "WS320240Display.h"
#include "GlcdDisplay.h"
/* USER CODE END Includes */



main() 함수 안에 다음 주석이 있는 위치를 두 곳을 찾아서 각각 코드를 추가합니다.*/

  /* USER CODE BEGIN 1 */
  uint8_t *p = (uint8_t *)"(C)BOO YEONG, JEONG 2018.10.30. ROK";
  uint8_t *str = (uint8_t *)"Information(생활정보) System V0.01";
   /* USER CODE END 1 */

  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim2);
  HAL_Delay(200);
  GlcdInitialize();
  GlcdGraphicPutsGotoxy(0, 0, p);
  GlcdGraphicPutsGotoxy(0, 32, str);
  GlcdPutsGotoxy(0,10,p);
  GlcdPutsGotoxy(0,11,p);
  /* USER CODE END 2 */



HAL_TIM_Base_Start_IT() 함수를 호출하지 않으면 TIM2가 시작하지 않습니다. 이 것을 빼먹고서 led가 깜빡거리지 않아 한참을 헤맸습니다.

여기까지 작업한 프로젝트를 압축하여 첨부합니다.

 

STM32F103WS320240.zip



다음 글에서는 인터넷에서 찾은 그래픽 라이브러리를 약간 편집해서 간단히 원이나 선을 그어 보도록 하겠습니다.

블로그 이미지

엠쿠스

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

,