RA8835 GLCD 제어하기(제6편) - 그래픽라이브러리 활용하기
인터넷 상에 있는 라이브러리를 이용해서 간단한 그림을 그려 보겠습니다. 우선 그래픽의 가장 기본이 되는 점을 찍는 함수 GlcdSetPixel()을 만듭니다. 특정한 위치에 점을 찍는 기능은 하드웨어에 따라 달라질 수 있으므로 WS320240Display.c에 만듭니다. WS320240Display.h에 다음의 함수 원형을 추가합니다. 매개 변수 x와 y는 점을 찍을 좌표이고, color 값이 0이면 점을 지우고, 0이 아니면 점을 찍습니다.
void GlcdSetPixel(uint16_t x,uint16_t y, int color);
WS320240Display.c에 GlcdSetPixel() 함수를 추가합니다.
void GlcdSetPixel(uint16_t x,uint16_t y, int color) { uint8_t tmp = 0; uint16_t address = GRAPHICSTART + ((SYSTEMSET_CR + 1) * y) + (x / BITSPERBYTE); GlcdSetCursorAddress(address); GlcdWriteCommand(MREAD_COMMAND); // read memory tmp = GlcdReadData(); if(color) tmp |= (1 << (SYSTEMSET_FXVALUE - (x % BITSPERBYTE))); else tmp &= ~(1 << (SYSTEMSET_FXVALUE - (x % BITSPERBYTE))); GlcdSetCursorAddress(address); GlcdWriteCommand(MWRITE_COMMAND); // write memory GlcdWriteData(tmp); }
좌표 x, y 값에 따라 RA8835의 주소값을 계산하여, 현재 메모리에 있는 값을 읽어 옵니다. 이 값에 color 값에 따라 점을 찍거나 지운 다음에 다시 기록합니다.
다음은 위 GlcdSetPixel() 함수를 이용해서 사각형을 그리는 GlcdRectangle() 함수, 원을 그리는 GlcdCircle() 함수, 선을 그리는 GlcdLine() 함수를 구현했습니다. 이 세 함수들은 인터넷 상에 있는 SED1335 라이브러리를 기준으로 하여, 필자의 함수명 부여 원칙에 부합되도록 함수명을 약간 손질했습니다. 원 소스는 en.radzio.dxp.pl/sed1335/입니다.
[Inc] 폴더 안에 Graphic.h 파일을 추가하고 다음의 함수 원형들을 입력합니다.
void GlcdRectangle(uint16_t x, uint16_t y, uint16_t b, uint16_t a); void GlcdCircle(uint16_t cx, uint16_t cy ,uint16_t radius); void GlcdLine(int X1, int Y1,int X2,int Y2);
[Src] 폴더에 Graphic.c 파일을 추가하고 다음 함수들을 입력합니다.
#include "stm32f1xx_hal.h" #include "WS320240Display.h" #include "Graphic.h" const uint8_t color = 1; void GlcdRectangle(uint16_t x, uint16_t y, uint16_t b, uint16_t a) { uint16_t j; for (j = 0; j < a; j++) { GlcdSetPixel(x, y + j, color); GlcdSetPixel(x + b - 1, y + j, color); } for (j = 0; j < b; j++) { GlcdSetPixel(x + j, y, color); GlcdSetPixel(x + j, y + a - 1, color); } } void GlcdCircle(uint16_t cx, uint16_t cy ,uint16_t radius) { int x, y, xchange, ychange, radiusError; x = radius; y = 0; xchange = 1 - 2 * radius; ychange = 1; radiusError = 0; while(x >= y) { GlcdSetPixel(cx + x, cy + y, color); GlcdSetPixel(cx - x, cy + y, color); GlcdSetPixel(cx - x, cy - y, color); GlcdSetPixel(cx + x, cy - y, color); GlcdSetPixel(cx + y, cy + x, color); GlcdSetPixel(cx - y, cy + x, color); GlcdSetPixel(cx - y, cy - x, color); GlcdSetPixel(cx + y, cy - x, color); y++; radiusError += ychange; ychange += 2; if ( 2*radiusError + xchange > 0 ) { x--; radiusError += xchange; xchange += 2; } } } void GlcdLine(int X1, int Y1,int X2,int Y2) { int CurrentX, CurrentY, Xinc, Yinc, Dx, Dy, TwoDx, TwoDy, TwoDxAccumulatedError, TwoDyAccumulatedError; Dx = (X2 - X1); Dy = (Y2 - Y1); TwoDx = Dx + Dx; TwoDy = Dy + Dy; CurrentX = X1; CurrentY = Y1; Xinc = 1; Yinc = 1; if(Dx < 0) { Xinc = -1; Dx = -Dx; TwoDx = -TwoDx; } if (Dy < 0) { Yinc = -1; Dy = -Dy; TwoDy = -TwoDy; } GlcdSetPixel(X1,Y1, color); if ((Dx != 0) || (Dy != 0)) { if (Dy <= Dx) { TwoDxAccumulatedError = 0; do { CurrentX += Xinc; TwoDxAccumulatedError += TwoDy; if(TwoDxAccumulatedError > Dx) { CurrentY += Yinc; TwoDxAccumulatedError -= TwoDx; } GlcdSetPixel(CurrentX,CurrentY, color); }while (CurrentX != X2); } else { TwoDyAccumulatedError = 0; do { CurrentY += Yinc; TwoDyAccumulatedError += TwoDx; if(TwoDyAccumulatedError>Dy) { CurrentX += Xinc; TwoDyAccumulatedError -= TwoDy; } GlcdSetPixel(CurrentX,CurrentY, color); }while (CurrentY != Y2); } } }
main.c 파일에 Graphic.h 파일을 포함시킨 후에 main() 함수에서 위의 함수들을 호출하여 그림을 그려 봅니다.
파일을 포함시키는 부분에 다음과 같이 Graphic.h를 포함하도록 추가합니다.
/* USER CODE BEGIN Includes */ #include "WS320240Display.h" #include "GlcdDisplay.h" #include "Graphic.h" /* USER CODE END Includes */
그래픽 출력이 잘 동작하는지 테스트하기 위해서 main() 함수 안에 다음과 같이 그래픽 함수를 호출하는 부분을 추가합니다.
/* 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); GlcdRectangle(0, 165, 299, 74); GlcdCircle(149, 139, 100); GlcdCircle(269, 189, 50); GlcdLine(0, 0, 319,239); /* USER CODE END 2 */
소스 프로그램을 zip으로 압축하여 첨부합니다.
이상으로 일단 컨트롤러로 RA8835를 사용한 그래픽 lcd WS320240C를 제어하는 글을 마칩니다. 행여 앞으로 기회가 된다면 그래픽 알고리즘을 이용해서 더 다양한 그래픽을 구현해 봤으면 합니다. 혹시 이 글을 읽으신 독자께서 더 훌륭한 라이브러리를 만드신다면 공유해 주셨으면 감사하겠습니다.