打印
[STM32F1]

DMA传PWM的脉冲数不准确问题

[复制链接]
2221|34
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ckjjj|  楼主 | 2020-9-7 10:59 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
用DMA传PWM脉冲数,需要发指定数量的脉冲数(10,200,500,1000,2000...)。之前发脉冲的的时间没有限制。然后调试发脉冲个数没问题。后面加上限定每1ms分别发这些脉冲。发10个或200个是没问题。然而在发500或1000个脉冲的时候,多了1个脉冲,发2000个脉冲多了3个脉冲数。而且这多的脉冲是标准的脉冲,而不是不完整的脉冲。请问为什么前面发10个或200个是没问题,然而后面的脉冲数多了就会存在多发脉冲的情况?改了优先级试过没用。附件上有程序,请大佬帮忙分析。

172607ab1pb4rbxyx1m4rc.png (115.51 KB )

这段是发500个脉冲

这段是发500个脉冲

172643kmjc7yzm8mbkdtcp.png (35.77 KB )

这里就刚好1ms,但后面会多一个脉冲

这里就刚好1ms,但后面会多一个脉冲

PWM Encoder.zip

314.42 KB

波形分析.zip

12.53 KB

用逻辑分析仪抓到的波形

使用特权

评论回复
沙发
香水城| | 2020-9-7 11:36 | 只看该作者
问你下,你好像用到多个定时器,定时器的启动、停止你是怎么安排的。

脉冲个数靠什么掌控,通过DMA传输的CCR值来掌控?DMA的触发事件是什么,更新事件还是比较事件?

你大致介绍下 然后人家看你代码就会方便很多。

使用特权

评论回复
评论
ckjjj 2020-9-7 13:29 回复TA
嗯嗯,是这样,我这个TIM的安排是输出PWM和编码器接收功能,编码器部分不看。因为我需要不定数量的可调占空比和频率的脉冲数,我是通过一组数组用来确定脉冲数,根据我设置的频率来通过关系pwm_period = PWM_CK_CNT1/Frequency - 1算出计数周期ccr。DMA的触发事件当然就是DMA传输完成事件触发,清零ccr值,停止发送脉冲。 
板凳
ckjjj|  楼主 | 2020-9-7 14:08 | 只看该作者
本帖最后由 ckjjj 于 2020-9-7 14:22 编辑

我是想实现多路脉冲+编码器接收功能。因为是小白,之前经过了很多考虑,包括IO翻转,或者定时器比较输出,都考虑过,但存在频繁中断的情况,或者不能单独改变每一路的频率,于是用DMA+PWM的方式发脉冲。主任务1ms会发一个脉冲数的数据,所以我需要在1ms内把脉冲发完才行。于是我就用DMA+PWM来。我的理解上,DMA用来控制脉冲个数,TIM负责发送PWM,于是脉冲个数就是DMA长度,这样,当DMA传数据直到DMA长度为0,产生中断把TIM-CCRx设置为0,停止定时器的发PWM,然后清除DMA中断标志。现在呢,因为需要1ms就要把脉冲发完,并且占空比设置为50%,所以,我在每次发送脉冲之前,分别设置TIM的PSC,ARR,和CCR,通过关系得到PSC,通过关系,算出ARR,然后知道ARR后就能知道设置比较值CCR,然后我设置好DMA长度后就开启DMA,这样就开始传数据。

然后呢,里面有几个函数可能没说清。TIMx_Dma_Pwm_Output_Init用来初始化PWM功能;TIMx_Dma_Pwm_Output用来输出PWM;Axis_Pwm_Mode_Cfg因为是用脉冲+方向的方式控制,所以用来配置脉冲的高或者低电平有效,以及方向高低电平有效;最主要就是初始化和输出PWM这两个函数,所以模式可以不用太注意。


使用特权

评论回复
地板
香水城| | 2020-9-8 12:50 | 只看该作者
感觉上你的脉冲个数是通过DMA不停送数据给CCR,通过DMA的传输次数来控制的,在DMA传输完成中断里修改CCR停止脉冲输出。

如果这样的话,你要注意DMA传输完成跟脉冲输出完成的同步问题,否则会出现关闭脉冲输出过早或过晚的情况。

我前面问你的DMA的触发事件是什么,即问你DMA请求是来自什么,你似乎误会我的意思了。估计是比较事件或更新事件。

像你这种指定个数脉冲的输出,最方便就是使用高级定时器的重复计数器结合单脉冲模式,要几个就输出几个。

另外,当然用DMA修改CCR也可以,要停止时最后一个数据写0或ARR,看你PWM模式。

比方像下面这样,更新事件触发DMA请求,DMA将数据送到CCR,关闭CCR的预装功能。
假设发送N个脉冲,第N+1个脉冲时送 0 给CCR 以停止PWM输出。






使用特权

评论回复
评论
ckjjj 2020-9-8 13:59 回复TA
感谢版主的回答,根据你的推荐方法,查了ST的参考手册,只有高级TIM才有这个重复计数器。这个办法我没了解过,不过作为一个方法后面我会试试。因为我需要尽可能多的PWM输出,推荐的办法我只有2路能用,所以我得用别的办法。 你的分析的确有道理,这个同步问题我debug也想到,但没有办法知道造成过晚关闭的原因。包括中断、使能TIM和使能DMA的先后,结果相一样。 
评分
参与人数 1威望 +1 收起 理由
ckjjj + 1 很给力!
5
ckjjj|  楼主 | 2020-9-8 14:08 | 只看该作者
本帖最后由 ckjjj 于 2020-9-8 15:48 编辑
香水城 发表于 2020-9-8 12:50
感觉上你的脉冲个数是通过DMA不停送数据给CCR,通过DMA的传输次数来控制的,在DMA传输完成中断里修改CCR停 ...

然后,你说的DMA的请求事件,嗯,我是用通道的捕获比较事件来的。这点的确是我的理解不到位才误解了。我有种猜测,是不是,频率高了,导致进中断的时候,会多产生脉冲,但没办法验证这个猜测。我在DMA的中断函数中,把中断标志判断用的库函数改为寄存器,发现能发500个了,但后面的都不行,还是会多。我认为这个方法验证了这个猜想,进了中断,这个TIM的频率太高,导致库函数里处理花了些时间。目前的话只有再看看哪里把程序改一下

使用特权

评论回复
6
character| | 2020-9-14 14:59 | 只看该作者
学习一下

使用特权

评论回复
7
yuan_莫| | 2020-9-20 22:46 | 只看该作者
事实证明DMA在传递的 会有一个误差,

使用特权

评论回复
评论
yuan_莫 2020-9-23 14:58 回复TA
@ckjjj :多少通道的?我用的是12(103)通道 当时测试 有时候有问题 有时候没有问题。 
ckjjj 2020-9-23 11:43 回复TA
@yuan_莫 :我这边测试500K以下没问题,因为我主任务1ms周期发送脉冲数过来,所以最少1个脉冲,频率1K,再低可就会接收不过来主任务的数据。虽然开个BUF可以暂存主任务发过来的数据,但感觉会变成个隐形BUG 
yuan_莫 2020-9-23 10:30 回复TA
@ckjjj :, 你降低频率到10k 好像是没有问题的。 1个到1W都可以。 
ckjjj 2020-9-23 10:27 回复TA
@yuan_莫 :我是在一个示例里面去测试这个功能的,也没有别的功能,就一个延时,一个TIM,一个DMA。你那个写信有给你回复么? 
yuan_莫 2020-9-23 10:17 回复TA
@ckjjj :我写信给st中国的技术部 也没有得到一个解决方案, 我的是延迟一个脉冲 最多2个, 如果超过了这个, 肯定就有问题。 我一直怀疑是进出中断导致的。单通道好像没有这个现象, 对了DMA是走的总线方式 你看看是不是你的总线被占用了的导致的误差值。 这种最好还是用FPGA来实现比较好 
ckjjj 2020-9-22 10:04 回复TA
@yuan_莫 :我这边想每路脉冲独立,所以就没用多通道。你说的50K和100K,目前我测试过10K、200K是没有问题,你说的中断延迟导致的可能性,我也有猜测过,就是没有一个验证来支持猜测。你用循环方式去做的话是能够做到怎样的效果? 
yuan_莫 2020-9-21 19:31 回复TA
@ckjjj :我在做12通道 103和407的时候都有测试过 会有1各的误差。 频率在50Khz 100Khz 如果低于20K 好像没有这个现象。, 我估计是中断延迟导致问题。 最后没有办法采用了循环的形式去做的 
ckjjj 2020-9-21 18:12 回复TA
按这个逻辑,它前面发的脉冲数就没问题,而后面的脉冲数又不止多1个脉冲呢 
8
单片小菜| | 2020-9-21 21:15 | 只看该作者
这么做时不可行的。

使用特权

评论回复
评论
ckjjj 2020-9-22 09:58 回复TA
老哥,做法不行,这个是怎么个回事?它这个外设时钟都能36M的,我这产生的PWM频率才2M,也远远没达到上限,为什么还不行? 
9
电子xiaocainiao| | 2020-9-22 18:30 | 只看该作者
感觉还是细节的问题,误差有,但不可能每次都这么大。

使用特权

评论回复
10
ckjjj|  楼主 | 2020-9-22 18:34 | 只看该作者
电子xiaocainiao 发表于 2020-9-22 18:30
感觉还是细节的问题,误差有,但不可能每次都这么大。

这个我也没找到问题,技术没到位,深入不了

使用特权

评论回复
11
東南博士| | 2020-9-23 15:35 | 只看该作者
DMA传PWM脉冲数,需要发指定数量的脉冲数(10,200,500,1000,2000...)

学习学习!

感觉这种 似乎FPGA 是强项啊!

使用特权

评论回复
12
wangjiahao88| | 2020-9-23 15:38 | 只看该作者
使用两个定时器+RT系统处理比较好!

而且使用两个Timer 一个做溢出判断,一个产生PWM 是最好的!

使用特权

评论回复
13
goodluck09876| | 2020-9-23 15:50 | 只看该作者
脉冲个数是通过DMA不停送数据给CCR,通过DMA的传输次数来控制的,在DMA传输完成中断里修改CCR停止脉冲输出。

如果这样的话,你要注意DMA传输完成跟脉冲输出完成的同步问题,否则会出现关闭脉冲输出过早或过晚的情况。

我前面问你的DMA的触发事件是什么,即问你DMA请求是来自什么,你似乎误会我的意思了。估计是比较事件或更新事件。

像你这种指定个数脉冲的输出,最方便就是使用高级定时器的重复计数器结合单脉冲模式,要几个就输出几个。

另外,当然用DMA修改CCR也可以,要停止时最后一个数据写0或ARR,看你PWM模式。

比方像下面这样,更新事件触发DMA请求,DMA将数据送到CCR,关闭CCR的预装功能。
假设发送N个脉冲,第N+1个脉冲时送 0 给CCR 以停止PWM输出。
~~~~~~~~~~~~~~~~~~~~

学到了!!!!!!!

使用特权

评论回复
14
goodluck09876| | 2020-9-23 16:14 | 只看该作者
于是我就用DMA+PWM来。我的理解上,DMA用来控制脉冲个数,TIM负责发送PWM,于是脉冲个数就是DMA长度,这样,当DMA传数据直到DMA长度为0,产生中断把TIM-CCRx设置为0,停止定时器的发PWM,然后清除DMA中断标志。现在呢,因为需要1ms就要把脉冲发完,并且占空比设置为50%,所以,我在每次发送脉冲之前,分别设置TIM的PSC,ARR,和CCR,通过关系得到PSC,通过关系,算出ARR,然后知道ARR后就能知道设置比较值CCR,然后我设置好DMA长度后就开启DMA,这样就开始传数据。

使用特权

评论回复
15
powermaker2568| | 2020-9-23 17:32 | 只看该作者
感觉 高速的情况下 想控制的精准一些 不容易!

使用特权

评论回复
16
carefull3357dc| | 2020-9-23 18:11 | 只看该作者
高速会有一两个脉冲的误差吧!

低速肯定不会!

更何况是DMA!

使用特权

评论回复
17
ckjjj|  楼主 | 2020-9-24 09:45 | 只看该作者
powermaker2568 发表于 2020-9-23 17:32
感觉 高速的情况下 想控制的精准一些 不容易!

emm,但是对于外设能支持到最大36M,这个连1/10都还没达到,也不算太高速的吧

使用特权

评论回复
18
ckjjj|  楼主 | 2020-9-24 09:46 | 只看该作者
carefull3357dc 发表于 2020-9-23 18:11
高速会有一两个脉冲的误差吧!

低速肯定不会!

低速测试是不会,但低速发的脉冲数就不多了

使用特权

评论回复
19
ckjjj|  楼主 | 2020-10-12 10:18 | 只看该作者
東南博士 发表于 2020-9-23 15:35
DMA传PWM脉冲数,需要发指定数量的脉冲数(10,200,500,1000,2000...)

学习学习!

你ID好熟啊,是WSY那个Ethercat的群?

使用特权

评论回复
20
ckjjj|  楼主 | 2020-10-12 10:39 | 只看该作者
wangjiahao88 发表于 2020-9-23 15:38
使用两个定时器+RT系统处理比较好!

而且使用两个Timer 一个做溢出判断,一个产生PWM 是最好的! ...

嗯,我也用主从TIM测试。然后分析了下,始终还是在发送PWM部分,配置ARR那里,我主频是72M,然后呢,如果我固定1ms周期发送500个脉冲,然后我每个脉冲的ARR就是72M/1000/500=144,当我发大于1000个的话,这个值除不尽导致偏差

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

20

帖子

0

粉丝