基于F28335的Simulink代码生成(五)——DMA的使用

11 篇文章 24 订阅
9 篇文章 3 订阅

基于F28335的Simulink代码生成系列文章目录

基于F28335的Simulink代码生成(一)——搞懂模型的运行逻辑
基于F28335的Simulink代码生成(二)——EPWM模块同步设置问题
基于F28335的Simulink代码生成(三)——EQEP模块获取光电编码器的速度与角度信息
基于F28335的Simulink代码生成(四)——如何链接可以访问底层文件的外部源文件和头文件
基于F28335的Simulink代码生成(五)——DMA的使用
基于F28335的Simulink代码生成(六)——如何修改变量的存储类型
基于F28335的Simulink代码生成(七)——成果展示



28335的DMA

DMA的使用可以很大程度上减少CPU的运行负担,在前面的文章中,我通过记录的方式,已经将我基于MBD开发永磁电机矢量控制的过程中遇到的一些个问题都写出来了,其实也不算基础教程,就是作为一个对于Simulink较为熟练的人在做MBD中完成一些和底层链接的工作。
后期想要的样子肯定是通过通信实现可视化操作的,希望有机会实践。

官方例程中的DMA

还记得几年前第一次接触DMA时,觉得这玩意儿好麻烦,要有源地址目标地址,还有什么循环,递增的操作,想要搞懂这个逻辑的确需要花费一段时间。也忘了之前有没有完全搞懂了,昨天晚上突然想起来,想在原来的模型中把ADC的采集换成DMA传输,虽然10KHz的运行频率是足够我代码跑完的。但是考虑到后期需要加入更加复杂的算法,以及后期做更多的采样。并且做到更加系统化,工业化的东西的时候,这种操作也是十分必要的。
网上有根据官方例程的ADC_DMA做了很多讲解,个人觉得也还OK。这里推荐可以试试这条博客的:https://blog.csdn.net/qq_40692629/article/details/88622324
主要就是理解burst、transfer、wrap的概念

MBD的DMA使用

在模型中可以在硬件设置中选择DMA的设置。这样的形式实质上比代码更加清晰,但是里面很多名词需要进一步说明和注意。
在这里插入图片描述
本文的目的是在10KHz的EPWM中断中采集三路ADC的值,通过DMA存储到同一个数组中,每个ADC数组存放16个值,数组长度位48个16位无符号字节。然后中断中在做均值滤波操作。
对于DMA的传输方式一般有两种:Transfer传输和wrap传输。这两种传输方式在工作时只能有一种有效。DSP通过wrapsize位字段或者transfersize位字段,谁的字段大就屏蔽谁的。
首先是确定burst字段的相关概念。她一共有三个字段:burst size;source burst step;Destination burst step。其中burst可以认为是帧的概念,burst size也就是一帧传输多少个数据过去。source burst step指的是一帧中每传输一个数据,源地址也就是我们这里用的AdcMirror.ADCRESULT0,在一帧中,传输完ADCRESULT0后,想传输下一个的时候,ADCRESULT0+Destination burst step即可选择相关地址偏移后的地址,那么接下来就是目的地址的问题了,也就是传输到ADC_result_array的哪个位置?第一帧的第一个数据自然是传输到ADC_result_array[0],那么下一个数据传输到哪个位置呢?这就要根据Destination burst step来看了。目标地址在传完第一个数据后,第二个数据会偏移到ADC_result_array+Destination burst step这个新的地址。好了,到这儿一帧的数据传输已经基本搞懂了,但是值得注意的是在MBD中burst size就是一帧总共的数据个数,然而在代码中*DMACH1BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)*的bsize=burst size-1。那么transfer size 和wrap size 也是同理。
接下来的问题就是传输完一帧后如何传输第二帧,因为我的目的是第一个ADC0传输到目标数组的前16个位置,第二个ADC1传输到后面的16个位置,以此类推。
DSP给的第一张方式——Transfer传输。首先需要确定他Transfer的次数,也就是transfer size的大小,确定为16。那么接下来就是第一帧传输结束后,源地址如何回到AdcMirror.ADCRESULT0,目标地址又如何回到ADC_result_array[1]。可以看到transfer还有两个参数,分别是source transfer step;Destination transfer step。这个就很好理解了,跟burst差不多。就是当我传输完一帧后,我的源地址是在AdcMirror.ADCRESULT3,所以source transfer step=-2时,我的源地址每次传输完就会-2回到AdcMirror.ADCRESULT0。那目标地址呢?第一帧传输完,我的目标地址应该是在ADC_result_array[32],我需要他回到ADC_result_array[1],所以当Destination transfer step=-31时就可以完成这个目的。结果见图
在这里插入图片描述
下一个传输方式是wrap传输,这是种回绕的方式,对于实现本文的目的来说显得更加方便。并且对于这种形式的回绕他会更加灵活。
同样,几个概念:source wrap size;Destination wrap size;source wrap step;Destination wrap step,可以发现wrap参数还是蛮多的。他的一个特点就是源地址和目标地址的回绕是可以分开的,这是transfer做不到的。source wrap size的概念是当第几个burst传输完成源地址后回绕,也就是第几帧完成的时候回绕。源地址回绕后会回到AdcMirror.ADCRESULT0,如果想到其他的位置就用到了source wrap step,其是在AdcMirror.ADCRESULT0+source wrap step,说明回绕后回到第几个源地址。那么Destination wrap size和Destination wrap step的概念也就清晰了,一个是目标地址在第几个burst完成后回绕,回绕后的目标地址为ADC_result_array[i]+Destination wrap step,其中ADC_result_array[i]指的是上一次回绕到的目标地址。
最终配置如下:
当完成WRAP_SIZE个burst传输时,就发生地址WRAP。此时,在起始地址的基础上增加WRAP_STEP,重新使用该地址作为下一次burst传输的地址。这里的“起始地址”就是第一次burst的地址。
值得注意的是这种wrap 的方式也要确认一共要传输多少次才产生中断,也就是我们的transfer size,所以这个值一就要保持16。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LEODWL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值