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


인터넷 상에 있는 라이브러리를 이용해서 간단한 그림을 그려 보겠습니다. 우선 그래픽의 가장 기본이 되는 점을 찍는 함수 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으로 압축하여 첨부합니다.


 

STM32F103WS320240(1).zip



 


이상으로 일단 컨트롤러로 RA8835를 사용한 그래픽 lcd WS320240C를 제어하는 글을 마칩니다. 행여 앞으로 기회가 된다면 그래픽 알고리즘을 이용해서 더 다양한 그래픽을 구현해 봤으면 합니다. 혹시 이 글을 읽으신 독자께서 더 훌륭한 라이브러리를 만드신다면 공유해 주셨으면 감사하겠습니다.

블로그 이미지

엠쿠스

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

,