硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1883|回复: 4
收起左侧

[DMA] 高版本HAL库串口DMA收发,直接可以使用回调函数去进行接收处理,无需自己再写DMA处理函数

[复制链接]

29

主题

103

回帖

190

积分

初级会员

积分
190
发表于 2024-10-20 10:26:28 | 显示全部楼层 |阅读模式
/*
*********************************************************************************************************
*
*        模块名称 : IWDG 初始化
*        文件名称 : bsp_iwdg.c
*        版    本 : V1.0
*        说    明 : IWDG 初始化
*
*        修改记录 :
*                版本号  日期             作者              说明
*                V1.0    2022-04-08      
*
*********************************************************************************************************
*/
#include "bsp.h"
#include "bsp_uart.h"

/*
*********************************************************************************************************
*                                            变量定义
*********************************************************************************************************
*/


#define UART1_BAUD        115200

#define UART1_TX_BUF_SIZE        1 * 256
#define UART1_RX_BUF_SIZE        1 * 256

UART_T g_tUart1;
static uint8_t g_TxBuf1[UART1_TX_BUF_SIZE];
static uint8_t g_RxBuf1[UART1_RX_BUF_SIZE];

static UART_HandleTypeDef huart1 = {0};

static DMA_HandleTypeDef hdma_uart1_tx = {0};
static DMA_HandleTypeDef hdma_uart1_rx = {0};


//static void USART1_TX_DMA_Config(UART_HandleTypeDef* huart);
//static void USART1_RX_DMA_Config(UART_HandleTypeDef* huart);
/*
*********************************************************************************************************
*        函 数 名: USART1_TX_DMA_Config
*        功能说明: 串口接发送DMA初始化
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void USART1_TX_DMA_Config(UART_HandleTypeDef* huart)
{
        __HAL_RCC_DMAMUX1_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();

        /* USART1_TX_DMA Init */
        hdma_uart1_tx.Instance = DMA1_Channel1;
        hdma_uart1_tx.Init.Request = DMA_REQUEST_USART1_TX;
        hdma_uart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        hdma_uart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_uart1_tx.Init.MemInc = DMA_MINC_ENABLE;
        hdma_uart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_uart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        hdma_uart1_tx.Init.Mode = DMA_NORMAL;
        hdma_uart1_tx.Init.Priority = DMA_PRIORITY_LOW;
        if (HAL_DMA_Init(&hdma_uart1_tx) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }

        __HAL_LINKDMA(huart, hdmatx, hdma_uart1_tx);

        /* DMA1_Channel1_IRQn interrupt configuration */
        HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
       
}

/*
*********************************************************************************************************
*        函 数 名: USART1_RX_DMA_Config
*        功能说明: 串口接收DMA初始化
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void USART1_RX_DMA_Config(UART_HandleTypeDef* huart)
{
        __HAL_RCC_DMAMUX1_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();


        /* USART1_RX_DMA Init */
        hdma_uart1_rx.Instance = DMA1_Channel2;
        hdma_uart1_rx.Init.Request = DMA_REQUEST_USART1_RX;
        hdma_uart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        hdma_uart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_uart1_rx.Init.MemInc = DMA_MINC_ENABLE;
        hdma_uart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_uart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        hdma_uart1_rx.Init.Mode = DMA_NORMAL;
        hdma_uart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
        if (HAL_DMA_Init(&hdma_uart1_rx) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }

        __HAL_LINKDMA(huart, hdmarx, hdma_uart1_rx);

        /* DMA1_Channel2_IRQn interrupt configuration */
        HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
       

}

/*
*********************************************************************************************************
*        函 数 名: uart_var_init
*        功能说明: 串口参数初始化
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
static void UartVarInit(void)
{
        g_tUart1.uart = USART1;
        g_tUart1.huart = &huart1;
        g_tUart1.hdma_tx = &hdma_uart1_tx;
        g_tUart1.hdma_rx = &hdma_uart1_rx;
        g_tUart1.pTxBuf = g_TxBuf1;
        g_tUart1.pRxBuf = g_RxBuf1;
        g_tUart1.usTxBufSize = UART1_TX_BUF_SIZE;
        g_tUart1.usRxBufSize = UART1_RX_BUF_SIZE;
        g_tUart1.usTxCount = 0;
        g_tUart1.usRxCount = 0;
        g_tUart1.ucTxFrame = 0x00;
        g_tUart1.ucRxFrame = 0x00;
       
}



/*
*********************************************************************************************************
*        函 数 名: UartSend_Buff
*        功能说明: 发送函数
*        形    参:
*        返 回 值: 无
*********************************************************************************************************
*/
uint8_t UartSend_Buff(UART_T *_pUart, uint8_t *_ucpBuf, uint16_t _usLen)
{
        if(_pUart->ucTxFrame != 0x00)
        {
                return _FALSE;   
        }
        if(_usLen > _pUart->usTxBufSize)   
        {
                return _FALSE;                           
        }

        _pUart->usTxCount = _usLen;
        memcpy(_pUart->pTxBuf, _ucpBuf, _pUart->usTxCount);   /* 复制数据到发送缓冲区 */
        HAL_UART_Transmit_DMA(_pUart->huart, _pUart->pTxBuf, _pUart->usTxCount);   /* 使能中断将数据发送出去 */
        _pUart->ucTxFrame = 0x01;
    return _TRUE;       
}




/*
*********************************************************************************************************
*        函 数 名: bsp_UartInit
*        功能说明: 初始化串口
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_UartInit(void)
{
        UartVarInit();

        /* USER CODE END USART1_Init 1 */

        huart1.Instance = USART1;
        huart1.Init.BaudRate = UART1_BAUD;
        huart1.Init.WordLength = UART_WORDLENGTH_8B;
        huart1.Init.StopBits = UART_STOPBITS_1;
        huart1.Init.Parity = UART_PARITY_NONE;
        huart1.Init.Mode = UART_MODE_TX_RX;
        huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        huart1.Init.OverSampling = UART_OVERSAMPLING_16;
        huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
        huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
        huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
          
        /* USART1 DMA Init */               
        /* USART1_TX Init */
        USART1_TX_DMA_Config(&huart1);
        /* USART1_RX Init */
        USART1_RX_DMA_Config(&huart1);
       
        if (HAL_UART_DeInit(&huart1) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }       
       
        if (HAL_UART_Init(&huart1) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }
        if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }
        if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }
        if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
        {
                Error_Handle(__FILE__, __LINE__);
        }
       
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_tUart1.pRxBuf, g_tUart1.usRxBufSize);  /* 使能DMA接收,空闲中断触发 */
}





/*
*********************************************************************************************************
*        函 数 名: Get_UartPtr
*        功能说明:
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
UART_T *Get_UartPtr(UART_HandleTypeDef *huart)
{
        UART_T *Ptr = 0;
       
        if(huart->Instance == USART1)
        {
                Ptr = &g_tUart1;
        }
               
        return Ptr;
}



/**
  * @brief  Reception Event Callback (Rx event notification called after use of advanced reception service).
  * @param  huart UART handle
  * @param  Size  Number of data available in application reception buffer (indicates a position in
  *               reception buffer until which, data are available)
  * @retval None
  */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
        UART_T *_pUart;
       
        _pUart = Get_UartPtr(huart);
       
        _pUart->ucRxFrame = 0x01;
        _pUart->usRxCount = Size;
        HAL_UARTEx_ReceiveToIdle_DMA(_pUart->huart, _pUart->pRxBuf, _pUart->usRxBufSize);
}

/**
  * @brief  Tx Transfer completed callback
  * @param  huart: UART handle.
  * @note   This example shows a simple way to report end of DMA Tx transfer, and
  *         you can add your own implementation.
  * @retval None
  */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
        UART_T *_pUart;
       
        _pUart = Get_UartPtr(huart);
       
        _pUart->ucTxFrame = 0x00;
}

/**
  * @brief  UART error callback.
  * @param  huart UART handle.
  * @retval None
  */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
        UART_T *_pUart;
       
        _pUart = Get_UartPtr(huart);
       
        HAL_UARTEx_ReceiveToIdle_DMA(_pUart->huart, _pUart->pRxBuf, _pUart->usRxBufSize);
}

/*
*********************************************************************************************************
*        函 数 名: UART_TX_DMA_IRQn
*        功能说明:
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void UART_TX_DMA_IRQn(UART_T *_pUart)
{
        HAL_DMA_IRQHandler(_pUart->hdma_tx);
}





/*
*********************************************************************************************************
*        函 数 名: UART_RX_DMA_IRQn
*        功能说明:
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void UART_RX_DMA_IRQn(UART_T *_pUart)
{
        HAL_DMA_IRQHandler(_pUart->hdma_rx);
}





/*
*********************************************************************************************************
*        函 数 名: UART_IRQn
*        功能说明:
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void UART_IRQn(UART_T *_pUart)
{
        HAL_UART_IRQHandler(_pUart->huart);
}



切记当串口进错误回调时,需再次使能DMA空闲接收中断,否则接收会失败!



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117564
QQ
发表于 2024-10-20 15:36:38 | 显示全部楼层
可以参考这个修改下

STM32H7基于STM32CubeMX的串口DMA+空闲中断接收不定长数据实现(HAL库1.9.0自带函数实现)
https://forum.anfulai.cn/forum.p ... 8553&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

10

主题

36

回帖

66

积分

初级会员

积分
66
发表于 2024-10-20 15:46:20 | 显示全部楼层
高版本的HAL是加了空闲中断的处理吗?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117564
QQ
发表于 2024-10-20 15:47:15 | 显示全部楼层
Devil_920 发表于 2024-10-20 15:46
高版本的HAL是加了空闲中断的处理吗?

对,也加入了函数HAL_UARTEx_ReceiveToIdle_DMA
回复

使用道具 举报

29

主题

103

回帖

190

积分

初级会员

积分
190
 楼主| 发表于 2024-10-22 08:44:04 | 显示全部楼层
eric2013 发表于 2024-10-20 15:36
可以参考这个修改下

STM32H7基于STM32CubeMX的串口DMA+空闲中断接收不定长数据实现(HAL库1.9.0自带函数 ...

好的,感谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-14 17:35 , Processed in 0.053919 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表