首页 > 其他分享 >DMA连续发送多帧但是只有最后一帧数据发出问题解决方法

DMA连续发送多帧但是只有最后一帧数据发出问题解决方法

时间:2024-10-17 20:18:02浏览次数:6  
标签:DMA 一帧 发送 串口 发送数据 字节 指针

问题描述

DMA连续发送多帧但是只有最后一帧数据发出

原因分析

DMA发送未完成时,下次DMA请求启动,导致之前的数据被放弃传输了

解决办法

创建DMA发送缓冲区,当启动DMA请求的时候,检测DMA设备是不是正在忙,如果正在忙,就把数据放入发送缓冲区等待,上次DMA发送完成的时会产生DMA发送完成中断,在发送完成中断处理函数中再次发起DMA传输任务,直到发送缓冲区清空。

1单片机串口发送数据的一般处理方法

单片机串口有一个发送数据缓冲区,当上一个字节被发送完成时下一个字节进入发送缓冲区。但如果在上一个字节被发送完毕前,下一个字节进入发送缓冲区,则上一个字节会被覆盖掉。因此CPU必须在上一个字节发送完毕之后发送下一个字节。针对这一问题,开发者们一般在串口发送数据时,不断循环查询串口发送中断标志位,当一个字节的数据正在发送过程中时等待,直到当前字节数据发送完毕再发送下一个字节。如此循环,直到整个通信协议发送完成。
以波特率9600为例,一帧数据包括:1个起始位:8个数据位;1个停止位;总共10bits;现有12bytes数据要发送因此有1210bits发送;1bit的发送时间=1000/9600(bit/ms),发送12bytes数据的时间=1210*(1000/9600)ms=12.5ms;STM32系列芯片(Cortex-M3)有三级流水线,指令周期不定,ARM给出的Cortex-M3核单片机的平均执行速度是1.25MIPS/Mhz。MIPS(MillionInstructionsPerSecond,每秒百万指令),Mhz(兆赫兹,是指单片机CPU的主频)。采用72Mhz系统时钟,则为1.2572=90MIPS,可见仅仅是等待串口发送12bytes数据,将浪费9012.5/1000=1.125,即浪费百万条指令执行时间。
这种串口数据发送方式,解决了单片机处理串口多字节通信的问题,是初学者常用的处理方式。但是相对于CPU,串口是速度非常慢的外设,尤其是串口波特率较低的时候,需要CPU浪费大量的时间在查询串口发送中断标志位上。单片机串口自带的数据缓冲区只能按字节处理串口数据,而单片机串口通信协议一般由多个字节组成,且通信频率较高,要求对数据处理速度快,这种处理方式在系统能够系统实时性要求高时无法满足要求。

2采用DMA技术串口发送数据的一般方法

使用DMA技术后,开发者们可以将要发送的数组的首地址、数组长度赋值给相应的DMA通道,并且使能一次DMA传输。DMA发送数据的过程中,CPU不再参与,从而大量节省了CPU占用时间。
但是在实际应用中可能会出现虽然用了DMA,但仍不能把CPU空闲出来做其它事情,因为后面的语句影响串口正在发送的数据,所以必须等到DMA发送完成以后,再执行后面的语句。例如需要连续发送多条数据的情况,此时还要使用DMA技术就需要判断上次的数据传输有没有发送完成,也就是要CPU查询DMA中断标志位并等待,否则在上次传输的数据还没有发送完成时,开启下一次DMA传输会导致上次的传输数据丢失。这样做其实没有发挥出DMA最大的优势,把CPU空闲出来做其他事情。所以这样使用DMA不会在发送数据的效率方面有所提高,因为在串口发送数据的时候,CPU不能做其他事情。

		if(t==KEY0_PRES)//KEY0按下
		{
			LCD_ShowString(30,150,200,16,16,"Start Transimit....");
			LCD_ShowString(30,170,200,16,16,"   %");//显示百分号
			printf("\r\nDMA DATA:\r\n"); 	    
		  USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送      
			MYDMA_Enable(DMA1_Channel4);//开始一次DMA传输!	  
		    //等待DMA传输完成,此时我们来做另外一些事,点灯
		    //实际应用中,传输数据期间,可以执行另外的任务
		    while(1)
		    {
				if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)	//判断通道4传输完成
				{
					DMA_ClearFlag(DMA1_FLAG_TC4);//清除通道4传输完成标志
					break; 
		    }
				pro=DMA_GetCurrDataCounter(DMA1_Channel4);//得到当前还剩余多少个数据
				pro=1-pro/SEND_BUF_SIZE;//得到百分比	  
				pro*=100;      //扩大100倍
				LCD_ShowNum(30,170,pro,3,16);	  
		    }			    
			LCD_ShowNum(30,170,100,3,16);//显示100%	  
			LCD_ShowString(30,150,200,16,16,"Transimit Finished!");//提示传送完成
		}

3采用DMA技术串口发送数据改进后的方法

为解决上述问题,本文在采用DMA技术缓存数组的方法基础上进行了改进,规定了循环存储的方式缓存串口发送数据。

3.1方法解析

适用于循环存储发送的串口发送方法,包括以下四个要素:循环数组、DMA状态标志、读写指针、容量计算。定义一个固定长度的数组用于循环存储要发送的数据,数组大小可自定义满足使用要求即可。
初始状态时,读写指针都指向循环数组首地址。需要发送数据时向数组内写入数据同时移动写指针。此时读指针和写指针不相等,开启一次DMA传输,并且将DMA状态标志置位,表示DMA传输正在进行。在DMA传输正在进行的过程中,如果有发送数据的需求,只需要将需要发送的数据循环写入环形存储区域即可。
但同时需要判断环形存储区域的剩余容量,如果剩余容量不足放入本次要发送的数据,则不能放入本次要发送的数据,否则会造成数据错误。
一次传输完成后DMA产生传输完成中断,在中断服务函数中判断是否读写指针相等,若相等就清除DMA正在进行的标志位等待下一次开启DMA传输,若不相等就直接开启下一次DMA传输。环形DMA串口发送数据方法流程如下图1。
在这里插入图片描述

图1环形DMA串口发送数据方法流程图

3.2循环存储

首先,定义一个固定长度的数组,该数组的长度应能保证可存储多条通信协议。以本文为例,设置缓存数组长度为256bytes。定义读指针tr和写指针tw,其中读指针tr指向DMA准备发送的字节在数组中的地址,写指针tw指向最新准备发送的数据在数组中的地址。当开始一次DMA传输时,发送数据的首地址为读指针tr,发送数据的长度为读写指针tr和tw之间的数据长度。发送完当前数据后,读指针tr递增至原写指针tw的位置,并检查有没有新数据,即检查tw是否改变。当指针地址偏移量达到256bytes,将相应指针重新指向数组首地址。示意图如图2所示。

在这里插入图片描述

图2循环缓存示意图
指针tw和tr在本文方法中用来表示串口数据存储和发送的进度,定义len表示一次DMA发送的数据大小,剩余空间即(256-len)bytes。
在这里插入图片描述

标签:DMA,一帧,发送,串口,发送数据,字节,指针
From: https://blog.csdn.net/weixin_43549140/article/details/143026942

相关文章

  • 【CANoe】智能座舱、使用Capl脚本自动化发送报文
    使用Capl脚本发送报文:CAPL脚本是CANoe中一种类C的语言,需要与网络节点关联,也可以利用其加强测量分析功能,以及搭建高效的自动化测试模块。1.定时器比如我们需要周期性的发送CAN报文,或者周期性的检测某个系统变量的变化时就需要用到定时器。#使用定时器的第一步就是申明定时......
  • 如何用axios发送ajax请求(函数)
    在上篇文章的基础上将格式改为:btns[2].onclick=function(){axios({//请求方法method:'POST',url:'/axios-server',params:{vip:10,......
  • Java 集成阿里云发送短信
    首先要有个阿里云账号,可到阿里云登录页注册并登录。登录后访问短信服务快速学习和测试,其中有逐步介绍如何发送短信:新增资质新增资质相当于进行实名认证,资质是申请签名的实名化信息。申请签名签名是短信中能代表发送者属性的字段。一般就是公司名字。发送短信时,签名会附加到......
  • 【链路层】流量控制:发送窗口大小和链路利用率
    一直觉得公式分母似乎有些小问题,结果仔细一画图分析就是对的在数据链路层的滑动窗口式流量控制中,需要确定发送端的发送窗口大小(最大在途帧数)。这个问题的讨论引出了链路利用率和实际数据传输速率的概念和计算。结论链路利用率(信道利用率,以下简称利用率):发送方在一个发送周期的......
  • 故障5:2022年1月1日所有邮件不能发送接收(Email Stuck in Exchange On-premises Transpo
    凯中故障5:2022年1月1日所有邮件不能发送接收(EmailStuckinExchangeOn-premisesTransportQueues)https://techcommunity.microsoft.com/t5/exchange-team-blog/email-stuck-in-exchange-on-premises-transport-queues/ba-p/3049447https://social.microsoft.com/Forums/zh-C......
  • 使用RabbitMQ发送和接收对象
    消息转换器当消息生产者发送的数据为对象时,接受到的信息如下,需要通过转换器将其转为易读、容量小的数据![image-20241016上午101616219](/Users/mianbao/Library/ApplicationSupport/typora-user-images/image-20241016上午101616219.png)配置JSON转换器1.导入依赖<dependen......
  • 《如果主机没有配置网关,ping不在同一网段的ip,主机会发送ARP吗?》
    一、在开始实验前,我们得先深刻剖析理解ARP协议的含义。1.1ARP1.1.1ARP的定义ARP是“AddressResolutionProtocol”(地址解析协议)的缩写。1.1.2ARP的作用及运行流程分析泛谈:在同一子网中,数据包的传输都是依据MAC地址进行的(分组交换设备仅设置交换机),在跨子网通信时,......
  • WebServer构建响应 && 发送响应
    1.构建响应构建响应流程如下确认方法根据不同方法,以不同方法提参确认访问资源如果用户的URL没有指明要访问的某种资源(路径),虽然浏览器默认会添加/,但是依旧没有告知服务器,要访问什么资源此时,默认返回对应服务的首页这里的/不是Linux服务器的根目录,通常是http服务器设......
  • python使用smtp发送邮件
    python使用smtp发送邮件一、概述与发送邮件相关的Python模块:smtplib是关于SMTP(简单邮件传输协议)的操作模块,在发送邮件的过程中起到服务器之间互相通信的作用。email简单来说,即服务器之间通信的信息,包括信息头、信息主体等等。举个简单的例子,当你登录邮箱,写好邮件......
  • 用python、JavaScript、JAVA等多种语言的实例代码演示教你如何免费获取股票数据(实时数
    ​近一两年来,股票量化分析逐渐受到广泛关注。而作为这一领域的初学者,首先需要面对的挑战就是如何获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息,这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的核心任务是从这些数据......