STM32-UART-DMA HAL库缓冲收发

这篇具有很好参考价值的文章主要介绍了STM32-UART-DMA HAL库缓冲收发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、说明

1.1、注意事项:

  • HAL库的DMA底层基本都会默认开启中断使能,如果在STM32CubeMx禁用了中断相关的功能,程序可能会进入空中断回调出不来。
  • 切记使用STM32-HAL库的DMA发送时需要开启USART中断和DMA中断。
  • 在一般时间要求不是很高很高的场合,使用HAL库自带的函数就可以,并不会很频繁的触发中断占用资源。

1.2、接收部分

  • 接收DMA初始化成循环传输模式。开启对应DMA通道中断和串口全局中断
  • 之前担心开启串口中断会在接收数据时连续触发中断、导致消耗CPU资源,实际HAL底层未开启接收中断,不会触发中断。

1.3、发送部分

  • 发送时如果要使用DAM功能,必须开启DMA中断和串口中断。HAL的全局状态需要在中断中得到更新,否则会发送完一次状态一直处于被占用中。
  • HAL底层开启了串口数据发送完成中断TC。该中断只有在DMA没有新的数据传入后,并且移位寄存器为空时才会触发一次,不会每发送一个字节就会触发中断

STM32-UART-DMA HAL库缓冲收发,stm32,单片机,嵌入式硬件


STM32-UART-DMA HAL库缓冲收发,stm32,单片机,嵌入式硬件

2、代码

2.1、初始化

初始化接收即可,发送会在有数据时才会去操作DMA
开启中断


STM32-UART-DMA HAL库缓冲收发,stm32,单片机,嵌入式硬件


STM32-UART-DMA HAL库缓冲收发,stm32,单片机,嵌入式硬件

 
#include "SEGGER_RTT.h"

#define TX_FIFO_SIZE 36
#define RX_FIFO_SIZE 128

static uint8_t rxbuff[RX_FIFO_SIZE];
static uint8_t txbuff[TX_FIFO_SIZE];

static uint16_t tx_tail = 0;
static uint16_t tx_head = 0;

2.2、缓冲接收

循环接收、需要开启DMA和UART中断

void dma_uart_init()
{
  HAL_UART_Receive_DMA(&huart1, rxbuff, RX_FIFO_SIZE);
}
///查询读取一个字节数据
int dma_uart_read_char()
{
  static int rx_tail = 0;
  int rx_head = (RX_FIFO_SIZE)-huart1.hdmarx->Instance->CNDTR; // 接收到的数据偏移量
  if (rx_head != rx_tail)
  {
    int ch = rxbuff[rx_tail++];
    if (rx_tail >= RX_FIFO_SIZE)
    {
      rx_tail = 0;
    }
    return ch;
  }
  return -1;
}

2.3、缓冲发送

单次DMA发送,需要开启DMA和UART中断文章来源地址https://www.toymoban.com/news/detail-801703.html

///查询状态并触发一次发送
static void dma_uart_write_trig()
{
  static int lock = 0;
  if (lock)//中断重入锁
    return;
  lock = 1;

  if (huart1.gState == HAL_UART_STATE_READY)
  {
    static uint8_t dma_tx_fifo[128];
    for (size_t n = 0; n < 128; n++)
    {
      if (tx_head != tx_tail)
      {
        dma_tx_fifo[n] = txbuff[tx_tail++];
        if (tx_tail >= TX_FIFO_SIZE)
          tx_tail = 0;
      }
      else
      {
        if (n > 0)
        {
          HAL_UART_Transmit_DMA(&huart1, dma_tx_fifo, n);
        }
        break;
      }
    }
  }
  lock = 0;
}

///DMA缓冲发送多个字节数据
void dma_uart_writes(const uint8_t *data, int size)
{
  for (size_t i = 0; i < size; i++)
  {
    uint16_t tmp = tx_head + 1;
    if (tmp >= TX_FIFO_SIZE)
    {
      tmp = 0;
    }
#if 0 // 丢弃新的数据
    if (tmp == tx_tail) // 数据溢出 发送慢于写入
    {
      break;  
    }
#else // 等待旧数据发送完
    if (tmp == tx_tail)
    {
      while (tmp == tx_tail)
      {
      }
    }
#endif
    txbuff[tx_head] = data[i];
    tx_head = tmp;
  }
  dma_uart_write_trig();
}

///中断回掉函数,该函数由串口发送完成中断TC触发
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  dma_uart_write_trig();
}

2.4、格式化打印

#include "stdarg.h"
#include "stdio.h"

#define PRINT_BUFF_SIZE 500
static char print_buff[PRINT_BUFF_SIZE];
void print_x(void *format, ...)
{
  va_list ap;
  va_start(ap, format);
  int n = vsnprintf(print_buff, PRINT_BUFF_SIZE, format, ap);
  va_end(ap);
  if (n > 0)
  {
    dma_uart_writes((uint8_t *)print_buff, n);
  }
}

到了这里,关于STM32-UART-DMA HAL库缓冲收发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32 hal库uart使用 DMA中断只能发送一次的问题

    1.stm32 uart使用DMA,无论发送还是接收都各自有一个数据流中断。这个数据流中断是框架代码不必过多关心。 2.使用了DMA后,uart的global中断是否要使用?标准做法是在cubemx上要勾选的,不然,就会产生只能发送一次的问题。 问题的原因? 我相信这是hal库的问题,理论上讲有一

    2024年02月11日
    浏览(38)
  • stm32中HAL_UART_Transmit_DMA,串口只能发送一次。

    配置串口+DMA不产生DMA中断方式, 1、HAL_UART_Transmit_DMA中调用HAL_DMA_Start_IT,在HAL_DMA_Start_IT中虽然开启了三个中断:hdma-Instance-CR  |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME,但是没有开DMA总中断,所以这3个不起作用;同时,锁住DMA( __HAL_LOCK(hdma))。如果开启DMA总中断,完成DMA后会调用下

    2024年04月28日
    浏览(44)
  • 【STM32笔记】STM32的串口数据收发基础(四)(USART DMA模式)

         在STM32中编写串口通信数据收发有三种方式: 轮询模式 (阻塞方式), 中断模式 (非阻塞方式)以及 DMA模式 。      打开STM32CubeMX,前部分配置流程如串口数据收发基础(三)节里一样。配置好USART1的基本参数,开启定时器中断后,接下来就要开启USART1的DMA。

    2024年02月03日
    浏览(38)
  • STM32 cubemx+串口空闲中断+DMA双缓冲

            写这篇文章是为了记录下之前做过的项目中用到的一部分关键技术,之前做过的项目中涉及到 采用最小开销来实时接收遥控器数据、能够准确验证传输过来数据的准确性 ,减小误差率,要求能稳定适用于不同的环境。 目录 1、为什么要用到串口空闲中断? 2、为

    2024年02月09日
    浏览(58)
  • stm32和python实现DMA+串口数据收发

    1-0 串口配置 1-1 DMA发送模式配置 1-2 通过DMA传输数据到USART1的发送寄存器 1-3 串口数据发送 将usart1_dma_tx_data()函数放在main函数中或者中断处理函数中即可,如下所示: 2-1 DMA接收模式配置 2-2 串口结束中断 2-3 对串口接收的数据进行处理 3 完整程序

    2024年02月14日
    浏览(40)
  • 【STM32】HAL库 STM32CubeMX——DMA (串口DMA发送接收)

    软件: STM32CubeMX KEIL5 mcuisp 串口通信助手 硬件: STM32F103C8Tx 杜邦线,面包板,USB转TTL DMA,全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 我们知道系统的运

    2024年02月12日
    浏览(63)
  • stm32 uart dma方式接收不定长度字符

    一般处理: stm32 uart使用dma接收时,会有自己的数据流中断,数据流中断会调用HAL_UART_RxCpltCallback。但是数据流中断只会在HAL_UART_Receive_DMA函数指定的buffer满时才会触发。 接收不定长度字符,需要和uart的UART_IT_IDLE结合。 两种结合方式 第一种:(习惯标准库的程序员) 步骤

    2024年02月10日
    浏览(33)
  • HAL库STM32的串口收发教程

            首先配置STM32CubeMX 第一步在系统SYS里的Debug(调试)选项选择Serial Wire(这里使用ST-LINK-V2仿真下载器所以选择该项)。  第二打开使用外部晶振  在芯片引脚上点击PC13选择GPIO_Output(即设置GPIO为输出模式) 点击GPIO,点击PC13 在其下方配置引脚: GPIO out  level 设置成

    2024年02月14日
    浏览(34)
  • STM32学习笔记(五)串口空闲中断+DMA实现不定长收发(stm32c8t6)

    记录一下学习过程 DMA DMA,全称为: Direct Memory Access,即直接存储器访问, DMA 传输将数据从一个 地址空间复制到另外一个地址空间。 这一过程无需cpu的参与,从而提高cpu使用的效率 DMA相关的参数:1 数据的源地址、2 数据传输的目标地址 、3 传输宽度,4 传输多少字节,5 传

    2024年02月14日
    浏览(43)
  • STM32 HAL DMA中断配置

    使用HAL库方式DMA中断时,在网上找了好多资料都没有怎么介绍。所以就自己研究了一下,并做个记录。我的芯片型号是STM32G030。下面我以I2C传数据为例介绍下HAL库是如何使用DMA中断的。 我使用的是I2C2,简单配置下参数,加上DMA通道。 DMA貌似默认开启了中断,蓝色的勾勾是我

    2024年04月23日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包