stm32串口HAL库的DMA发送问题

发布者:Quail最新更新时间:2019-08-30 来源: eefocus关键字:stm32  串口  HAL库  DMA发送 手机看文章 扫描二维码
随时随地手机看文章

本文使用stm32f411ret的串口1的DMA方式发送数据,刚开始调试的时候发现串口只能发送一次数据,之后就把系统hang住了。通过网上搜资料和不断尝试,发现问题是中断回调函数没有写的原因。


使用HAL库的DMA,需要同时实现DMA中断回调函数和串口中断回调函数。


void DMA2_Stream7_IRQHandler(void)

{

    HAL_DMA_IRQHandler(Uart1Handle.hdmatx);

}

 

void USART1_IRQHandler(void)

{

  HAL_NVIC_ClearPendingIRQ(USART1_IRQn);

  HAL_UART_IRQHandler(&Uart1Handle);

}

下面附上我的dma配置和串口配置函数


dma配置


void HAL_UART1_dma_Init(void)

{

  static DMA_HandleTypeDef hdma_tx;

 

  __HAL_RCC_DMA2_CLK_ENABLE();                //打开DMA2时钟

  /*##-3- Configure the DMA streams ##########################################*/

  /* Configure the DMA handler for Transmission process */

  hdma_tx.Instance                 = DMA2_Stream7;      

  hdma_tx.Init.Channel             = DMA_CHANNEL_4;        //串口1发送属于stream7、channel4,可在参考手册的DMA章节查到

  hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;    //数据发送方向:内存->外设

  hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;        //外设为串口,地址不需要增加

  hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;        //存储需要增加

  hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    //串口为字节

  hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;    //与串口设置要一致

  hdma_tx.Init.Mode                = DMA_NORMAL;              //一次发送,如果设置为循环模式,会一直不停的发 

  hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;        //低优先级

  hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    

  hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;

  hdma_tx.Init.MemBurst            = DMA_MBURST_INC4;

  hdma_tx.Init.PeriphBurst         = DMA_PBURST_INC4;

  

  HAL_DMA_Init(&hdma_tx);   

  

  /* Associate the initialized DMA handle to the the UART handle */

  __HAL_LINKDMA(&Uart1Handle, hdmatx, hdma_tx);            //将dma的发送handle赋值给串口1的hdmatx成员

  /*##-4- Configure the NVIC for DMA #########################################*/

  /* NVIC configuration for DMA transfer complete interrupt (USARTx_TX) */

  HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 1);           //设置dma中断优先级

  HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);                   //使能dma中断

}

串口引脚配置


void Init_Usart1(void)

{

GPIO_InitTypeDef  GPIO_InitStruct;

  

  /*##-1- Enable peripherals and GPIO Clocks #################################*/

  /* Enable GPIO TX/RX clock */

  __HAL_RCC_GPIOA_CLK_ENABLE();  

  /* Enable USARTx clock */

   __HAL_RCC_USART1_CLK_ENABLE();

  

  /*##-2- Configure peripheral GPIO ##########################################*/  

  /* UART TX GPIO pin configuration  */

  GPIO_InitStruct.Pin       = GPIO_PIN_9;

  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;

  GPIO_InitStruct.Pull      = GPIO_PULLUP;

  GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;

  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;

  

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    

  /* UART RX GPIO pin configuration  */

  GPIO_InitStruct.Pin = GPIO_PIN_10;

  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;

    

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

HAL_NVIC_SetPriority(USART1_IRQn,0,0);

HAL_NVIC_EnableIRQ(USART1_IRQn);

}

串口配置


void Usart1_Configuration(uint32_t BaudRate)

{    

  Uart1Handle.Instance          = USART1;

  

  Uart1Handle.Init.BaudRate     = BaudRate;

  Uart1Handle.Init.WordLength   = UART_WORDLENGTH_8B;

  Uart1Handle.Init.StopBits     = UART_STOPBITS_1;

  Uart1Handle.Init.Parity       = UART_PARITY_NONE;

  Uart1Handle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;

  Uart1Handle.Init.Mode         = UART_MODE_TX_RX;

  Uart1Handle.Init.OverSampling = UART_OVERSAMPLING_16;

    

  if(HAL_UART_Init(&Uart1Handle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler(); 

  }

    

}

发送数据调用下面的函数即可


HAL_UART_Transmit_DMA(&Uart1Handle, (uint8_t*)aTxBuffer, 32)

实际操作时可以在串口中断中设置一个标志位,用来标记串口发送完成,在主程序中用标志位控制对发送函数的调用。

关键字:stm32  串口  HAL库  DMA发送 引用地址:stm32串口HAL库的DMA发送问题

上一篇:STM32学习笔记1-----初识stm32F429IGT6
下一篇:STM32F4串口接收(HAL库)使用笔记

推荐阅读最新更新时间:2024-11-10 12:18

STM32硬件调试详解
STM32的基本系统主要涉及下面几个部分:   一、电源   1)、无论是否使用模拟部分和AD部分,MCU外围出去VCC和GND,VDDA、VSSA、Vref(如果封装有该引脚)都必需要连接,不可悬空;   2)、对于每组对应的VDD和GND都应至少放置一个104的陶瓷电容用于滤波,并接该电容应放置尽量靠近MCU; 3)、用万用表测试供电电压是否正确。调试时最好用数字电源供电,以便过压或过流烧坏板子。电压最好一步一步从进线端测试到芯片供电端。   二、复位、启动选择   1)、Boot引脚与JTAG无关。其仅是用于MCU启动后,判断执行代码的起始地址;   2)、在电路设计上可能Boot引脚不会使用,但要求一定要外部连接电阻到地或
[单片机]
<font color='red'>STM32</font>硬件调试详解
STM32-蜂鸣器实验
一,蜂鸣器介绍 蜂鸣器分有源蜂鸣器和无源蜂鸣器,这里的源指的是震荡源 一般我们使用有源蜂鸣器,如图:   有两个引脚,较长的一端为正极,较短的一段为负极 二,蜂鸣器硬件连接: 蜂鸣器负极连接在STM32的PB8引脚: 错误的连接方法: IO口接蜂鸣器接地 错误的臆想: IO口输出高电平,蜂鸣器正负极产生电压差,蜂鸣器发出声响 错误分析: STM32IO口电流驱动能力非常有限,不能通过IO口驱动大功率硬件,需要通过三极管来驱动(三极管的放大作用),将IO口输出的小电流放大为大电流(放大倍数β) R38作用: STM32芯片复位后IO口默认为浮空状态,IO口电平是不确定的,有可能跳边的电流经过三极管被放大使蜂鸣器
[单片机]
STM32-蜂鸣器实验
STM32的SYSTICK详解
什么是SYSTICK: 这是一个24位的系统节拍定时器system tick timer,SysTick,具有自动重载和溢出中断功能,所有基于Cortex_M3处理器的微控制器都可以由这个定时器获得一定的时间间隔。 作用: 在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。要解决这个问题,可以使用实时操作系统(RTOS). 因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有
[单片机]
<font color='red'>STM32</font>的SYSTICK详解
stm32定时器捕捉高低电平计时长代码分析
定时器是stm32的一大利器,现在的项目中可以说没有一个不会用到定时器的,所以掌握理解运用定时器才会做出好的产品来。 本章内容说一说关于stm32的定时器TIM_GetCounter(TIMx)的运用。之前的项目中曾经用这个来获取高低电平的时长,在超声波测距,红外遥控解码中运用过。Stm32的定时器除了1和8其他都是通用定时器。如何用这句函数来捕捉电平时长呢?首先看一下初始化内容,以TIM4为例 void Timer4_CFG() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1Per
[单片机]
stm32 gpio口的库函数配置
库函数的配置方法 1.例程 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); 2.GPIO_InitTypeDef GPIO_InitS
[单片机]
基于STM32神舟系列开发板的读取绝对式编码器源码
#include stm32f10x.h #include stm32f10x_usart.h #include #include #include #define CMD_BUFFER_LEN 100 GPIO_InitTypeDef GPIO_InitStructure; void Delay(__IO uint32_t nCount) { for(; nCount != 0; nCount--); } void RCC_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClo
[单片机]
stm32专题十七:深度解析 stm32 硬件iic (i2c)
首先是配置I2C的GPIO,然后配置I2C参数。就是常规配置,按流程来写不会错。 /** * @brief EEPROM IIC 配置 */ void I2C_EE_config(void) { GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; // 开启I2C GPIO时钟 EPROM_I2C_GPIO_APBxClkCmd(EEPROM_I2C_SCL_GPIO_CLK | EEPROM_I2C_SDA_GPIO_CLK, ENABLE); // 开启I2C 外设时钟 EEPROM_I2C_APBxC
[单片机]
<font color='red'>stm32</font>专题十七:深度解析 <font color='red'>stm32</font> 硬件iic (i2c)
STM32之如何封装自己的lib库
似乎stm32刚开始出来的时候就是用的l.ib库,后来就开源了。 网上看了一些网友做的lib库,自己也弄了一下,其实也挺简单。 以下封装lib库都是基于stm32的3.0固件库 1、打开一个工程,将除固件库以外的其他文件删掉,如下: 2、在option下进行设置,如下: 来个特写: 3、将编译好的lib库拷贝到另外一个工程,添加进去,并将工程下库的c文件全部删除(h文件必须保留) 4、编译,如下: 注意,只需将stm32_lib_30.lib文件add进去就可以了,没必要在主文件里面include之类的。 否则编译的时候就会出错(重复包含),如下:
[单片机]
<font color='red'>STM32</font>之如何封装自己的lib库
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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