基于STM32L431+Liteos的串口空闲中断加DMA循环接收

news2024/11/18 21:48:02

①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通道中断。
在这里插入图片描述
模拟串口收到一帧数据,但是任务没有处理数据,又来一帧时一起处理。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

appium桌面版本以及一些自动化测试方方封装

标签&#xff08;空格分隔&#xff09;&#xff1a; appium_desktop 一 appium_desktop_v1.2.6 1.appium_desktop在github上最新下载地址&#xff1a;appium桌面版本地址 2.一路傻瓜式安装就好了&#xff1a; 3.然后点击搜索按钮&#xff08;右上角&#xff09; 三 inspector …

基于国产龙芯 CPU 的气井工业网关研究与设计(二)

3.1 系统硬件的总体设计 从硬件架构上&#xff0c;该 RTU 主要包括三大部分的设计&#xff1a; &#xff08;1&#xff09;外围电路设计&#xff1a;电源电路设计、RTC 电路设计和 EEPROM 电路设计。 &#xff08;2&#xff09;RTU 本体 I/O 端口设计&#xff1a;A/I 模拟量输入…

使用RedisDesktopManager无法连接Redis服务器问题

问题&#xff1a;解决办法问题1&#xff1a;redis的配置文件问题进入redis的目录 [rootredis ~]# cd /opt/apps/redis/ opt apps 是自己创建的文件夹&#xff08;用于安装redis&#xff09; 使用vim进入配置文件的修改 [rootredis redis]# vim redis.conf使用vim编辑器修改bi…

ERROR 1114 (HY000): The table ‘tt2‘ is full

insert 操作时提示is full 问题原因 rootlocalhost 11:55:41 [t]>show table status from t like ‘tt2’ \G ; *************************** 1. row *************************** Name: tt2 Engine: MEMORY Version: 10 Row_format: Fixed Rows: 7056 Avg_row_length: 944…

ASEMI代理FGH60N60SMD安森美ON原装原厂IGBT

编辑-Z 安森美FGH60N60SMD原厂IGBT参数&#xff1a; 型号&#xff1a;FGH60N60SMD 集电极到发射极电压&#xff08;VCES&#xff09;&#xff1a;600V 栅极到发射极电压&#xff08;VGES&#xff09;&#xff1a;20V 收集器电流&#xff08;IC&#xff09;&#xff1a;120…

纯css实现坤坤经典动作-“铁山靠”

背景 2023年2月16日&#xff0c;晴&#xff0c;今天没有工作&#xff0c;一直在掘金摸鱼&#xff0c;摸的我好累。 不行&#xff01;我得找点有意义的事情做&#xff01; 此时间&#xff0c;我发的一条沸点竟然有小黑子给我评论&#xff0c;\ 我看到之后气不打一处来&#xff…

1v1游戏互动,接入社交场景(内含接入方法)

游戏的需求洞察 许多互联网产品想要拓宽功能领域&#xff0c;纷纷选择进入小游戏赛道&#xff0c;试图从新颖有趣的方向深度触达用户&#xff0c;提高产品的活跃度和留存。群玩洞察了这一需求&#xff0c;还发现海外用户也对1v1互动游戏感兴趣&#xff0c;于是开始做这类游戏的…

中国人寿业务稳定性保障:“1+1+N” 落地生产全链路压测

引言 保险业务的数字化转型正如火如荼地进行&#xff0c;产品线上化、投保线上化、承保线上化、核保线上化等业务转型&#xff0c;导致系统的应用范围不断扩大&#xff0c;用户的高频访问也正在成为常态。同时&#xff0c;系统复杂性也呈指数上升&#xff0c;这些因素都增加了…

3.InfluxDB WEB使用

结合telegraf做指标数据收集 点击 Load Data -> Telegraf 配置界面 influxDB支持在WEB-UI中生成配置文件 然后利用telegraf通过远程URL请求的方式进行获取 点击CREATE CONFIGURATION 创建telegraf配置文件 选择Bucket InfluxDB提供了很多配置好的监控模板供用户选择 可以…

分享112个HTML旅游交通模板,总有一款适合您

分享112个HTML旅游交通模板&#xff0c;总有一款适合您 112个HTML旅游交通模板下载链接&#xff1a;https://pan.baidu.com/s/15OctJIB4NtyFddyalXX70A?pwd7tpa 提取码&#xff1a;7tpa Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 响应式旅游度假HTML5模板…

学会开发自己的Python AI应用【OpenAI API篇】

最近 OpenAI 宣布 ChatGPT 将很快推出他们的 API。虽然我们不知道这需要多长时间&#xff0c;但这之前我们可以熟悉下OpenAI API&#xff0c;快速开发自己的AI应用&#xff01;通过今天学习 OpenAI API&#xff0c;你将能够访问 OpenAI 的强大模型&#xff0c;例如用于自然语言…

动态生成复选框列表弹性盒子

效果图 1.准备一块盒子区域 id“checkBoxList” 为例 //样式的简单介绍 style{ overflow:scroll; //让超出div 内容在div区域内以滚动条形式呈现 display: flex; //搞一个弹性盒子容器 flex-wrap: wrap;align-content: flex-start; // 文本对齐方式 这里是上下元素的内容对齐…

【论文Word排版】使用多级列表设置论文序号

在Word中对论文进行排版 1.设置章节前面的序号 1.1 需求 通常情况下要求如下 一级标题“第一章 XXX”&#xff0c;然后是“1.1 研究意义”&#xff0c; “1.2 研究现状” 之前的处理方式都是手打&#xff0c;并没有借助word的多级列表实现。这次趁着写毕业论文研究了一下。…

虹科案例 | Redis企业版数据库帮助金融机构满足客户需求

传统银行无法提供无缝的全渠道客户体验、无法实时检测欺诈、无法获得业务洞察力、用户体验感较差、品牌声誉受损和业务损失&#xff1f;虹科提供的Redis企业版具有低延迟、高吞吐和高可用性特征&#xff0c;使用Redis企业版数据库&#xff0c;金融机构可以实现即时的客户体验、…

搭建Hexo博客-第3章-Markdown语言介绍及编辑博客

搭建Hexo博客-第3章-Markdown语言介绍及编辑博客 搭建Hexo博客-第3章-Markdown语言介绍及编辑博客 搭建Hexo博客-第3章-Markdown语言介绍及编辑博客 大家好&#xff0c;如果你按照上一篇文章的内容安装并部署了博客&#xff0c;那么现在在你的主页上应该有一篇 Hello World&…

工业上为什么要使用Io-Link?

工业上为什么要使用Io-Link&#xff1f;IO-Link是一种通讯技术&#xff0c;可以把传统的硬件从单纯的输入输出转变为可配置、可编程的网络设备。它可以大大减少有线连接&#xff0c;改善机器人控制和过程控制系统的可读性和可维护性&#xff0c;实现智能化的装置。使用IO-Link可…

科技云报道:2023,云计算的风向变了

科技云报道原创。 2022&#xff0c;是云计算的“分水岭”之年。 与前两年的火热相比&#xff0c;2022年云计算行业实属不太好过&#xff1a;阿里云一季度营收增速创出历史新低&#xff0c;腾讯云的市场份额也被后来者华为云反超&#xff0c;沦为第三。 在此情形下&#xff0c…

rabbitmq菜鸟教程,搭建rabbitmq

一、前言RabbitMQ是一个开源的遵循 AMQP协议实现的基于 Erlang语言编写&#xff0c;即需要先安装部署Erlang环境再安装RabbitMQ环境。需加注意的是&#xff0c;读者若不想跟着我的版本号下载安装&#xff0c;可根据两者版本号的对应表&#xff08;下面图示只展示了部分&#xf…

Git(GitHub,Gitee 码云,GitLab)详细讲解

目录第一章 Git 概述1.1 何为版本控制1.2 为什么需要版本控制1.3 版本控制工具1.4 Git 简史1.5 Git 工作机制1.6 Git 和代码托管中心第二章 Git 安装第三章 Git 常用命令3.1 设置用户签名3.2 初始化本地库3.3 查看本地库状态3.3.1 首次查看&#xff08;工作区没有任何文件&…

2023年美赛ICM问题E:光污染 这题很好做啊!

2023年美赛ICM问题E:光污染 这题很好做啊&#xff01;![在这里插入图片描述](https://img-blog.csdnimg.cn/e918cc6fc9214b53bf4859063bfe56b0.png#pic_center) 我看到DS数模的分析&#xff0c;看似头头是道&#xff0c;实则GouPi不通&#xff0c;我出一个&#xff0c;用于大家…