基于STM32L431+Liteos的串口空闲中断加DMA循环接收
①MCU为STM32L431,使用串口2。
②Liteos采用接管中断的方式。
STM32CubeMX配置生成串口代码:
串口DMA接收和发送配置区别是接收采用循环模式,发送为正常模式。
将生成的代码移植到liteos工程中,由于使用的接管中断的方式,所以使能中断的时候需要先注册中断。
HAL_NVIC_SetPriority(USART2_IRQn, 1, 0);HAL_NVIC_EnableIRQ(USART2_IRQn);HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 1, 0);HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 2, 0);HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);改为:uvIntSave = LOS_IntLock();LOS_HwiCreate(USART2_IRQn,1,(HWI_MODE_T)0,(HWI_PROC_FUNC)USART2_IRQHandler,(HWI_ARG_T)0);LOS_HwiCreate(DMA1_Channel6_IRQn,1,(HWI_MODE_T)0,(HWI_PROC_FUNC)DMA1_Channel6_IRQHandler,(HWI_ARG_T)0);LOS_HwiCreate(DMA1_Channel7_IRQn,2,(HWI_MODE_T)0,(HWI_PROC_FUNC)DMA1_Channel7_IRQHandler,(HWI_ARG_T)0); LOS_IntRestore(uvIntSave);
创建一个事件标志组,并用其中的一位来表示串口接收到数据。
#define ZigbeeUartIdle (0x01<<0)#define ZigbeeUartRecv (0x01<<1)UINT32 uwRet = LOS_OK;uwRet = LOS_EventInit(&SysEventGroup);if(uwRet != LOS_OK){PRINT_ERR("Event Error Code:0x%X\n",uwRet);return uwRet;}
串口初始化函数中使能串口接收:
__HAL_UART_CLEAR_IDLEFLAG(&huart2); HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t*)Usart2RxBuf, USART2_RX_BUFFER_LEN);
不要使用HAL_UART_Receive_DMA函数,直接使用HAL_UARTEx_ReceiveToIdle_DMA函数,该函数会以DMA方式接收一定数量的数据,直到收到预期数量的数据或者发生IDLE事件时会产生中断,这样的话在中断服务函数中可以直接调用回调函数,去处理DMA接收的数据。
串口的中断服务函数:
void ClearError(UART_HandleTypeDef *huart)
{uint32_t isrflags = READ_REG(huart->Instance->ISR);uint32_t errorflags;/* If no error occurs */errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE));if (errorflags != 0U) {__HAL_UART_CLEAR_FLAG(&huart2, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);}
}void USART2_IRQHandler(void)
{ClearError(&huart2);HAL_UART_IRQHandler(&huart2);
}
在中断服务函数中调用ClearError是为了防止因为上溢错误或者帧错误导致一直进入中断服务函数中,所以在处理中断事件时先把错误清除。
如果在初始化串口的时候注册了DMA通道的中断的话,当使用DMA发送数据时半发送或者发送完成时,都会进入DMA通道中断,同样的在接收数据的时候当收到定义的缓冲区一半或者接收满时也会进入DMA通道中断。
void DMA1_Channel6_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma_usart2_rx);
}void DMA1_Channel7_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma_usart2_tx);
}
使用DMA发送数据完成会调用HAL_UART_TxCpltCallback回调函数,可以在这里表示串口空闲。
/*** @brief Tx Transfer completed callback* @param UartHandle: UART handle. * @note This example shows a simple way to report end of DMA Tx transfer, and * you can add your own implementation. * @retval None*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
{/* Set transmission flag: transfer complete*/LOS_EventWrite(&SysEventGroup,ZigbeeUartIdle);
}
当发生空闲中断的时候会调用HAL_UARTEx_RxEventCallback函数来处理,函数参数Size表示接收到的字节数,如果使用的循环模式,那么传进来的Size会自动循环。比如定义的接收缓冲区共有56个字节,第一次产生空闲中断时接收20字节,Size大小为20,第二次产生空闲中断时接收20字节,Size大小为40,第三次产生空闲中断时接收20字节,Size大小为4。
Usart2RxLen为一个全局变量,用来表示任务在每次处理数据时需要处理的数据长度,比如第一次收到20字节,任务立刻处理,那么会在任务中把Usart2RxLen清零;如果第一次收到20字节,任务没有处理,第二次又收到20字节,Usart2RxLen会累加,那么这个时候任务需要从接收缓存区中读取的数据长度就是40。RecvOnce是一个静态的全局变量,用来记录上次执行HAL_UARTEx_RxEventCallback函数时传入的Size值,以此来区分本次空闲中断产生时,接收的数据有没有从头开始,从而正确的计算出本次接收到数据的长度。
volatile uint16_t Usart2RxLen = 0;
static uint16_t RecvOnce = 0;
/*** @brief Reception Event Callback (Rx event notification called after use of advanced reception service).* @param huart UART handle* @param Size Number of data available in application reception buffer (indicates a position in* reception buffer until which, data are available)* @retval None*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if(huart->Instance == USART2){LOS_EventWrite(&SysEventGroup,ZigbeeUartRecv);//通知任务接收到数据if(Size > RecvOnce){PRINT_INFO("size = %d\r\n",Size-RecvOnce);Usart2RxLen = (Usart2RxLen + Size - RecvOnce) % USART2_RX_BUFFER_LEN; }else{PRINT_INFO("size = %d\r\n",(USART2_RX_BUFFER_LEN - RecvOnce + Size));Usart2RxLen = (Usart2RxLen+(USART2_RX_BUFFER_LEN - RecvOnce + Size)) % USART2_RX_BUFFER_LEN; } RecvOnce = Size;}
}
任务中读取数据:
void Process_Task(void)
{UINT32 uwRet = LOS_OK; UINT16 msglen = 0;UINT8 msg[USART2_RX_BUFFER_LEN];while(1){uwRet = LOS_EventRead(&SysEventGroup,ZigbeeUartRecv,LOS_WAITMODE_AND | LOS_WAITMODE_CLR,0);if(uwRet & ZigbeeUartRecv){msglen = Usart2RxLen;Usart2RxLen = 0;//待处理数据长度清零memset(msg,0x00,USART2_RX_BUFFER_LEN);if((msglen + DealAddr) <= USART2_RX_BUFFER_LEN){memcpy(msg,&Usart2RxBuf[DealAddr],msglen);}else{memcpy(msg,&Usart2RxBuf[DealAddr],(USART2_RX_BUFFER_LEN - DealAddr));memcpy(&msg[USART2_RX_BUFFER_LEN - DealAddr],Usart2RxBuf,(msglen+DealAddr-USART2_RX_BUFFER_LEN));}DealAddr = (DealAddr+msglen) % USART2_RX_BUFFER_LEN;HAL_UART_Transmit_DMA(&huart2,msg,msglen);}LOS_TaskDelay(LOS_MS2Tick(50));//50ms轮询一次}
}
任务处理串口数据的周期是50ms,使用LOS_EventRead读取事件标志的时候超时时间设置为0,作用相当于轮询状态后直接返回,处理数据的时候使用DealAddr变量来记录上次处理之后的位置,通过(msglen + DealAddr)的值和接收缓冲区的长度比较,来确定读取数据的方式,并使用HAL_UART_Transmit_DMA函数来完成数据回环测试。
接收缓冲区的长度是56,可以看到在第三次和第六次接收的时候,一帧数据调用了两次HAL_UARTEx_RxEventCallback函数,这是因为DMA通道产生了半接收(28)和接收完成中断(56),但是对一帧数据的接收没有影响。
如果不想有这种情况,可以不使能串口RX绑定的DMA通道中断。
模拟串口收到一帧数据,但是任务没有处理数据,又来一帧时一起处理。
相关文章:

基于STM32L431+Liteos的串口空闲中断加DMA循环接收
①MCU为STM32L431,使用串口2。 ②Liteos采用接管中断的方式。 STM32CubeMX配置生成串口代码: 串口DMA接收和发送配置区别是接收采用循环模式,发送为正常模式。 将生成的代码移植到liteos工程中,由于使用的接管中断的方式&#…...
BZOJ4403 序列统计
题目描述 给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对106310^631063取模的结果。 输入 输入第一行包含一个整数T,表示数据组数。 第2到第T1行每行包含三个整数N、L和R,N、…...

如何正确使用 钳位二极管
在电路设计中,经常遇到需要IO保护的场景,比如ADC采样,GPIO接收电平信号等。 常见的保护方法有分压,限幅,限流等。本次我们讨论限幅方法中的 钳位二极管。 我们以BAT54S为例,它的符号是这样的, 而在很多手册里,我们可以看到,一般是这样使用的: 因此,我设计了简化…...

【C语言进阶】动态内存管理
👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:C语言航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&a…...

第一批因ChatGPT坐牢的人,已经上路了
大家好,我是 Jack。 ChatGPT 的火爆有目共睹,有人靠着它赚了第一桶金,也有人靠着它即将吃上第一顿牢饭。 任何一件东西的火爆,总会给一些聪明人带来机会。 艾尔登法环火的时候,一堆淘宝卖魂的;羊了个羊火…...

Eclipse下Maven的集成
Eclipse下Maven的集成 2.1指定本地maven环境 参考:Eclipse的Maven创建_叶书文的博客-CSDN博客_eclipse创建maven项目 指定用本地maven指定maven仓库设置和地址2.2创建maven项目 1.新建 2.目录设置 3.坐标设置(随便写就行) 4.目录结构 2.3配置…...

Elasticsearch7学习笔记(尚硅谷)
文章目录一、ElasticSearch概述1、ElasticSearch是什么2、全文搜索引擎3、ElasticSearch 和 Solr3.1 概述3.2 比较总结二、Elasticsearch入门1、Elasticsearch安装1.1 下载使用1.2 数据格式2、索引操作3、文档操作(了解)3.1 创建文档3.2 文档查询3.3 文档…...

前端学习第一阶段-第7章 品优购电商项目
7-1 品优购项目介绍及准备工作 01-品优购项目导读 02-网站制作流程 03-品优购项目规划 04-品优购项目搭建 05-品优购项目-样式的模块化开发 06-品优购项目-favicon图标制作 07-品优购项目-TDK三大标签SEO优化 7-2 首页Header区域实现 08-品优购首页-快捷导航shortcut结构搭建 0…...

cocos2dx 4.0 - cpp - pc版 环境搭建
开发环境vs2022 cocos2dx4.0 python2.7.18 cmake3.25安装教程(环境搭建)安装VS2022-Community, 勾选c进行安装安装cmake3.25, 勾选环境变量进行安装安装python2.7.18, 勾选环境变量进行安装下载cocos2dx4.0并解压配置cocos2dx:运行cmd,进入…...

剑指 Offer 53 - I. 在排序数组中查找数字 I
原题链接 难度:easy\color{Green}{easy}easy 题目描述 统计一个数字在排序数组中出现的次数。 示例 1: 输入: nums [5,7,7,8,8,10], target 8 输出: 2示例 2: 输入: nums [5,7,7,8,8,10], target 6 输出: 0提示: 0<nums.length<1050 <…...
华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】
最近更新的博客 华为OD机试 - 热点网络统计 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 查找单入口空闲区域 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 好朋友 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 找出同班小朋友 | 备考思路,刷题要点…...

PowerShell Install Office 2021 Pro Plus Viso Professional
前言 微软Office在很长一段时间内都是最常用和最受欢迎的软件。从小型创业公司到大公司,它的使用比例相当。它可以很容易地从微软的官方网站下载。但是,微软只提供安装程序,而不提供完整的软件供下载。这些安装文件通常比较小。下载并运行后,安装的文件将从后端服务器安装M…...

KubeSphere实战
文章目录一、KubeSphere平台安装1、Kubernetes上安装KubeSphere1.1 安装docker1.2 安装Kubernetes1.3 前置环境之nfs存储1.4 前置环境之metrics-server1.5 安装KubeSphere2、Linux单节点部署KubeSphere3、Linux多节点部署KubeSphere(推荐)二、KubeSphere实战1、多租户实战2、中…...

Linux 简介
Linux 内核最初只是由芬兰人林纳斯托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的。 Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的操作系统。 …...

java面试题-泛型异常反射
泛型1.什么是泛型?Java是一种强类型语言,数据类型在编译时必须确定。如果我们想要在代码中使用不同类型的数据,那么就需要为每种类型分别写出相应的代码。这样会导致代码冗长、重复,也不便于维护。为了解决这个问题,Ja…...

详细解读ChatGPT:如何调用ChatGPT的API接口到官方例子的说明以及GitHub上的源码应用和csdn集成的ChatGPT
文章目录1. 解读ChatGPT1.1 词语解释1.2 功能解读2. GitHub上ChatGPT的应用源码3. 调用ChatGPT的API4. 官方例子说明5. 集成ChatGPT自ChatGPT出来到如今,始终走在火热的道路上,如今日活用户破亿,他为何有如此大的魅力,深受广大用户…...

九龙证券|最新评级情况出炉,机构扎堆这一板块!聚氨酯龙头获得最多关注
本周算计254家上市公司获组织“买入型”评级。 电子板块评级组织扎堆 证券时报数据宝计算,2月13日至17日,A股市场53家组织算计进行347次评级,254家上市公司获“买入型”评级(包含买入、增持、强烈推荐、推荐)。 从申…...

考研复试机试 | C++ | 尽量不要用python,很多学校不支持
目录1.1打印日期 (清华大学上机题)题目:代码:1.2改一改:上一题反过来问题代码:2.Day of Week (上交&&清华机试题)题目:代码:3.剩下的树(清…...

ChatGPT时代,别再折腾孩子了
今天这篇完全是从两件事儿有感而发。昨天在文印店,在复印机上看到装订好的几页纸,我瞥了一眼,是历史知识点:隋朝大运河分为四段,分别是___ ___ ___ ___,连接了五大河___ ___ ___ ___ ______ 年ÿ…...

万字干货 | 荔枝魔方基于云原生的架构设计与实践
近年来,荔枝集团在国内和海外的业务迅速发展,业务数据规模也是成几何式地增长,海量数据的计算分析场景、业务智能算法应用需求随之而生,为了快速地满足业务发展的需要,我们面临着诸多的技术挑战。技术挑战工程问题资源…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...