STM32 使用HAL库做串口的DMA发送和中断接收

发布者:mb5362443最新更新时间:2018-06-10 来源: eefocus关键字:STM32  HAL库  串口  的DMA发送  中断接收 手机看文章 扫描二维码
随时随地手机看文章

HAL库使用太死板

HAL串口中断接收

HAL库使用起来太不灵活,限制太多,后面如有时间,将使用寄存器和HAL库混合操作的方式。 
如使用串口中断接收,在接收到数据后,库里做了关闭接收非空中断RXNEIE,如下 
这里写图片描述

HAL库DMA发送

目前,我用的是DMA发送,本来向直接将数据扔给DMA,不想开发送DMA的中断,但是,HAL库考虑的比较周详,使用HAL库的DMA发送API,就会使用了DMA句柄中的相关标志位,这些标志位得你开了中断后,在DMA发送完成后,才会做相应的清除,并且,使用了__HAL_LOCK(),这样你用了他的库发送,剩下的其他处理你也得用他的库;前面说的,用了库的DMA发送,不开中断,就会因为上次是__HAL_LOCK()状态,导致无法继续执行,并且用了DMA发送后,还会标志几个标志位为BUSY状态,你如果不开中断,也得清除,总的来说,使用起来还是挺麻烦的,平白无故的多开了一个中断。

以下代码为STM32F7串口1的DMA发送和串口接收中断程序

实现代码

/**

  ******************************************************************************

  * @file    driver_uart.c

  * @author  Quentin.Que

  * @version V.0

    * @date    2017-12-14

  * @brief   所有串口底层的配置 

  ******************************************************************************

  */


/* Includes ------------------------------------------------------------------*/

#include "common_config.h"

#include "stm32f7xx_hal.h"  

#include "driver_uart.h"

/* Macros ------------------------------------------------------------------*/



/* Enumerations ------------------------------------------------------------------*/    



/* Type Definitions ------------------------------------------------------------------*/    

#define DEF_UART1_RX_BUF_SIZE   1   

#define DEF_UART1_DMA_TX_BUF_SIZE   200 


/* Private variables ---------------------------------------------------------*/

static UART_HandleTypeDef m_Uart1Handler;

static DMA_HandleTypeDef    m_DmaUart1Handler;

static INT8U Uart1RxBuf[DEF_UART1_RX_BUF_SIZE];

static INT8U Uart1DmaTxBuf[DEF_UART1_DMA_TX_BUF_SIZE];

static UART_RECEIVE_CALLBACK pFunUart1Callback = NULL;


/* Private function prototypes -----------------------------------------------*/    





/***********************************************************************

* @brief  初始化串口1

* @param  baudrate:波特率   

* @retval NONE

***********************************************************************/    

static void DRIVER_Uart1Init(INT32U baudrate)

{

    m_Uart1Handler.Instance = USART1;

    m_Uart1Handler.Init.BaudRate = baudrate;

    m_Uart1Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;

    m_Uart1Handler.Init.Mode = UART_MODE_TX_RX;

    m_Uart1Handler.Init.Parity = UART_PARITY_NONE;

    m_Uart1Handler.Init.StopBits = UART_STOPBITS_1;

    m_Uart1Handler.Init.WordLength = UART_WORDLENGTH_8B;


    HAL_UART_Init(&m_Uart1Handler); /* 串口初始化 */

    HAL_UART_Receive_IT(&m_Uart1Handler, (INT8U *)Uart1RxBuf, DEF_UART1_RX_BUF_SIZE);  /* 开中断,设置接收buf和大小 */


}   


/**************************************************************************************

  * @brief  设置串口1接收中断

  * @param  revice_callback:接收回调函数

  * @retval NONE

**************************************************************************************/

static void DRIVER_Uart1SetReviceCallback(UART_RECEIVE_CALLBACK revice_callback)    

{

    pFunUart1Callback = revice_callback;

}   


/***************************************************************************************

* @brief  DRIVER_UART1SendData

* @param  串口1发送

* @retval NONE

***************************************************************************************/    

static BOOLEAN DRIVER_UART1SendData(INT8U* pdata, INT16U len)

{

    INT16U real_len = 0;

    real_len = len > DEF_UART1_DMA_TX_BUF_SIZE ? DEF_UART1_DMA_TX_BUF_SIZE : len;  /* 强制截取 不能超过定义的缓存大小 */

    memcpy(Uart1DmaTxBuf, pdata,real_len);

    while(0 != __HAL_DMA_GET_COUNTER(&m_DmaUart1Handler))  /* 等待发送完成 */

    {

    }

  do 

    {

    }while(HAL_OK != HAL_UART_Transmit_DMA(&m_Uart1Handler, Uart1DmaTxBuf, real_len)); 


    return TRUE;

}


/***************************************************************************************

* @brief  HAL_UART_MspInit  会被HAL_UART_Init()调用

* @param  串口句柄

* @retval NONE

***************************************************************************************/    

void HAL_UART_MspInit(UART_HandleTypeDef *huart)    

{

    GPIO_InitTypeDef GPIO_Initure;

    if(USART1 == huart->Instance)

    {

        __HAL_RCC_GPIOA_CLK_ENABLE();

        __HAL_RCC_USART1_CLK_ENABLE();


        __HAL_RCC_DMA2_CLK_ENABLE();


        GPIO_Initure.Pin=GPIO_PIN_9;         

        GPIO_Initure.Mode=GPIO_MODE_AF_PP;   

        GPIO_Initure.Pull=GPIO_PULLUP;           

        GPIO_Initure.Speed=GPIO_SPEED_FAST;      

        GPIO_Initure.Alternate=GPIO_AF7_USART1;  

        HAL_GPIO_Init(GPIOA,&GPIO_Initure); 


        GPIO_Initure.Pin=GPIO_PIN_10;        

        HAL_GPIO_Init(GPIOA,&GPIO_Initure);


    /* Peripheral DMA init*/

    m_DmaUart1Handler.Instance = DMA2_Stream7;

        m_DmaUart1Handler.Init.Channel = DMA_CHANNEL_4;

    m_DmaUart1Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;

    m_DmaUart1Handler.Init.PeriphInc = DMA_PINC_DISABLE;

    m_DmaUart1Handler.Init.MemInc = DMA_MINC_ENABLE;

    m_DmaUart1Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    m_DmaUart1Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    m_DmaUart1Handler.Init.Mode = DMA_NORMAL;

    m_DmaUart1Handler.Init.Priority = DMA_PRIORITY_LOW;     


        HAL_DMA_DeInit(&m_DmaUart1Handler);

    HAL_DMA_Init(&m_DmaUart1Handler);


    __HAL_LINKDMA(huart,hdmatx,m_DmaUart1Handler); 


        HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 3, 0);

        HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);  


        HAL_NVIC_EnableIRQ(USART1_IRQn);

        HAL_NVIC_SetPriority(USART1_IRQn,3,0);           

    }

}


/********************************************************************************

* @brief  HAL_UART_RxCpltCallback  进入中断后HAL库会调用这个函数

* @param  串口句柄

* @retval NONE

*********************************************************************************/  

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

    if(USART1 == huart->Instance)

    {

        if(NULL != pFunUart1Callback)

        {

            pFunUart1Callback(Uart1RxBuf[0]); /* 将接收到的数据通过回调传出 */

        }

        do

        {


        }while(HAL_OK != HAL_UART_Receive_IT(&m_Uart1Handler, (INT8U *)Uart1RxBuf, DEF_UART1_RX_BUF_SIZE));  /* 开中断,设置接收buf和大小 */


    }


}


/*******************************************************************************

 * @brief  USART1_IRQHandler 串口1中断函数

 * @param  串口句柄

 * @retval NONE

*********************************************************************************/  

void USART1_IRQHandler(void)     

{

    HAL_UART_IRQHandler(&m_Uart1Handler);


}


/*******************************************************************************

 * @brief  DMA2_Stream7_IRQHandler 串口1DMA发送中断

 * @param  NONE

 * @retval NONE

*********************************************************************************/  

void DMA2_Stream7_IRQHandler(void)

{

  HAL_DMA_IRQHandler(&m_DmaUart1Handler); 


}


/***********************************************************************

* @brief  初始化串口 

* @param  port:串口号  baudrate:波特率  prx_fun:接收回调函数

* @retval TRUE:成功  FALSE:失败 

***********************************************************************/

BOOLEAN DRIVER_UARTInit(INT8U port, INT32U baudrate, UART_RECEIVE_CALLBACK prx_fun)

{

    switch(port)

    {

        case DRIVER_UART_PORT1:

            DRIVER_Uart1Init(baudrate);

            DRIVER_Uart1SetReviceCallback(prx_fun);

            break;


        default:

            return FALSE;

    }

    return TRUE;

}


/***********************************************************************

* @brief  串口发送

* @param  port:串口号  pdata:数据起始地址 len:长度

* @retval TRUE:成功  FALSE:失败 

***********************************************************************/

BOOLEAN DRIVER_UARTWrite(INT8U port, INT8U* pdata, INT16U len)

{

    switch(port)

    {

        case DRIVER_UART_PORT1:

            return DRIVER_UART1SendData(pdata, len);

        default:

            return FALSE;

    }


}


关键字:STM32  HAL库  串口  的DMA发送  中断接收 引用地址:STM32 使用HAL库做串口的DMA发送和中断接收

上一篇:STM32串口发送不正常
下一篇:STM32F10X USART 中断接受+发送,测试无误

推荐阅读最新更新时间:2024-03-16 16:05

STM32片上外设时钟使能 失能和复位区别
今天分享的关于时钟知识,可能很多人没有在意过。这也是之前有朋友问过的问题,这里就简单给大家普及一下吧。 1 RCC时钟说明 在STM32参考手册中,都有Reset and Clock Control(RCC)复位和时钟控制的章节。 在这一章节就可以看到有两类寄存器:peripheral reset register(RSTR)外设复位寄存器和peripheral clock enable register(ENR)外设时钟使能寄存器。 我们拿STM32F1参考手册为例,可以看到如下图寄存器: 一种是控制外设时钟的寄存器,一种是复位外设的寄存器。 2 外设时钟使能和失能 我们都知道,配置STM32外设,会先开启对应的时钟
[单片机]
<font color='red'>STM32</font>片上外设时钟使能 失能和复位<font color='red'>的</font>区别
单片机串口通信编程总结
本次小结的主要目的是更加明确单片机的串口中断是如何发生的。即:是如何触发串口中断的发送功能的。在说明中我使用特殊的字体颜色来强调重点部分和注意事项。 程序一: 本程序是使用软件设置TI来实现串口中断的触发,如果在初始化函数中不增加 TI=1; 这条语句,那么是不会触发中断的 #include STC89C5X.h //包含51单片机的头文件 #define uint unsigned int #define uchar unsigned char /* 串口通讯接口定义 RXD-------P3.0 数据接收端 TXD-------P3.1 数据发送端 */ /*====================
[单片机]
应用笔记 | MPU 子区话题
1. 问题起因 有人询问STM32F7 和STM32H7 系列库例程中有关MPU 配置中的下面这句加绿色下划线的代码的意思是什么?有何用? 图1、芯片存储空间MPU 背景配置 从上面截图中的红色框内代码我们不难看出,这里进行MPU 设置就是将从0 开始的4G 空间,即整个STM32 可寻址空间定义为Strongly Ordered 存储属性。且此时MPU Region 编号为0。可代码注释上又说只是将未定义的区域配置为Strongly Ordered,这未定义区域到底啥意思,该如何理解?难道跟绿色下划线标示的那行代码有关系。 那么,这句代码MPU_InitStruct.SubRegionDisable = 0x87;
[单片机]
应用笔记 | MPU 子区话题
S3C2440串口基本使用
2440A有三个串口,我们使用串口0对它进行了解熟悉。 首先肯定是应该找到手册上串口0所对应的引脚,然后配置相应寄存器。 串口0对应GPIO H的 2,3 串口在单片机中我们已经有很多使用经验了,对于协议采用 8-N-1,8bit数据位,无校验,1停止位。 说明波特率的计算方式: 把串口对应IO配置成 TX和RX功能之后,我们需要对指定寄存器进行读写操作,实现串口的接发。 具体的寄存器就不贴出来了。手册上都有,这里不使用FIFO和中断方式,只是最基本的接发操作。 main.c: #include s3c2440_gpio.h #include s3c2440_soc.h #include uart.h
[单片机]
S3C2440<font color='red'>串口</font><font color='red'>的</font>基本使用
STM32笔记——外部中断配置
一、选择对应芯片 常规操作,这里我们选择F407ZGT6 二、配置sys 选择Serial Wire 三、配置RCC 选择高速外部时钟晶振,系统自动配置相应引脚。 四、配置外部中断引脚 通过查看开发板原理图,找出按键对应引脚 五、设置外部中断引脚 1、上升沿触发(外部中断触发引脚上的电平从低电平跳转到高电平) 2、下降沿触发(外部中断触发引脚上的电平从高电平跳转到低电平) 3、上下边沿均触发 (外部中断触发引脚上有电平变化) 六、开启外部中断 七、配置中断优先级 八、配置时钟 九、生成工程 HAL库GPIO函数库讲解 1、外部中断服务函数 void HAL_GPIO_EXTI_IRQ
[单片机]
<font color='red'>STM32</font>笔记——外部<font color='red'>中断</font><font color='red'>的</font>配置
STM32中assert_param使用
在STM32的固件库和提供的例程中,到处都可以见到assert_param()的使用。如果打开任何一个例程中的stm32f10x_conf.h文件,就可以看到实际上assert_param是一个宏定义; 在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数。所谓有效的参数是指满足规定范围的参数,比如某个参数的取值范围只能是小于3的正整数,如果给出的参数大于3,则这个assert_param()可以在运行的程序调用到这个函数时报告错误,使程序员可以及时发现错误,而不必等到程序运行结果的错误而大费周折。 这是一种常见的软件技术,可以在调试阶段帮助程序员快速地排除那些明显的错误。它确实
[单片机]
sTM32 使用TIMx_CH1作为 Tx1F_ED 计数器时钟
环境:iar arm 5.3 stm32f103vbt6 使用PA.8 外部输入10Mhz的方波。可从systick中断得到数据4. 4×5000(预分频值)×1000(tick中断时间)=20MHz 属于双边沿检测,一个PA.8个脉冲有2个边沿,所以时钟加倍。 由于使用了TI1F_ED它的结构如下: void RCC_Configuration( void ) { /* Setup STM32 system (clock, PLL and Flash configuration) */ SystemInit( ); /* Enable GPIOA, GPIOC and USART1 clock */ RCC
[单片机]
<font color='red'>sTM32</font> 使用TIMx_CH1作为 Tx1F_ED 计数器时钟
AVR串口下载线DIY
很多朋友都遇到过并口损坏的时候,这时并口下载线就无用武之地了,其实,对于台式机来说多数都是并口插座引脚对地的小电容漏电的原因,直接去掉即可,当然也有主板上串并口芯片损坏的。 而USB接口的下载线制作很麻烦,这里介绍一种串口的AVR下载线,也非常的好用,速度较快。源码测试正确。 软件用AVR STUDIO 熔丝位设置 FUSE:L=BF,H=C9 BOD打开设成2.7V,防止EEPROM损坏,设成2.7V是为了适应3.3V或5V供电。3.3V供电时要用MAX3232。 固件: ourdev_432579.rar 使用方法: 所有元器件安装好后,将设置开关扳到“自编程”位置,用并口编程器和此板连接好,编程后再把设置开关扳
[单片机]
AVR<font color='red'>串口</font>下载线DIY
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved