串口数据的接收可以用三种方式:
1、阻塞方式(接收数据很少用到)
2、中断方式(用的比较多,但是在接收不定长协议数据时候,逻辑判断较复杂)
3、DMA IDLE方式(常用做接收不定长数据)
用cubemx配置下串口驱动如下
接收数据用到的结构体
#define uart_buf_size 256
typedef union{
struct{
uint8_t buf[uart_buf_size];
uint8_t timeout;
uint16_t len;
}bf;
uint8_t data[uart_buf_size+3];
}uart_struct_t;
使能串口空闲中断
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1,(uint8_t *)&uart_info.bf.buf[0],uart_buf_size);
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
重定义printf需要在头文件中加入stdio.h,同时也添加下string.h好使用memxxx函数
int fputc(int ch, FILE *f)
{
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC) != SET);
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,100);
return ch;
}
中断中进行数据的处理
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_UART_DMAStop(&huart1);
if(uart_info.bf.timeout == 0)
{
uart_info.bf.timeout = 1;
uart_info.bf.len = uart_buf_size - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
HAL_UART_Transmit(&huart1,(uint8_t *)&uart_info.bf.buf[0],uart_info.bf.len,100);
}
uart_info.bf.timeout = 0;
memset(uart_info.bf.buf,0,uart_buf_size);
HAL_UART_Receive_DMA(&huart1,(uint8_t *)&uart_info.bf.buf[0],uart_buf_size);
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
以上代码是将接收到的数据原样返回