본문 바로가기
  • SpokeHouse
STM32/STM32F

STM32F103 - uart를 printf로 세팅하는법

by SpokeHouse 2023. 11. 4.
728x90
728x90

안녕하세요. 오동나무 토끼입니다.

항상 ST MCU를 사용해서 개발을 진행하려고하는 경향이 있습니다.

익숙하기도 하고 항상 ODM 위주 개발 프로젝트가 대부분이기 때문에 기간도 타이트하고, 

짧은 시간 정확한 퍼포먼스를 도출하기위해서는 새로운 모험은 힘든게 사실입니다.

가격 경쟁력이 있을거같아 대만, 중국, 한국 출신 MCU 써보려고 시도 했었는데 그나마 대만께 쓸만할거같았는데

STM32103하고 1,000원정도 차이였는데 하다가 수명 짧아지는거같아 깔끔히 접었습니다.

무튼 STM32103 사용 개발 진행중인데 디버깅용 UART로 데이터 확인하는데 매번 HAL_~~~~ 귀찮아서 PRINTF문 사용 

메모하고 헤더 , 소스로 쪼개서 들고다니면서 계속 사용하고자합니다.

설명은 따로 없습니다. 

헤더파일

#ifndef INC_MYPRINTF_H_
#define INC_MYPRINTF_H_


#include "usart.h"
#include <stdio.h>
#include <string.h>

#define PRINTF_UART_HANDLE		huart1 //using uart hander

#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE	int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE	int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE	int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE	int fgetc(FILE *f)
#endif	/* __GNUC__*/
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
#ifdef __GNUC__
int __io_putchar(int ch);
int __io_getchar(void);
#else
int fputc(int ch, FILE *f);
int fgetc(FILE *f);
#endif	/* __GNUC__*/

extern uint8_t udata[2];

#endif /* INC_MYPRINTF_H_ */

소스파일

#include <stdio.h>
#include <string.h>
#include "myPrintf.h"

uint8_t udata[2];

/**
 * @fn int _read(int, char*, int)
 * @brief
 *
 * @param file
 * @param ptr
 * @param len
 * @return
 */
#ifdef __cplusplus
extern "C" int _read(int file, char *ptr, int len)
#else
int _read(int file, char *ptr, int len)
#endif
{
	int DataIdx;

	for (DataIdx = 0; DataIdx < len; DataIdx++) {
		*ptr++ = __io_getchar();
	}

	return len;
}

/**
 * @fn int _write(int, char*, int)
 * @brief
 *
 * @param file
 * @param ptr
 * @param len
 * @return
 */
#define __SWV		0
#define __USO		1

#if (__SWV == 1)
#define _SWV_
#elif(__USO == 1)
#define _USO_
#endif

#ifdef __cplusplus
extern "C" int _write(int file, char *ptr, int len)
#else
int _write(int file, char *ptr, int len)
#endif
{
	int DataIdx;

	for (DataIdx = 0; DataIdx < len; DataIdx++) {
#ifdef _SWV_
		ITM_SendChar(*ptr++);
#endif
#ifdef _USO_
		__io_putchar(*ptr++);
#endif
	}

	return len;
}

PUTCHAR_PROTOTYPE
{
#if 0 // basic "string + <lf>"
	HAL_UART_Transmit(&PRINTF_UART_HANDLE, (uint8_t *)&ch, 1, 0xffff);

	while (HAL_UART_GetState(&PRINTF_UART_HANDLE) != HAL_UART_STATE_READY);

#else// basic "string + <cr>+<lf>
	if (ch == '\n') {
		HAL_UART_Transmit(&PRINTF_UART_HANDLE, (uint8_t *)('\r'), 1, 0xffff);
		while (HAL_UART_GetState(&PRINTF_UART_HANDLE) != HAL_UART_STATE_READY);
		HAL_UART_Transmit(&PRINTF_UART_HANDLE, (uint8_t *)('\n'), 1, 0xffff);
	}
	else {
		HAL_UART_Transmit(&PRINTF_UART_HANDLE, (uint8_t *)&ch, 1, 0xffff);
	}
	while (HAL_UART_GetState(&PRINTF_UART_HANDLE) != HAL_UART_STATE_READY);
#endif

	return ch;
}

/*****************************************************
 * @fn int __io_getchar(void)
 * @brief
 *
 * @return
 */

GETCHAR_PROTOTYPE
{
#if 0 // receiv func -testing
	/* Place your implementation of fgetc here */
	char data[4];
	uint8_t ch, len = 1;

	while(HAL_UART_Receive(&PRINTF_UART_HANDLE, &ch, 1, 10)){}

	memset(data, 0x00, 4);

	switch (ch) {
	case '\r':
	case '\n':
		len = 2;
		sprintf(data, "\r\n");
		break;
	case '\b':
	case 0x7f:
		len = 3;
		sprintf(data, "\b \b");
		break;
	default:
		data[0] = ch;
		break;
	}
	HAL_UART_Transmit(&PRINTF_UART_HANDLE, (uint8_t *)data, len, 10);

	return ch;

#else
	HAL_UART_Receive(&PRINTF_UART_HANDLE, udata, 1, 100);

	while (HAL_UART_GetState(&PRINTF_UART_HANDLE) != HAL_UART_STATE_READY);

	return udata[0];
#endif

}

리시브쪽은 테스트 안해봐서 보시고 수정사항있으면 저도 도움 받게 댓글로 남겨주시면 매우 감사드리구요

중요한 참고사항 보내는 스트링값 뒤에는 \r\n 붙여주어야 동작잘됨.

그럼 이만 오늘도 대단히 맛있는거 많이 드시고 ㄱ

춍춍!

728x90
728x90

댓글