STM32串口:DMA空闲中断实现接收不定长数据(基于HAL库)

STM32串口:DMA空闲中断实现接收不定长数据(基于HAL库):


第一步:设置rcc,时钟频率,下载方式

设置system core->RCC如图所示:(即High Speed Clock和Low Speed Clock都选择第二个)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d9fe743edf044420b825958eae1fdb65.png![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/668a5c2f7696417680d144b7be22bb71.png


设置时钟频率,我选择的是stm32f103c8t6,f1系列最大时钟频率都是72M,因此设置为72M,点击Clock Configuration选择HCLK,输入72,然后回车,确定
在这里插入图片描述
下载方式设置如下图:(我使用的方式是stlink)
在这里插入图片描述


第二步:设置串口为DMA中断发送和接受,并开启nvic,如图设置:

在这里插入图片描述
开启nvic中断:
在这里插入图片描述

添加dma发送接受通道
在这里插入图片描述

以上就是cubemx的全部设置,生成代码

第三步:代码编写:

需要写的代码,我全部写在main.c文件,需要复制的请看本文最后

接下来开始写代码逻辑,我打算写一个接受不定长数据的中断函数,然后再中断函数中再把这个数据原封不动的发送出去,以此来验证发送和接收功能是否正常

首先定义一个较大的数组来用于存放接收的数据,由于我们要用中断来接收数据的,因此要定义再main函数之外,即定义为全局变量才行:
在这里插入图片描述


然后在while循环之前加入以下内容:
在这里插入图片描述
这两行代码,第一行的作用是开启串口的dma空闲中断功能,第二行的作用是禁止dma传输过半中断,这里的dma传输过半是相对我们上一步定义的那个接受数组的总长度而言的,我定义的是100,因此只要连续接收到50个字节的数据,就会触发中断,如果连续接收的数据小于50个字节,接受空闲了,那就不会触发过半的中断,而是直接触发空闲中断。这样来看的话,这个dma传输过半中断对于我们的接受逻辑并没有太大用,因此将其禁止了!


接下来编写串口的dma空闲中断函数,它是HAL库弱定义的一个函数,我把它重写再main.c文件中,如下:
在这里插入图片描述


if里面第一行就是将接收到的数据发送出去,第二行,第三行再次重复上一步的操作具体略

整个main.c文件如下:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t r_data[100];

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)//Size参数是本次接受到的数据长度
{
	if(huart==&huart2)
	{
		HAL_UART_Transmit_DMA(&huart2, r_data, Size);
		HAL_UARTEx_ReceiveToIdle_DMA(&huart2, r_data, sizeof(r_data));//重新启动接收
		__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);//禁止DMA传输过半中断
	}
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_UARTEx_ReceiveToIdle_DMA(&huart2, r_data, sizeof(r_data));//设置串口接收DMA空闲中断(用于接受不定长数据)
  __HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);//禁止DMA传输过半中断
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/448496.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【企业动态】国际知名设备商来访东胜物联,考察交流

本周,国际知名设备商的技术及生产团队一行莅临东胜物联杭州总部和湖州生产工厂,进行参观考察,深入交流。该设备商的业务范围广泛,在全球各地拥有许多分公司,其中机器人和工业自动化设备等多项业务处于业界领先水平。 …

设计模式深度解析:工厂方法模式与抽象工厂模式的深度对比

​🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 探索设计模式的魅力:工厂方法模式文章浏览阅读17k次,点赞105次&#xff0…

【棘手问题】Spring JPA一级缓存导致获取不到数据库表中的最新数据,对象地址不发生改变

【棘手问题】Spring JPA一级缓存导致获取不到数据库表中的最新数据,对象地址不发生改变 一、问题背景二、解决步骤2.1 debug2.2 原因分析2.2.1 数据步骤2.2.2 大模型解释2.2.3 解释举例2.2.4 关键函数 2.3 解决方案 三、Spring JPA一级缓存 一、问题背景 项目的数据…

CubeMX使用教程(5)——定时器PWM输出

本篇我们将利用CubeMX产生频率固定、占空比可调的两路PWM信号输出 例如PA6引脚输出100Hz的PWM;PA7引脚输出500Hz的PWM,双路同时输出 我们还是利用上一章定时器中断的工程进行学习,这样比较方便 首先打开CubeMX对PA6、PA7进行GPIO配置 注&a…

Python递归函数你用对了吗?

1.递归函数 递归函数:函数自己调用自己 2.需求 使用函数的方式,计算数字n的阶乘 # 5! """ 5! 1 * 2 * 3 * 4 * 5 4! 1 * 2 * 3 * 4 3! 1 * 2 * 3 2! 1 * 2 1! 1综上可以总结出:n! n * (n - 1) "&qu…

Spring Cloud部署篇2——Docker Compose部署至CentOS云服务器

一、项目介绍 系统模块 com.mingink |--mingink-api // 接口模块 | └──mingink-api-system // 系统接口 |--mingink-common // 通用模块 | └──mingink-common-core // 系统接口 |--mingink-gateway…

Mybatis操作sql报错ibatis.binding.BindingException: Parameter ‘empId‘ not found.

你们好,我是金金金。 场景 在使用Mybatis操作sql语句过程当中,更新操作,报错信息如下:Caused by: org.apache.ibatis.binding.BindingException: Parameter ‘empId’ not found. Available parameters are [arg1, arg0, param1, …

链表中的经典问题——奇偶链表

奇偶链表 给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。 第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。 请注意,偶数组和奇…

R语言绘制桑基图教程

原文链接:R语言绘制桑基图教程 写在前面 在昨天3月10日,我们在知乎、B站等分享了功能富集桑基气泡图的绘制教程。相关链接:NC|高颜值功能富集桑基气泡图,桑基气泡组合图。 确实,目前这个图在文章中出现的频率相对比较…

仿牛客网项目---Elasticsearch分布式搜索引擎

1.什么是ElasticSearch分布式搜索引擎? Elasticsearch是一个开源的分布式搜索引擎,提供实时的、高可用性的搜索和分析解决方案。它支持快速索引和搜索大规模数据,具有分布式架构、RESTful API、基于JSON的查询语言等功能,适用于各…

手机备忘录可以设置密码吗 能锁屏加密的备忘录

在繁忙的生活中,手机备忘录成了我随身携带的“小秘书”。那些关于工作的灵感、生活的琐事,甚至深藏心底的小秘密,都被我一一记录在里面。然而,每次当手机离开我的视线,或者需要借给他人使用时,我总会心生担…

力扣:118. 杨辉三角

力扣:118. 杨辉三角 描述 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输…

根据xlsx文件第一列的网址爬虫(selenium)

seleniumXpath 在与该ipynb文件同文件下新增一个111.xlsx,第一列放一堆需要爬虫的同样式网页 然后使用seleniumXpath爬虫 from selenium import webdriver from selenium.webdriver.common.by import By import openpyxl import timedef crawl_data(driver, url)…

数据结构->双向链表带你体验开火车(哨兵)与拼接火车(应用)厢的乐趣

✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青-CSDN博客 目的:学习双向带头链表的增,删,查,销毁…

Logseq电脑端+安卓端同步gitee或github

文章目录 0.初衷1.电脑端1.1 新建仓库1.2 克隆项目,生成秘钥1.3 添加图谱,选择文件目录,我是原本就有笔记,所以会如下所示。1.4 下载脚本文件1.5赋权限 (windows可跳过)1.6 修改脚本命令1.7 logseq设置同步…

从大模型到Agentscope——Multi-Agent框架应用与开发

目录 大模型发展历程 大模型的缺陷 智能体 Agent的构建 模型计划内存工具 Agent到多Agent Multi-Agent 带来性能提升的同时也带来一些新的问题 流程设计鲁棒可靠多模态多系统提升运行效率 Multi-Agent框架 AgentScope Demo 三行代码实现聊天机器人 预告

Python与FPGA——sobel边缘检测

文章目录 前言一、sobel边缘检测二、Python sobel边缘检测三、FPGA sobel边缘检测总结 前言 边缘存在于目标、背景区域之间,它是图像分割所依赖的较重要的依据,也是图像匹配的重要特征。边缘检测在图像处理和计算机视觉中,尤其在图像的特征提…

C++进阶之路---多态(二)

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、多态的原理 1.虚函数表 // 这里常考一道笔试题:sizeof(Base)是多少? class Base { public:…

Vue首屏优化方案

在Vue项目中,引入到工程中的所有js、css文件,编译时都会被打包进vendor.js,浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多,那么vendor.js文件体积将会相当的大,影响首屏的体验。可以看个例子:…

后端八股笔记------微服务篇

注册中心的主要作用:根据服务进行负载均衡,服务的健康监控。 服务雪崩,因为一个服务D的宕机,导致很多服务崩掉。 达到失败阈值----Closed_to_Open 服务降级------某一个接口 服务熔断------整个服务 限流常见的算法可以是令牌…