串口DMA接收不定长数据

STM32F767—>串口通信接收不定长数据的处理方法_stm32串口超时中断-CSDN博客

STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号_stm32 hal usart2 dma-CSDN博客

#define USART1_RxBuffSize 100
extern DMA_HandleTypeDef hdma_usart1_rx;	//此处声明的变量在其他地方定义
uint8_t USART1_RxBuffer[USART1_RxBuffSize];		//串口接收缓冲区
uint8_t USART1_RxLen = 0;	//接收到的数据长度
uint8_t data[USART1_RxBuffSize];
volatile uint8_t rxComplete = 0;  // 接收完成标志// 重定向printf start
//_write函数在syscalls.c中, 使用__weak定义以可以直接在其他文件中定义_write函数
int _write(int file, char *ptr, int len)
{if(HAL_UART_Transmit(&huart1,(uint8_t *)ptr,len,0xffff) != HAL_OK){Error_Handler();return -1;}return len;
}
// 重定向printf end
  • 串口控制数据收发!DMA仅仅用于传输数据,减轻CPU负担。

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
    
    • 将 DMA(Direct Memory Access,直接内存访问)与 UART(通用异步收发传输器)进行绑定的,在usart.cHAL_UART_MspInit硬件初始化中。
    • USART1 的接收操作能够通过 DMA 直接将数据传输到内存中,减少了 CPU 的参与,提高了数据处理的效率。

方法一:串口空闲中断+DMA

/* 开启串口DMA空闲中断接收,内部会使能串口空闲中断,并设置串口接收类型为空闲中断* 空闲的定义是总线上在一个字节的时间内没有再接收到数据,即空闲帧 */HAL_UARTEx_ReceiveToIdle_DMA(&huart1, USART1_RxBuffer, USART1_RxBuffSize);
/* 串口空闲中断回调函数 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if(huart->Instance == USART1){/* 获取DMA中已经传输的数据个数* __HAL_DMA_GET_COUNTER访问DMA的NDTR寄存器(只读,用于指示要传输的剩余数据项数,每次DMA传输后,此寄存器将递减) */USART1_RxLen = USART1_RxBuffSize - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);/* 内存复制* 数据帧:帧头:0x65(A),帧长:4个字节 */if (USART1_RxBuffer[0] == 0x41 && USART1_RxLen == 4)	//接受完一帧数据{memcpy(data, USART1_RxBuffer, USART1_RxLen);}HAL_UART_Transmit_DMA(huart, USART1_RxBuffer, USART1_RxLen);// 再次开启串口DMA空闲中断,HAL_UARTEx_ReceiveToIdle_DMA → UART_Start_Receive_DMAHAL_UARTEx_ReceiveToIdle_DMA(huart, USART1_RxBuffer, USART1_RxBuffSize);}
}

方法二:串口接收超时中断+DMA

/* 接收超时中断* 波特率:串口通信的速率,即串口通信时每秒钟可以传输多少个二进制位* 时钟分频后,传输1bit所需的时钟周期数为1个时钟周期* 波特率 = 系统时钟频率 / (过采样倍数(8或16) * 时钟分频值)* 数据帧的格式:起始位 + 数据位 + 停止位* USART_RTOR的RTO[23:0]:此位域用于提供接收器的超时值(以波特时钟数为单位)* 	在标准模式下,如果在接收到最后一个字符后,在RTO值对应的时间内未检测到新的起始位,则RTOF标志置1* 	in terms of number of bits* 	写入超时多少个位数 */__HAL_UART_ENABLE_IT(&huart1, UART_IT_RTO);	//使能接收超时中断HAL_UART_ReceiverTimeout_Config(&huart1, 28800);	//设置接收超时时间,比如3*9600=28800,超时3s(波特率9600bit/s)HAL_UART_EnableReceiverTimeout(&huart1);	//使能接收超时功能HAL_UART_Receive_DMA(&huart1, USART1_RxBuffer, USART1_RxBuffSize);	//此函数检查功能CR2_RTOEN从而开启中断CR1_RTOIEwhile (1){ProcessReceivedData();}
/* 串口接收超时中断回调函数 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){USART1_RxLen = USART1_RxBuffSize - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); // 计算接收的数据长度rxComplete = 1; //设置接收完成标志memcpy(data, USART1_RxBuffer, USART1_RxLen); //复制接收缓冲区到数据memset(USART1_RxBuffer, 0, USART1_RxBuffSize); //清空接收缓冲区,避免残留数据干扰下一次接收HAL_UART_Receive_DMA(huart, USART1_RxBuffer, USART1_RxBuffSize); //重新开启DMA+串口接收}
}
// 在主循环或独立任务中进行协议处理
// 在中断处理程序中,应该尽量减少复杂的处理,避免阻塞系统
// 一般来说,回调函数只用于标记接收数据的完成状态,而实际的数据解析和协议处理可以放在主循环或独立的任务中来执行
//(回调函数里不要调用print打印信息!)
void ProcessReceivedData(void)
{if (rxComplete){rxComplete = 0; // 清除接收完成标志// 协议解析printf("ReceivedValidData: \r\n"); //printf必须带\r\n,否则不显示HAL_UART_Transmit_DMA(&huart1, data, USART1_RxLen); // 发送响应数据}
}
  • USART1_IRQHandlerHAL_UART_IRQHandler

    在代码中,UART 的接收超时(RTO)中断处理流程如下:

    1. 检测 UART 超时中断标志

      if (((isrflags & USART_ISR_RTOF) != 0U) && ((cr1its & USART_CR1_RTOIE) != 0U))
      

      这里 USART_ISR_RTOF 表示接收超时标志位,USART_CR1_RTOIE 表示接收超时中断使能位。如果 USART_ISR_RTOF 被置位且 USART_CR1_RTOIE 已启用,则会进入接收超时中断的处理流程。

    2. 清除 UART 超时标志

      __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF);
      

      该行代码清除 UART 接收超时标志,以防止重复触发中断。

    3. 设置错误代码

      huart->ErrorCode |= HAL_UART_ERROR_RTO;
      

      HAL_UART_ERROR_RTO 添加到 huart->ErrorCode 中,记录接收超时错误。

    4. 进入错误处理
      代码随后检查 huart->ErrorCode 是否包含任何错误。如果 ErrorCode 不为 HAL_UART_ERROR_NONE,代码会根据错误类型采取相应的处理措施:

      • 如果错误被视为“阻塞性错误”,例如接收超时(RTO)、溢出错误(ORE)或 DMA 模式下的错误,则会中止接收传输,调用 UART_EndRxTransferHAL_DMA_Abort_IT 函数中止 DMA。
      • 如果错误是非阻塞性错误,会直接调用用户定义的 ErrorCallback
    5. 进入用户回调函数
      当代码检测到错误并将错误处理完成后,进入错误回调:

      #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)huart->ErrorCallback(huart);
      #elseHAL_UART_ErrorCallback(huart);
      #endif
      

      这里调用了 HAL_UART_ErrorCallback 或用户注册的 ErrorCallback

  • HAL_UART_ErrorCallback

    __weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
    

    重写错误回调(当前为接收超时RTO)函数。

调试debug

  • 串口助手+STM32CubeIDE
  1. 点击调试debug,烧录程序并进入调试模式;

  2. 点击继续,运行程序;

  3. 串口助手选择串口,配置波特率等,以接收超时中断为例,发送字符AC,则大概3秒之后,串口助手窗口会返回AC;

  4. 若要实时查看变量的值,则在现场表达式进行调试;

  5. 若用表达式查看变量的值,需要点击暂挂,暂停程序运行才能查看:

    请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git简介和本地仓库创建,并提交修改。git config init status add commit

一、Git简介和本地仓库组成 1.1 git简介 视频教程在这 git简介,版本控制系统,工作区,暂存区,本地仓库_哔哩哔哩_bilibili 如下图,比如我们写毕业论文,要经常修改和完善,得靠自己保存&#x…

鸿蒙学习生态应用开发能力全景图-赋能套件(1)

文章目录 赋能套件鸿蒙生态应用开发能力全景图 赋能套件 鸿蒙生态白皮书: 全面阐释了鸿蒙生态下应用开发核心理念、关键能力以及创新体验,旨在帮助开发者快速、准确、全面的了解鸿蒙开发套件给开发者提供的能力全景和未来的愿景。 视频课程: 基于真实的开发场景,提供向导式…

vue+svg圆形进度条组件

vuesvg圆形进度条组件 一、实现思路二、ProgressCircle.vue三、父组件使用四、实现效果 一、实现思路 使用svg的circle元素画两个圆形&#xff0c;一个圆形控制进度&#xff0c;一个绘制底色 二、ProgressCircle.vue 代码示例&#xff1a; <template><!-- 圆形进度…

软件测试 —— 自动化基础

目录 前言 一、Web 自动化测试 1.什么是 Web 自动化测试 2.驱动 3.安装驱动管理 二、Selenium 1.简单 web 自动化测试示例 2.工作原理 三、元素定位 1.cssSelector 2.XPath 四、操作测试对象 1.点击/提交对象 2.模拟按键输入 3.清除文本内容 4.获取文本信息 5.…

基于SpringBoot的旅游网站(程序+数据库+报告)

基于SpringBoot的旅游网站&#xff0c;系统包含两种角色&#xff1a;管理员、用户,系统分为前台和后台两大模块&#xff0c;主要功能如下。 【前台】&#xff1a; - 首页&#xff1a;展示旅游网站的核心内容&#xff0c;包括推荐的旅游线路、最新的旅游资讯等。 - 旅游线路&am…

RabbitMQ教程:路由(Routing)(四)

文章目录 RabbitMQ教程&#xff1a;路由&#xff08;Routing&#xff09;&#xff08;四&#xff09;一、引言二、基本概念2.1 路由与绑定2.2 Direct交换机2.3 多绑定2.4 发送日志2.5 订阅 三、整合代码3.1 EmitLogDirectApp.cs3.2 ReceiveLogsDirectApp.cs3.3 推送所有和接收e…

AntFlow:一款高效灵活的开源工作流引擎

AntFlow 是一款功能强大、设计优雅的开源工作流引擎&#xff0c;其灵感来源于钉钉的工作流设计理念&#xff0c;旨在为企业和开发者提供灵活、高效的工作流解决方案。AntFlow 支持复杂的业务流程管理&#xff0c;具有高度可定制性&#xff0c;且拥有现代化的前端设计&#xff0…

游戏引擎学习第13天

视频参考:https://www.bilibili.com/video/BV1QQUaYMEEz/ 改代码的地方尽量一张图说清楚吧,懒得浪费时间 game.h #pragma once #include <cmath> #include <cstdint> #include <malloc.h>#define internal static // 用于定义内翻译单元内部函数 #…

中仕公考怎么样?事业编面试不去有影响吗?

事业编考试笔试已经通过&#xff0c;但是面试不去参加会有影响吗&#xff1f; 1. 自动放弃面试资格&#xff1a;未能按时出席事业单位的面试将被视为主动放弃该岗位的竞争机会。 2. 个人信誉问题&#xff1a;面试作为招聘流程的关键步骤&#xff0c;无故缺席可能被解释为诚信…

ElasticSearch学习笔记二:使用Java客户端

一、前言 在上一篇文章中&#xff0c;我们对ES有了最基本的认识&#xff0c;本着实用为主的原则&#xff0c;我们先不学很深的东西&#xff0c;今天打算先学习一下ES的Java客户端如何使用。 二、创建项目 1、普通Maven项目 1、创建一个Maven项目 2、Pom文件 <dependenc…

使用 Grafana api 查询 Datasource 数据

一、使用grafana 的api 接口 官方API 二、生成Api key 点击 Administration -》Users and accss -》Service accounts 进入页面 点击Add service account 创建 service account 点击Add service account token 点击 Generate token , 就可以生成 api key 了 三、进入grafana…

机器学习-36-对ML的思考之机器学习研究的初衷及科学研究的期望

文章目录 1 机器学习最初的样子1.1 知识工程诞生(专家系统)1.2 知识工程高潮期1.3 专家系统的瓶颈(知识获取)1.4 机器学习研究的初衷2 科学研究对机器学习的期望2.1 面向科学研究的机器学习轮廓2.2 机器学习及其应用研讨会2.3 智能信息处理系列研讨会2.4 机器学习对科学研究的重…

深入List集合:ArrayList与LinkedList的底层逻辑与区别

目录 一、前言 二、基本概念 三、相同之处 四、不同之处 五、ArrayList 底层 六、LinkedList 底层 七、ArrayList 应用场景 八、LinkedList 应用场景 九、ArrayList和LinkedList高级话题 十、总结 一、前言 在Java集合的广阔舞台上&#xff0c;ArrayList与LinkedLis…

python实现十进制转换二进制,tkinter界面

目录 需求 效果 代码实现 代码解释 需求 python实现十进制转换二进制 效果 代码实现 import tkinter as tk from tkinter import messageboxdef convert_to_binary():try:# 获取输入框中的十进制数decimal_number int(entry.get())# 转换为二进制binary_number bin(de…

关于强化学习的一份介绍

在这篇文章中&#xff0c;我将介绍与强化学习有关的一些东西&#xff0c;具体包括相关概念、k-摇臂机、强化学习的种类等。 一、基本概念 所谓强化学习就是去学习&#xff1a;做什么才能使得数值化的收益信号最大化。学习者不会被告知应该采取什么动作&#xff0c;而是必须通…

js导入导出

前言: 后面将学习: Vue3ElementPlus 前置知识:前端三件套 HTML,CSS,JS 使用Vscode 本篇学习 这里先补充一个JavaScript的模块化的知识点 - 导入导出 JS提供的导入导出机制,可以实现按需导入. 我们之前是这样导入的 showMessage.js //简单的展示信息 function simpleMessage…

Web导出Excel表格

背景&#xff1a; 1. 后端主导实现 流程&#xff1a;前端调用到导出excel接口 -> 后端返回excel文件流 -> 浏览器会识别并自动下载 场景&#xff1a;大部分场景都有后端来做 2. 前端主导实现 流程&#xff1a;前端获取要导出的数据 -> 常规数据用插件处理成一个e…

【Linux】Ubuntu中muduo库的编译环境安装

Muduo is a multithreaded C network library based on the reactor pattern. muduo库的介绍就是&#xff1a;一个基于reactor反应堆模型的多线程C网络库。 muduo网络库是C语言开发的一个非常优秀的网络库&#xff0c;作者陈硕&#xff0c;muduo网络库在多线程环境下性能非常高…

IDEA leetcode插件代码模板配置,登录闪退解决

前言 最近换电脑&#xff0c;配置idea时和原来的模板格式不一样有点难受&#xff0c;记录一下自己用的模板&#xff0c;后期换电脑使用&#xff0c;大家也可以使用&#xff0c;有更好的地方可以分享给我~ IDEA leetcode插件代码模板配置,登录闪退解决 前言1 下载IDEA leetcode…

网络安全SQL初步注入2

六.报错注入 mysql函数 updatexml(1,xpath语法,0) xpath语法常用concat拼接 例如: concat(07e,(查询语句),07e) select table_name from information_schema.tables limit 0,1 七.宽字节注入(如果后台数据库的编码为GBK) url编码:为了防止提交的数据和url中的一些有特殊意…