单片机
返回首页

stm32串口HAL库的DMA发送问题

2019-08-30 来源:eefocus

本文使用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)

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

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何构建一个触摸传感器电路

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章