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가 깜빡거리지 않아 한참을 헤맸습니다.
여기까지 작업한 프로젝트를 압축하여 첨부합니다.
다음 글에서는 인터넷에서 찾은 그래픽 라이브러리를 약간 편집해서 간단히 원이나 선을 그어 보도록 하겠습니다.
'STM32F103' 카테고리의 다른 글
STM32F103 DFU Bootloader 만들기 (19) | 2018.11.19 |
---|---|
RA8835 GLCD 제어하기(제6편) - 그래픽라이브러리 활용하기 (0) | 2018.11.18 |
RA8835 GLCD 제어하기(제4편) - RA8835 제어함수 만들기 (0) | 2018.11.15 |
RA8835 GLCD 제어하기(제3편) - STM32F103 GPIO 다루기(2) (0) | 2018.11.15 |
RA8835 GLCD 제어하기(제2편) - STM32F103 GPIO 다루기(1) (0) | 2018.11.11 |