note:
- Article only portions of code based on the received serial data is recorded HAL.
- In this paper, USART2 STM32F103RCT6 example, the pin is TX-> PA2, RX-> PA3.
Part I: custom data structures:
#define UART_RECV_BUF_SIZE_TEMPORARY (64) // 临时缓存区大小
typedef struct
{
unsigned int uart_recv_len_temporary;// 临时缓存区接收到的数据长度
unsigned int uart_recv_len_formal;// 正式缓存区接收到的数据长度
unsigned char uart_recv_buf_temporary[UART_RECV_BUF_SIZE_TEMPORARY];// 临时缓存区
unsigned char uart_recv_buf_formal[UART_RECV_BUF_SIZE_TEMPORARY * 2];// 正式缓存区
}ts_uart_recv;
Part II: Custom global function:
/**
* This function enable uart interrupt and reset uart receive buff.
* @param uart_handle
* @param uart_recv
*/
void init_uart_interrupt(UART_HandleTypeDef* uart_handle, ts_uart_recv* uart_recv)
{
memset(uart_recv, 0, sizeof(ts_uart_recv));// Reset serial receiving memory.
__HAL_UART_ENABLE_IT(uart_handle, UART_IT_RXNE);// Enable UART_IT_RXNE.
__HAL_UART_ENABLE_IT(uart_handle, UART_IT_IDLE);// Enable UART_IT_IDLE.
__HAL_UART_CLEAR_IDLEFLAG(uart_handle);// Reset UART_FLAG_IDLE.
}
/**
* This function will be called in the interrupt function.
* @param uart_handle
* @param uart_recv
*/
void uart_interrupt_recv_callback(UART_HandleTypeDef* uart_handle, ts_uart_recv* uart_recv)
{
if(__HAL_UART_GET_FLAG(uart_handle, UART_FLAG_RXNE) != RESET)
{
unsigned char ch = uart_handle->Instance->DR;// Read a byte.
if(uart_recv->uart_recv_len_temporary < sizeof(uart_recv->uart_recv_buf_temporary))
{
uart_recv->uart_recv_buf_temporary[(uart_recv->uart_recv_len_temporary)++] = ch;// Store data in temporary cache.
}
__HAL_UART_CLEAR_FLAG(uart_handle, UART_FLAG_RXNE);// Reset UART_FLAG_RXNE.
}
if(__HAL_UART_GET_FLAG(uart_handle, UART_FLAG_IDLE) != RESET)
{
if (uart_recv->uart_recv_len_formal < sizeof(uart_recv->uart_recv_buf_formal))
{
memcpy(&uart_recv->uart_recv_buf_formal[uart_recv->uart_recv_len_formal],
uart_recv->uart_recv_buf_temporary,
uart_recv->uart_recv_len_temporary);// Save data from temporary cache to the end of formal cache.
uart_recv->uart_recv_len_formal += uart_recv->uart_recv_len_temporary;// Calculate data length in formal cache.
}
memset(uart_recv->uart_recv_buf_temporary, 0, uart_recv->uart_recv_len_temporary);// Reset temporary cache space.
uart_recv->uart_recv_len_temporary = 0;// Reset data length of temporary cache space.
/* Reset UART_FLAG_IDLE */
unsigned long temp;
temp = uart_handle->Instance->SR;// Must
temp = uart_handle->Instance->DR;// Must
__HAL_UART_CLEAR_IDLEFLAG(uart_handle);
}
}
Part III: hardware initialization and static variables defined
static UART_HandleTypeDef huart2;// uart2 handle.
static ts_uart_recv uart_recv_2;// uart2 receive cache.
/**
* This function is to configure UART2 hardware.
*/
void init_uart_2(void)
{
/* Enable clock*/
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Configure GPIO */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Configure NVIC */
HAL_NVIC_SetPriority(USART2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* Configure UART */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
/* Enable uart interrupt */
init_uart_interrupt(&huart2, &uart_recv_2);
}
Part IV: interrupt service function configuration
/**
* This function is uart2 interrupt server function.
*/
void USART2_IRQHandler(void)
{
uart_interrupt_recv_callback(&huart2, &uart_recv_2);
HAL_UART_IRQHandler(&huart2);
}