文本提供的代码是基于STM32CubeMX生成的HAL库的。
STM32串口接收大体分为3种方式:
1、阻塞接收---HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
2、中断接收---HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
3、DMA接收---HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
本文只谈论DMA接收方式,同时增加空闲中断和多级缓冲。单纯的DMA接收适合固定长度的数据接收,局限性太大,很难适用实际项目需要。增加空闲中断,可以做到不定长接收。多级缓冲在一定程度上可以缓解裸机代码实时性差的问题。
具体步骤如下:
1.STM32CubeMX生成工程,这里介绍串口部分的设置:
2.新建usart_ex.c文件,主要关注两个函数:void HW_UART_Modem_IRQHandler(UART_HandleTypeDef *huart)和void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)。
/**
******************************************************************************
* @file : usart_ex.c
* @author : xEndLess
* @version : V1.0.0
* @date : 2018-4-3
* @brief : 本文件是对usart.c的扩展,避免每次用Cube建立工程时,需要对usart.c做出修改.
* 串口发送函数,回调函数,DMA接收完成函数,都放在这里。
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#include "stdarg.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
Usart1_BufTypeDef Usart1Buf;
Usart2_BufTypeDef Usart2Buf;
Usart3_BufTypeDef Usart3Buf;
Usart4_BufTypeDef Usart4Buf;
Usart5_BufTypeDef Usart5Buf;
/* 以下4个变量是在uasrt.c中定义的 ,Cube自动生成 */
extern DMA_HandleTypeDef hdma_uart4_rx;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart3_rx;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/****************** UART CallBack *******************/
/**
* @brief Rx Transfer completed callback
* @param UartHandle: UART handle
* @note This example shows a simple way to report end of DMA Rx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
Usart1Buf.RxEndFlag[Usart1Buf.RxDimension] = SET;
Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] = USART1_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
Usart1Buf.RxDimension++;
Usart1Buf.RxDimension %= USART1_BUF_DIMENSION;