인터넷 상에 있는 라이브러리를 이용해서 간단한 그림을 그려 보겠습니다. 우선 그래픽의 가장 기본이 되는 점을 찍는 함수 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를 제어하는 글을 마칩니다. 행여 앞으로 기회가 된다면 그래픽 알고리즘을 이용해서 더 다양한 그래픽을 구현해 봤으면 합니다. 혹시 이 글을 읽으신 독자께서 더 훌륭한 라이브러리를 만드신다면 공유해 주셨으면 감사하겠습니다.
'STM32F103' 카테고리의 다른 글
| STM32F103 DFU Bootloader로 펌웨어 업데이트하기 (6) | 2018.11.19 |
|---|---|
| STM32F103 DFU Bootloader 만들기 (19) | 2018.11.19 |
| RA8835 GLCD 제어하기(제5편) - 한글 및 영문자 출력하기 (0) | 2018.11.18 |
| RA8835 GLCD 제어하기(제4편) - RA8835 제어함수 만들기 (0) | 2018.11.15 |
| RA8835 GLCD 제어하기(제3편) - STM32F103 GPIO 다루기(2) (0) | 2018.11.15 |
STM32F103WS320240(1).zip