CubeMX에서 사용하고자 하는 UART 페리페럴 설정을 합니다. 저는 프로젝트를 만들면 사용자에게 제안하는 기본 모드 설정(Default mode)을 사용한 상태입니다. 기본 설정은 USART 3번 채널을 사용합니다.
기본 설정 상태에서는 UART관련 인터럽트를 사용할 수 없습니다. 따라서 데이터 송수신과 관련한 인터럽트를 발생시키도록 하는 설정이 필요합니다. [NVIC Settings] 탭에서 "USART3 global interrupt"를 활성화 한 뒤 저장합니다. (.ioc 파일을 저장하면 자동을 code generate 될 것입니다.)
그다음은 데이터 수신이 이루어졌을 때 인터럽트를 발생시키도록 설정하는 함수 HAL_UART_Receive_IT()를 추가합니다. 위치는 main 함수 안, while 문이 시작되기 전입니다. 이 함수에 전달해야 하는 인자는 총 3가지입니다. 첫 번째는 UART 핸들, 두 번째는 수신 버퍼의 포인터, 마지막으로 수실 데이터 크기입니다. UART 핸들의 타입은 UART_HandleTypeDef 이고, 정상적으로 code generation이 되었다면 이미 선언되어 있을 것입니다. 수신 버퍼의 타입은 unsigned char*가 되어야 합니다. 수신 데이터 크기는 설정한 크기만큼 데이터를 수신 받았을 때 인터럽트를 발생시키도록 하는 값입니다. 만약 크기 값을 10으로 설정하였다면 버퍼에 데이터가 10 byte 쌓였을 때 비로소 인터럽트가 발생합니다. 이 사실을 유의해서 사용해야 할 것입니다.
int main(void)
{
...
HAL_UART_Receive_IT(&huart3, rx_buff_temp, RX_BUFF_SIZE);
...
while (1)
{
...
}
}
데이터 수신이 완료되면 UART의 인터럽트 서비스 루틴에서 HAL_UART_RxCpltCallback() 함수를 호출합니다. 따라서 이 함수 안에서 할 일을 작성해야 합니다. 이 함수의 선언부는 만들어져 있지만 정의는 사용자가 직접 입력해야 합니다. 선언부는 저의 경우 stm32h7xx_hal_uart.h 에 있습니다. 사용하시는 MCU 모델에 따라서 헤더 파일 이름은 다를 수 있습니다.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* uartHandle)
{
...
}
이곳에서 해야 할 가장 기본적인 일은 두 가지입니다. 우선 수신 버퍼의 데이터를 다른 버퍼에 저장하도록 합니다. 수신 버퍼는 말 그대로 데이터 수신시에만 사용하는 버퍼입니다. 따라서 데이터를 어느 정도 쌓아두고 필요할 때 값을 꺼내 처리해야 할 때는 별도의 버퍼에 저장해두는 것이 좋다고 생각합니다. 아마 대부분의 상황에서 이러한 방법을 쓰지 않을까 싶습니다.
또 한 가지 이 곳에서 해야할 일이 있습니다. 그것은 바로 UART 통신 수신 인터럽트 설정 함수를 다시 한번 호출하는 일입니다. 그러나 우리는 분명히 main 함수의 while 문이 시작하기 전에 그 함수를 호출했었습니다. 그런데 왜 또다시 이 함수를 불러내야 할까요?
그 이유는 HAL_UART_Receive_IT() 함수에 의해서 설정한 인터럽트 활성 설정은 1회용이기 때문입니다. 한 번 인터럽트가 발생하면 해당 설정을 비활성화하도록 되어있습니다. 즉, 단 한 번의 수신만 가능하다는 것이다. 만약 UART 통신을 하는데 첫 바이트만 수신을 하고 나머지 바이트를 수신하지 못한다면 이와 관련된 내용을 확인해보시기 바랍니다. 우리는 데이터 1바이트를 수신한 뒤에 계속 데이터를 받고자 합니다. 따라서 현재 위치에 다시 수신 인터럽트 설정을 하도록 합니다.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* uartHandle)
{
rx_buff[buff_count] = rx_buff_temp[0];
buff_count += 1;
if (buff_count == 256)
{
buff_count = 0;
}
HAL_UART_Receive_IT(&huart3, rx_buff_temp, RX_BUFF_SIZE);
}
위 코드에서 rx_buff_temp는 크기가 1Byte인 수신 버퍼이며, rx_buff는 크기가 256Byte인 데이터 처리용 버퍼입니다. 그리고 buff_count는 데이터 처리용 버퍼의 현재 인덱스 값을 의미합니다. 데이터를 계속 수신하다가 인덱스 값이 256이 되면 다시 0으로 바꾸어 순환하도록 하였습니다. 마지막 줄에는 UART 수신 인터럽트 활성 설정을 하는 함수를 사용하고 있습니다.
'연구 노트 > Embedded' 카테고리의 다른 글
[MCS-51] AT89S52 특징 (0) | 2019.12.12 |
---|---|
[MCS-51] MCS-51 기본 구조 (0) | 2019.12.11 |
시리얼 데이터 통신을 위한 프로토콜 (0) | 2019.10.14 |
PWM으로 스텝모터 제어시 꼭 확인합시다. (0) | 2019.09.19 |
아두이노 설치 및 환경 설정 (0) | 2018.10.09 |