STM32H743基于HAL库实现串口中断发送+DMA空闲中断接收

1、STM32H743与STM32F1xx系列单片机在配置DMA数据流的不同:

STM32H743单片机在配置DMA数据流时,DMA1的7个数据流没有限定用于对用的通道。也就是说串口接收的DMA通道可以任意选择一个数据流

STM32F1xx则有DMA数据流和通道选择表,只能在对应的通道使用串口的DMA传输功能(具体内容参考SMT32F1xx的参考手册)。

2、HAL库

不同于标准库,HAL库提供了封装程度更加深的库接口。HAL库的结构:

**加粗样式**

使用HAL库的思路:使用STM32cubeMX配置得到初始化工程——>在main.c和stm32h7xx_it.c文件中实现用户代码——>开启或关闭中断(有时需要)——>实现中断回调函数

需要注意的是:HAL库在处理中断的函数中,不仅清空了中断标志位,还关闭了中断。这需要每次调用HAL提供的函数开启中断,在中断函数的回调函数中处理中断内容。因此,中断函数除了HAL库的中断处理函数外,一般不需要添加额外的代码。用户处理中断的代码添加在中断回调函数中就可以。

3、串口初始化过程分析

MX_USART1_UART_Init();//配置串口结构体:huart1;调用初始化函数:HAL_UART_Init()
//(总的来说是MX_xx——>HAL;MX开头表示有STM32CubeMX软件生成的代码,HAL开头表示由HAL库提供的接口函数)
//初始化回调函数,调用HAL_UART_MspInit(huart);芯片解决方案函数
——>#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    UART_InitCallbacksToDefault(huart);

    if (huart->MspInitCallback == NULL)
    {
      huart->MspInitCallback = HAL_UART_MspInit;
    }

    /* Init the low level hardware */
    huart->MspInitCallback(huart);
#else
    /* Init the low level hardware : GPIO, CLOCK */
    HAL_UART_MspInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
  }
//配置串口寄存器
——>UART_SetConfig(huart)
//清空中断标志位
——>CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
//使能串口
——>__HAL_UART_ENABLE(huart);
——>串口初始化函数结束,退出

 总的来说:初始换函数完成了四个部分:第一个是从模板接口函数调用HAL库初始化函数;第二个是配置中断回调函数;第三个是配置串口模式;第四个是清空中断标志位,使能串口。

4、DMA初始化代码分析

HAL_DMA_Init(&hdma_usart1_rx);//DMA初始化函数入口
//根据配置内容初始化DMA
——>/* Get the CR register value */
    registerValue = ((DMA_Stream_TypeDef   *)hdma->Instance)->CR;

    /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
    registerValue &= ((uint32_t)~(DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
                        DMA_SxCR_PL    | DMA_SxCR_MSIZE  | DMA_SxCR_PSIZE  | \
                        DMA_SxCR_MINC  | DMA_SxCR_PINC   | DMA_SxCR_CIRC   | \
                        DMA_SxCR_DIR   | DMA_SxCR_CT     | DMA_SxCR_DBM));

    /* Prepare the DMA Stream configuration */
    registerValue |=  hdma->Init.Direction           |
            hdma->Init.PeriphInc           | hdma->Init.MemInc           |
            hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
            hdma->Init.Mode                | hdma->Init.Priority;
//完成不同模式下的寄存器值配置
(代码太多,在HAL库中可以找到)
//此时的DMA对应的数据流已经完成对串口请求的配置,可以认为已经准备好
——>就绪状态,等待中断调用
——>如果串口为空闲中断模式,则DMA的中断可以不开。此时DMA只是实现数据搬运的功能。

以上内容全部是HAL库和STM32CubeMX软件实现,不需要用户自己实现。

5、用户需要调用的函数和处理的中断回调函数

前面提到,HAL库提供的接口函数中,执行一遍后,会将中断关闭。意思就是完成此次的需求后,回复到初始化状态,当下次需要时,重新调用则会开始新的一次。

a)串口阻塞式发送数据和接收数据的HAL库接口函数有:

(#) Blocking mode API's are :
        (+) HAL_UART_Transmit()
        (+) HAL_UART_Receive()

 b)串口中断式发送数据和接收数据的HAL库接口函数有:

(#) Non-Blocking mode API's with Interrupt are :
     (+) HAL_UART_Transmit_IT()
     (+) HAL_UART_Receive_IT()
     (+) HAL_UART_IRQHandler()

c)串口DMA发送数据和接收数据的HAL库接口函数有:

    (#) Non-Blocking mode API's with DMA are :
        (+) HAL_UART_Transmit_DMA()
        (+) HAL_UART_Receive_DMA()
        (+) HAL_UART_DMAPause()
        (+) HAL_UART_DMAResume()
        (+) HAL_UART_DMAStop()

d)串口中断回调函数有:(包括中断和终止的回调)

    (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
        (+) HAL_UART_TxHalfCpltCallback()
        (+) HAL_UART_TxCpltCallback()
        (+) HAL_UART_RxHalfCpltCallback()
        (+) HAL_UART_RxCpltCallback()
        (+) HAL_UART_ErrorCallback()

    (#) Non-Blocking mode transfers could be aborted using Abort API's :
        (+) HAL_UART_Abort()
        (+) HAL_UART_AbortTransmit()
        (+) HAL_UART_AbortReceive()
        (+) HAL_UART_Abort_IT()
        (+) HAL_UART_AbortTransmit_IT()
        (+) HAL_UART_AbortReceive_IT()

    (#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
        (+) HAL_UART_AbortCpltCallback()
        (+) HAL_UART_AbortTransmitCpltCallback()
        (+) HAL_UART_AbortReceiveCpltCallback()

以上,就是串口+DMA+空闲中断在HAL库下开发的分析过程。

到了实际应用过程,分两步:首先,调用HAL提供的串口接收/发送数据接口,其次在串口中断的回调函数中添加数据保存或清空的代码。

重要提示:不知为啥,HAL库中串口的空闲中断需要用户手动开启,还要配置一个接收模式的标志变量reception为空闲接收模式。并且在中断函数中还要调用HAL库提供的中断开启函数再次开启空闲中断和配置接收模式为空闲接收。通过代码分析,可以知道空闲中断的回调函数是:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
	HAL_UART_DMAStop(&huart1);
	do_for_usart1_recv_idle(Size);
	flag=0x01;
	HAL_UART_Receive_DMA(&huart1,usartRecvDataArr,BUFFERSIZE);
	huart1.ReceptionType=HAL_UART_RECEPTION_TOIDLE;
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
}

总结:使用HAL库分三步,第一步是分析HAL库提供的初始化过程中是否实现了需要的功能,比如空闲中断没开,就需要手动开启;第二步,确定调用阻塞还是非阻塞函数,发送和接收数据;第三步:找到中断回调函数,在回调函数中确定是否再次开启串口接收或发送,完成数据处理的代码。

至此,串口就能实现DMA+中断接收数据,串口中断发送数据。可分别进入不同的回调函数。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值