UART
UART(Universal asynchronous receiver/transmitter)란 병렬 형태의 데이터를 직렬(Serial) 방식으로 전환하여 전송하는 통신 방법입니다. UART는 대부분 3.3V ~ 5V를 사용하기 때문에 -12V ~ 12V을 사용하는 RS-232, RS-485와 같은 통신 표준으로 변경하여 전달하는 경우가 많습니다.
TX(송신)와 RX(수신) 2개의 핀을 사용하며, 데이터 통신을 위한 클럭을 사용하지 않기 떄문에 송신측과 수신측에서 사전에 baud rate, data size 등을 설정해야합니다.
데이터 형식
- Start bit : 통신의 시작을 의미하는 비트
- Data bit : 데이터를 표현하는 비트, 5 ~ 8비트를 사용합니다.
- Parity bit : 오류 검증을 하기 위한 패리티 비트, 송신 측에서 생성하고 수신 측에서 이를 사용하여 오류를 판단합니다.
- Stop bit : 통신 종료를 알리는 비트
Baud Rate
Baud Rate(보율)이란 1초당 송/수신하는 데이터의 양을 의미합니다. 만약 baud rate를 9600으로 설정하면 1초에 9600개의 데이터를 송/수신한다는 것입니다. 송신측과 수신측에 동일한 baud rate를 설정해야 올바르게 데이터를 주고받을 수 있습니다.
개발 환경
개발 도구
구분 | 내용 |
통합 개발 환경 | STM32CubeIDE |
터미널 에뮬레이터 | Xshell 5 |
BOM
상품명(링크) | 수량 |
STM32F103 Development Board | 1 |
FT232RL 아두이노 USB to UART 모듈 | 1 |
ST-Link STM32 디버거 (with JTAG 20-pin cable) | 1 |
USB 2.0 A to mini-B 커넥터 | 2 |
소켓 점퍼 케이블 40P (칼라) (M/F) 20cm | 6 |
브레드보드 | 1 |
* FT232RL 모듈이 노트북에서 인식하지 않는 경우, 재부팅을 해보거나 FTDI 드리아버를 추가로 설치해야합니다.
H/W
H/W 구성도
STM32F103 Development Board는 디버깅을 위해 STLink를 사용하여 전원을 인가했고, FT232RL 모듈은 USB 커넥터를 사용하여 전원을 인가하고 PC에 데이터를 전송했습니다.
HSI(Human System Interface)
S/W
소스코드
HAL_UART_Transmit()
- HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
- UART_HandleTypeDef *huart : UART 모듈에 대한 구성 정보를 포함하는 UART_HandleTypeDef 구조체 포인터
- const uint8_t *pData : 데이터 버퍼(u8 또는 u16 데이터 요소)를 가리키는 포인터
- uint16_t Size : 전송할 데이터 요소(u8 또는 u16)의 크기
- uint32_t Timeout : 데이터 전송 작업의 시간 제한
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1)
{
/* Infinite loop */
/* USER CODE BEGIN WHILE */
char data[20] = "Hello World!\r\n";
HAL_UART_Transmit(&huart1, data, strlen(data), 1000);
HAL_Delay(1000);
/* USER CODE END WHILE */
}
}
printf()를 사용하여 UART 데이터 전송
printf 함수는 C 언어에서 문자열을 stdout에 출력하는 함수입니다. 보통 gdb나 lldb를 사용하여 디버깅을 하지만 멀티 스레드 혹은 멀티 프로세스 환경 같이 디버깅이 제한되는 경우가 있기 때문에 printf를 많이 사용하게 됩니다.
HAL_UART_Transmit() 함수를 사용해도 되지만, 조금 더 편하게 디버깅을 하기 위해 printf 함수가 데이터를 UART 통신의 transmit 값으로 전송하도록 printf 함수 내부의 _write()를 재정의하여 사용합니다.
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
int _write(int file, char *p, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *)p, len, 10);
return len;
}
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1)
{
/* Infinite loop */
/* USER CODE BEGIN WHILE */
printf("Hello World!\r\n");
HAL_Delay(1000);
/* USER CODE END WHILE */
}
}
추가
MCU/MPU 환경에서 printf 함수로 float을 출력하기 위해서는 링커에 -u _printf_float 플래그를 추가해야합니다. -u _printf_float는 printf 함수의 부동 소수점 출력 기능을 사용하기 위해 _printf_float 심볼을 강제로 포함하도록 하는 옵션입니다.
결과
참고자료
[임베디드 15강] UART로 printf()를 구현해보자!
'Embedded' 카테고리의 다른 글
[임베디드] SSD1306 OLED 모듈 제어 - I2C (1) | 2024.09.02 |
---|---|
[임베디드] 74HC595D FND 모듈 제어 - SPI (0) | 2024.08.10 |
[임베디드] 74HC595D FND 모듈 제어 - GPIO (4) | 2024.08.07 |