基于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时代,别再折腾孩子了
今天这篇完全是从两件事儿有感而发。昨天在文印店,在复印机上看到装订好的几页纸,我瞥了一眼,是历史知识点:隋朝大运河分为四段,分别是___ ___ ___ ___,连接了五大河___ ___ ___ ___ ______ 年ÿ…...
 
万字干货 | 荔枝魔方基于云原生的架构设计与实践
近年来,荔枝集团在国内和海外的业务迅速发展,业务数据规模也是成几何式地增长,海量数据的计算分析场景、业务智能算法应用需求随之而生,为了快速地满足业务发展的需要,我们面临着诸多的技术挑战。技术挑战工程问题资源…...
 
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
 
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
 
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
 
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
 
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
 
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
