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


True Studio에서 printf() 함수를 사용할 수 있도록 하는 작업은 참으로 아주 간단합니다. 인터넷으로 검색하면 꽤 복잡한 내용의 글들이 많습니다만, 그런 글 신경쓰지 말고 _write() 함수만 정의하면 됩니다.

앞 글 ST7565P GLCD 제어하기(제2편)에서 만들었던 STM32F103M19264.zip을 조금 수정해서, printf() 함수를 그래픽 lcd에다 출력해 보겠습니다.

main.c의 아래 부분에 다음과 같은 주석문이 보이는 곳에 _write() 함수를 다음과 같이 정의합니다.

/* USER CODE BEGIN 4 */
int _write(int file, char *ptr, int len)
{
	uint8_t preCode = 0;
	int i;

	LED_GPIO_Port->BRR = LED_Pin;
	for (i = 0;i < len;i++)
	{
		if(*(ptr + i) & 0x80) {
		  if(preCode == 0) preCode = *(ptr + i);
		  else
		  {
		    GlcdGraphicDisplayHangeulKSC5601((preCode << 8) + *(ptr + i));
		    preCode = 0;
		  }
		}
		else
		{
		  if(preCode == 0) GlcdGraphicDisplayASCII(*(ptr + i));
		  else
		  {
		    GlcdGraphicDisplayASCII(preCode);
		    GlcdGraphicDisplayASCII(*(ptr + i));
		    preCode = 0;
		  }
		}
	}
	LED_GPIO_Port->BSRR = LED_Pin;
	return len;
}

/* USER CODE END 4 */



함수가 길어서 복잡해 보입니다만, 함수가 긴 것은 한글을 처리하느라 길어진 것뿐입니다. 다음과 같이하면 더 간단해 보일 것입니다. 물론 main() 함수 상단에 DisplayChar() 함수의 원형을 선언해 주어야 컴파일할 때에 경고가 뜨지 않을 것입니다.

/* USER CODE BEGIN 4 */
int _write(int file, char *ptr, int len)
{
	int i;

	LED_GPIO_Port->BRR = LED_Pin;
	for (i = 0;i < len;i++)
           DisplayChar(*(ptr + I));
	LED_GPIO_Port->BSRR = LED_Pin;
	return len;
}

void DisplayChar(uint8_t ch)
{
	static uint8_t preCode = 0;

	if(ch & 0x80) {
	  if(preCode == 0) preCode = ch;
	  else
	  {
	    GlcdGraphicDisplayHangeulKSC5601((preCode << 8) + ch);
	    preCode = 0;
	  }
	}
	else
	{
	  if(preCode == 0) GlcdGraphicDisplayASCII(ch);
	  else
	  {
	    GlcdGraphicDisplayASCII(preCode);
	    GlcdGraphicDisplayASCII(ch);
	    preCode = 0;
	  }
	}
}



main() 함수 안에 다음과 같이하여 printf() 함수를 사용해 봅니다.

  /* USER CODE BEGIN 2 */
  GlcdInitialize();
  printf("한글과 ASCII 문자가 섞여있습니다.\n");
  GlcdGraphicGotoxy(0, 32);
  printf("버전 Ver%03d.%d %3.1f\n", 0, 3, 2.1);
 /* USER CODE END 2 */



True Studio에서 printf() 함를 사용할 때에 유의해야할 점이 하나 있습니다. 출력할 내용의 맨 끝에 LF(Line Feed: '\n') 문자를 반드시 보내야 합니다. '\n' 가 없으면 출력하지 않습니다. 위의 main() 함수 내용을 실행한 그래픽 lcd 화면입니다.



출력된 화면에 두 가지 문제가 있습니다.
첫째, printf() 함수에 반드시 보내야하는 LF 문자가 그래픽 폰트로 출력되고 있습니다.
둘째, 실수 출력 "%f"가 되지 않고 있습니다.

하나씩 해결해 보겠습니다.

첫째, LF 문자 문제는 GlcdGraphicDisplayASCII() 함수에서 특수 문자인 LF(0x0D)나 CR(0x0A)는 그 기능을 수행하고 화면에 그래픽으로 출력하지 않도록 조치하면 됩니다. 이를 위해서 세 군데를 수정하겠습니다.

[Inc] 폴더 안의 M19264Display.h 파일을 열어 다음의 내용을 추가합니다.

#define	CR							0x0D
#define	LF							0x0A

uint8_t GlcdGraphicSpecialASCII(uint8_t ch);

처리할 특수 문자 LF와 CR의 코드를 정의하고, 처리할 함수 GlcdGraphicSpecialASCII() 함수의 함수 원형을 정의했습니다.



[Src] 폴더 안의 M19264Display.c 파일을 열어 적당한 곳에 다음의 함수를 추가합니다.

uint8_t GlcdGraphicSpecialASCII(uint8_t ch)
{
	if (ch == CR)
	{
		GlcdGraphicGotoxy(0, CurrentY);
		return 1;
	}
	else if (ch == LF)
	{
		GlcdGraphicGotoxy(CurrentX, CurrentY + ASCII_FONTSIZE_Y);
		return 1;
	}
	return 0;
}

CR 문자는 출력할 위치를 그 행의 맨 앞으로 옮기고, LF 문자는 출력할 위치를 다음 행으로 옮깁니다. CR 문자나 LF 문자를 처리한 후에는 1을 리턴하고, 그렇지 않은 경우에는 0을 리턴합니다. 이 함수를 호출하는 함수에서는 리턴 값에 따라 다른 행동을 취할 수 있습니다.



[Src] 폴더의 GlcdDisplay.c 파일을 열어 GlcdGraphicDisplayASCII() 함수를 다음과 같이 수정합니다.

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



이와 같이 수정하면 다음과 같이 LF 문자 없이 출력됩니다.




둘째, 실수형 숫자가 출력되지 않았던 문제를 해결할 차례입니다. printf() 함수에서 실수형 숫자를 출력하려면 프로그램이 많이 커지므로, True Studio를 비롯한 대부분의 MCU용 링커들이 기본적으로 실수형 문자를 출력하는 라이브러리를 사용하지 않도록 설정되어 있습니다. True Studio가 printf() 함수에서 실수형 문자를 처리할 수 있도록 설정만 변경해주면 됩니다.

True Studio의 [Project] 메뉴를 엽니다. 맨 아래 항목인 [Properties]를 클릭합니다. 새로 나타난 팝업 메뉴에서 [C/C++ Build]를 선택하고, 그 아래 항목에서 [Settings] 항목을 클릭합니다. 오른쪽의 화면에서 [Tool Settings] 탭에서 [C Linker] 하위 메뉴인 [Miscellaneous]를 클릭합니다. 오른쪽 화면의 [Other options] 항목에 다음과 같이 -u _printf_float를 입력하고 [OK] 버튼을 누릅니다.





의도한 바와 같이 맽 끝에 실수 2.1이 출력되었습니다. printf() 함수에서 실수를 사용할 수 있도록 설정하면 실행 코드는 약 9KB 이상 더 커집니다.



STM32CubeMX가 버전 5.0.0으로 업데이트 되었고, STM32F1 시리즈의 Software Package도 V1.7.0으로 업데이트 되어서, 이번 프로젝트는 STM32CubeMX 5.0.0과 STM32F1 V1.7.0으로 만들었습니다. 동작하는 소스프로그램들을 zip으로 압축하여 첨부합니다.


STM32F103M19264Printf.zip


블로그 이미지

엠쿠스

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

,