【STM32笔记】STM32的串口数据收发基础(四)(USART DMA模式)

这篇具有很好参考价值的文章主要介绍了【STM32笔记】STM32的串口数据收发基础(四)(USART DMA模式)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


  在STM32中编写串口通信数据收发有三种方式:轮询模式(阻塞方式),中断模式(非阻塞方式)以及DMA模式

一. 串口通信(DMA模式)


  打开STM32CubeMX,前部分配置流程如串口数据收发基础(三)节里一样。配置好USART1的基本参数,开启定时器中断后,接下来就要开启USART1的DMA。
#20: identifier #20: identifier
设置好之后,设置存储路径,选择所用IDE,然后点击GENERATE CODE创建工程,open project打开工程进行全局编译。

二. HAL库中串口收发的重要函数(DMA模式)

  1. DMA模式下发送数据函数:HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

@简介  以DMA模式发送一定数量的数据。
@参数  huart,指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数  pData,待发送数据缓冲区的指针。
@参数  Size,待发送数据的字节数。
@返回值  函数执行状态。

  2. DMA模式下接收数据函数: HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

@简介  在DMA模式下接收一定数量的数据
@参数  huart,指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数  pData,待接收接收数据缓冲区的指针。
@参数  Size,待接收数据的字节数。
@注意  当UART奇偶校验使能(PCE = 1)时,接收的数据包含奇偶校验位。
@返回值  函数执行状态。

  3. DMA模式下接收不定长数据函数: HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

@简介  在DMA模式下接收一定数量的数据,直到接收到预期数量的数据或发生IDLE事件。
@注意  接收数据由这个函数调用发起。DMA服务实现了接收数据的进一步进展,在用户接收缓冲区中自动传输接收到的数据元素,并在接收传输过半/完成时调用回      
      调函数。UART IDLE事件也用于将接收阶段视为结束。在所有情况下,回调执行将指示接收到的数据元素的数量。
@参数  huart 指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数  pData 待接收接收数据缓冲区的指针。
@参数  Size  待接收数据的字节数。
@返回值  函数执行状态。

  4. DMA模式数据传输完成回调函数:HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size);

__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  UNUSED(huart);
  UNUSED(Size);
}

@简介  接收事件回调(使用高级接收服务后调用的Rx事件通知)。
@参数  huart UART handle
@参数  Size,应用程序接收缓冲区中可用数据的数量(表示接收缓冲区中数据可用的位置)
@返回值  空

  5.禁用指定的DMA通道中断函数:__HAL_DMA_DISABLE_IT(HANDLE, INTERRUPT) (CLEAR_BIT((HANDLE)->Instance->CCR , (INTERRUPT)));

#define __HAL_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__)  (CLEAR_BIT((__HANDLE__)->Instance->CCR , (__INTERRUPT__)))

@简介  禁用指定的DMA通道中断。
@参数  __HANDLE__: DMA处理
@参数  __INTERRUPT__: 指明要启用或者禁用的DMA中断源
该参数可以是下列值的任意组合:
    @arg DMA_IT_TC:  传输完成中断屏蔽
    @arg DMA_IT_HT:  过半传输完成中断屏蔽
    @arg DMA_IT_TE:  传输错误中断屏蔽
@返回值  空

以上提及的函数可在stm32f1xx_hal_uart.cstm32f1xx_hal_dma.h中,在这些文件中找到
#20: identifier
#20: identifier

#20: identifier

三. 实现串口定长收发通信(DMA模式)

在main.c文件中的Private variables下的USER CODE BEGIN PV注释对中写入以下代码

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
unsigned char String_1[] = "hello world!!!\r\n";
unsigned char rx[16];
/* USER CODE END PV */

在main.c文件中的Private function prototypes下的USER CODE BEGIN PFP注释对中写入以下代码

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// dma模式
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
	if(huart == &huart1){ //  将上位机发来的数据完整的返回回去
		HAL_UART_Transmit_DMA(&huart1,rx,sizeof(rx));
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_4);
		HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
	}
}
/* USER CODE END PFP */

在main.c文件中的main函数下USER CODE BEGIN 2 注释对写入以下代码

/* USER CODE BEGIN 2 */
  HAL_UART_Transmit_IT(&huart1,String_1,sizeof(String_1));
  HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
/* USER CODE END 2 */

实现的效果是在当开发板通过USB转TTL模块与电脑上的串口调试助手相连后,上位机向开发板发送的数据。开发板接收到上位机发来的数据后,翻转PB4引脚上的LED灯亮灭,随后将接收到的数据原封不动的再返回给上位机。
#20: identifier

四. 实现串口不定长收发数据通信(DMA模式)

在main.c文件中的Private function prototypes下的USER CODE BEGIN PFP注释对中写入以下代码

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// dma模式
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
	if(huart == &huart1){ //  将上位机发来的数据完整的返回回去
		HAL_UART_Transmit_DMA(&huart1,rx,Size);
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
	}
}
/* USER CODE END PFP */

在main.c文件中的main函数下USER CODE BEGIN 2 注释对写入以下代码

/* USER CODE BEGIN 2 */
  HAL_UART_Transmit_IT(&huart1,String_1,sizeof(String_1));
  HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
/* USER CODE END 2 */

实现的效果是在当开发板通过USB转TTL模块与电脑上的串口调试助手相连后,上位机向开发板发送的数据。开发板接收到上位机发来的数据后,随后将接收到的数据原封不动的再返回给上位机。
如下图可以发现依次发送不定长的数据给开发板后,开发板都完整的返回了。

#20: identifier
但是当我们一次发送过多的数据后,返回的数据竟然不完整了。
#20: identifier
这是因为在发送数据的时候,当我们接收的数据量达到设置的最大值的一半的时候
也就是这个#20: identifier
,就会触发HAL_UARTEx_RxEventCallback回调函数。
为了解决这个问题,我们可以使用关闭“DMA传输过半中断”的函数,也就是__HAL_DMA_DISABLE_IT()函数。将其写入到HAL_UARTEx_RxEventCallback回调函数中

#20: identifier
注意:如果编译出错为 **error: #20: identifier “hdma_usart1_rx” is undefined **时,说明标识符“hdma_usart1_rx”未定义。可以证明解决。
在usart.h中的USER CODE BEGIN Private defines注释对中添加extern DMA_HandleTypeDef hdma_usart1_rx;
#20: identifier
编译,运行,串口调试助手,启动!!!
这个时候可以发现数据终于实现了正常的不定长收发了(只要不要写过我们的先前设定的rx数组长度就好了)

#20: identifier 文章来源地址https://www.toymoban.com/news/detail-769249.html

到了这里,关于【STM32笔记】STM32的串口数据收发基础(四)(USART DMA模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • HAL库STM32CUBEMX学习记录(一)——USART(串口中断收发数据)

    一、首先使用STM32CUBEMX新建一个工程 二、打开工程文件 1.在usart.c中添加以下代码  2.然后在最后面加入中断回调函数 3.在usart.h文件中加入  4.新建一个cmd.c文件,创建命令check函数 5.在mian函数中的while(1)循环中调用USART1_Check(USART_RX_BUF)函数 6.最后串口初始化函数后打开串口中

    2024年02月16日
    浏览(35)
  • 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日
    浏览(33)
  • STM32学习笔记(五)串口空闲中断+DMA实现不定长收发(stm32c8t6)

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

    2024年02月14日
    浏览(39)
  • STM32+UART串口+DMA收发

    目录 1、cubemax端配置 1.1 初始化配置 1.2 GPIO配置  1.3 UART配置 1.3.1 串口基础配置 1.3.2 DMA配置 2、keil端代码设计 2.1 初始化配置 2.2 DMA接收初始化配置 2.3 DMA发送配置  2.4 接收回调函数设置 2.5 回调函数内容代码编写 2.5.1 接收回调函数 2.5.2 发送回调函数 2.6 回调函数内容代码优化

    2024年02月07日
    浏览(35)
  • stm32串口+DMA环形缓冲收发保姆级

    首先在此感谢开源项目,以及大佬们的无私奉献,让每一个逐梦人能够免费学习,再次感谢! 发布只为记录,记性不够,笔记来凑。记得点赞哦 具体实现原理讲起来确实挺复杂,不过用起来还是很NICE的!可以直接移植! 1.1、选择单片机型号 2、配置时钟和串口 或者直接在

    2024年02月10日
    浏览(31)
  • 【STM32】STM32学习笔记-USART串口数据包(28)

    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式, 电子工程师在调试设备时也经常使用该通讯方式输出调试信息。 在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和

    2024年01月18日
    浏览(35)
  • STM32系列——串口收发数据基础

    串行接口相关知识 两种通信方式:并行通信与串行通信,并行通信传输速度快但是占用的引脚资源多,串行通信传输速度慢但是占用的引脚资源少。 三种模式:单工、半双工、全双工 异步串行通信:通信双方在没有同步时钟的前提下,将一个字符(包括特定的附加位)按位进

    2024年02月11日
    浏览(27)
  • STM32:串口轮询模式、中断模式、DMA模式和接收不定长数据

           在STM32每个串口的内部都有两个寄存器:发送数据寄存器(TDR)/发送移位寄存器,当我们调用HAL_UART_Transmit 把数据发送出去时,CPU会将数据依次将数据发送到数据寄存器中,移位寄存器中的数据会根据我们设置的比特率传化成高低电平从TX引脚输出。待发送移位寄存器中发

    2024年02月07日
    浏览(42)
  • 【STM32】STM32学习笔记-USART串口协议(25)

    按数据传送的方式,通讯可分为串行通讯与并行通讯,串行通讯是指设备之间通过少量数据信号线(一般是8根以下), 地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式。而并行通讯一般是指使用8、16、32及64根或更多的数据线进行传输的通讯方式, 它们的通

    2024年01月19日
    浏览(40)
  • stm32学习笔记-9 USART串口

    注:笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注:工程及代码文件放在了本人的Github仓库。 从本节开始,将逐一学习STM32的通信接口。首先介绍以下stm32都集成了什么通信外设。 为了控制或读取外挂模块,stm32需要与外挂模块进行通信,来扩

    2024年02月14日
    浏览(37)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包