硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2448|回复: 35
收起左侧

[DMA] STM32H7的DMAMUX的定时器触+DMA双缓冲控制任意IO做PWM和脉冲数控制,使用DMA NORMAL控制方法

  [复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-8-20 15:21:23 | 显示全部楼层 |阅读模式
原始案例和教程:

教程第43章及其配套例子
https://forum.anfulai.cn/forum.php? ... 6980&extra=page%3D1


修改方法

之前是采用的,DMA循环模式,使用NORMAL模式修改方法

74060337CB029FB8885998BE3D4D823F.png

然后脉冲也是对的。只是第1次DMA NORMAL的第1次发脉冲时间有点短

1.png

再发一个DMA NORMAL的脉冲就正常了。

2.png

修改后完整案例

V7-011_DMAMUX修正版.7z (1.31MB)
回复

使用道具 举报

692

主题

3576

回帖

5677

积分

论坛元老

积分
5677
发表于 2024-8-20 16:23:19 | 显示全部楼层
貌似下载不了呀 ?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-8-21 12:33:04 | 显示全部楼层
hpdell 发表于 2024-8-20 16:23
貌似下载不了呀 ?

可以了,已经修正。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-8-22 10:53:31 | 显示全部楼层
V7群友分享,修改下执行顺序可解决第1个脉冲宽度不对问题

12.png
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2024-8-24 20:44:33 | 显示全部楼层
eric2013 发表于 2024-8-22 10:53
V7群友分享,修改下执行顺序可解决第1个脉冲宽度不对问题

大佬 我尝试了改一下顺序,还是不行呀,有没有完整的工程啊
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-8-25 10:20:53 | 显示全部楼层
2859932063 发表于 2024-8-24 20:44
大佬 我尝试了改一下顺序,还是不行呀,有没有完整的工程啊

这个是群友测试的,我没测,改天我试试。
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2024-8-25 18:35:17 | 显示全部楼层
eric2013 发表于 2024-8-25 10:20
这个是群友测试的,我没测,改天我试试。

好的谢谢英汉了
回复

使用道具 举报

36

主题

149

回帖

262

积分

高级会员

积分
262
发表于 2024-8-27 15:38:18 | 显示全部楼层
正常模式现在问题每次发脉冲都要初始化DMA(HAL_DMA_DeInit)和配置DMAMUX(HAL_DMAEx_ConfigMuxRequestGenerator),执行太多的代码占用时间, 单独调用HAL_DMA_Start_IT不行。循环模式问题个数控制不准,动不动少半脉冲。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-8-27 16:49:21 | 显示全部楼层
takent 发表于 2024-8-27 15:38
正常模式现在问题每次发脉冲都要初始化DMA(HAL_DMA_DeInit)和配置DMAMUX(HAL_DMAEx_ConfigMuxRequestGen ...

1、单次这个,肯定是可以解决的,测试那几个参数下次执行需要再配置。仅调用HAL_DMA_Start_IT不行,肯定是那个参数遗漏了。
2、循环模式不可能丢,如果出现丢的情况,DMA传输次数就出问题了。有可能是动态缓冲更新不及时。
回复

使用道具 举报

36

主题

149

回帖

262

积分

高级会员

积分
262
发表于 2024-8-28 10:21:40 | 显示全部楼层
eric2013 发表于 2024-8-27 16:49
1、单次这个,肯定是可以解决的,测试那几个参数下次执行需要再配置。仅调用HAL_DMA_Start_IT不行,肯定 ...

循环模式改LPTIM1、2、3定时器最后一个脉冲不正常,完成中断用HAL_LPTIM_PWM_Stop停止,最后一个脉冲低电平很短后变为高电平
1.png
2.png
回复

使用道具 举报

36

主题

149

回帖

262

积分

高级会员

积分
262
发表于 2024-8-28 10:28:21 | 显示全部楼层
    定时器配置
LptimHandleX.Instance                           = LPTIM1;
    LptimHandleX.Init.CounterSource                 = LPTIM_COUNTERSOURCE_INTERNAL;
    LptimHandleX.Init.UpdateMode                    = LPTIM_UPDATE_ENDOFPERIOD;
    LptimHandleX.Init.OutputPolarity                = LPTIM_OUTPUTPOLARITY_LOW;
    LptimHandleX.Init.Clock.Source                  = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
    LptimHandleX.Init.Clock.Prescaler               = LPTIM_PRESCALER_DIV2;
    LptimHandleX.Init.UltraLowPowerClock.Polarity   = LPTIM_CLOCKPOLARITY_RISING;
    LptimHandleX.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION;
    LptimHandleX.Init.Trigger.Source                = LPTIM_TRIGSOURCE_SOFTWARE;
    LptimHandleX.Init.Trigger.ActiveEdge            = LPTIM_ACTIVEEDGE_RISING;
    LptimHandleX.Init.Trigger.SampleTime            = LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION;
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-8-28 10:37:36 | 显示全部楼层
takent 发表于 2024-8-28 10:21
循环模式改LPTIM1、2、3定时器最后一个脉冲不正常,完成中断用HAL_LPTIM_PWM_Stop停止,最后一个脉冲低电 ...

使用循环模式不要去暂停,应该设置缓冲为全高或者全低
回复

使用道具 举报

36

主题

149

回帖

262

积分

高级会员

积分
262
发表于 2024-8-28 10:43:37 | 显示全部楼层
不停止的话,会一直进中断
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2024-8-28 10:55:02 | 显示全部楼层
takent 发表于 2024-8-28 10:43
不停止的话,会一直进中断

其实用普通定时器也可以的,但是就会出现第一次脉冲宽度不对。现在一直不太明白问题出在哪里
回复

使用道具 举报

6

主题

306

回帖

324

积分

高级会员

积分
324
发表于 2024-8-28 11:00:34 | 显示全部楼层
DMA控制GPIO,感觉还是有点不可控,DMA会和CPU进行竟争,有可能阻塞,还是PWM靠谱。但也是一个不错思路。
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2024-8-28 11:14:38 | 显示全部楼层
fxyc87 发表于 2024-8-28 11:00
DMA控制GPIO,感觉还是有点不可控,DMA会和CPU进行竟争,有可能阻塞,还是PWM靠谱。但也是一个不错思路。

总线上有竞争而已,除非cpu或者dma把总线的带宽占满,
回复

使用道具 举报

6

主题

306

回帖

324

积分

高级会员

积分
324
发表于 2024-8-28 13:32:34 | 显示全部楼层
2859932063 发表于 2024-8-28 11:14
总线上有竞争而已,除非cpu或者dma把总线的带宽占满,

是的,如果速度不是特别快到Mhz级别那基本上看不出来区别。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-8-28 15:40:50 | 显示全部楼层
takent 发表于 2024-8-28 10:43
不停止的话,会一直进中断

这个没关系,CPU闲着也是闲着,这个中断里面的代码执行时间非常短。
回复

使用道具 举报

36

主题

149

回帖

262

积分

高级会员

积分
262
发表于 2024-8-28 18:24:25 | 显示全部楼层
DMA真难用各种问题,搞了两周了。
修改缓存也要大量时间,4K缓存。
循环模式的发送数据长度用HAL_DMA_Start_IT不能重新修改,频率可以改,重新指向用HAL_DMA_Start_IT另一个内存也不行这样不修改缓存
回复

使用道具 举报

0

主题

8

回帖

8

积分

新手上路

积分
8
发表于 2024-11-16 20:37:38 | 显示全部楼层
汉子哥,有个疑问没看懂,直接控制BSRR寄存器,例程使用的是PB1,会不会影响到PB2,3,等等其他的端口状态,如果有其他端口配置成其他模式如IIC,SPI,ADC啥的
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-11-17 11:18:59 | 显示全部楼层
大花狸 发表于 2024-11-16 20:37
汉子哥,有个疑问没看懂,直接控制BSRR寄存器,例程使用的是PB1,会不会影响到PB2,3,等等其他的端口状态, ...

不会,我们这里使用的BSRR寄存器,不是ODR.
使用ODR不行,会影响其它。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2024-12-19 20:31:43 | 显示全部楼层
大神,你好,这种DMAMUX的定时器触+DMA双缓冲控制任意IO做PWM和脉冲数控制,能否用TIM12_TRGO来同时触发多个DMA,来分别操作PA,PB,PC口呢?
我使用TIM12_TRGO来触发DMA1_Stream1,DMA1_Stream2,DMA1_Stream3,出DMAMUX1_OVR_IRQHandler中断。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2024-12-20 08:45:35 | 显示全部楼层
tabc_123 发表于 2024-12-19 20:31
大神,你好,这种DMAMUX的定时器触+DMA双缓冲控制任意IO做PWM和脉冲数控制,能否用TIM12_TRGO来同时触发多 ...

这个可以试试。
回复

使用道具 举报

4

主题

34

回帖

46

积分

新手上路

积分
46
发表于 2025-1-19 21:25:16 | 显示全部楼层
你好硬汉老大,请问这种方式 能实现8路,不同频率的脉冲 同时输出吗? 假设就用h7系列芯片
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2025-1-20 06:21:57 | 显示全部楼层
asj 发表于 2025-1-19 21:25
你好硬汉老大,请问这种方式 能实现8路,不同频率的脉冲 同时输出吗? 假设就用h7系列芯片

可以的,频率跨度不要太大。
回复

使用道具 举报

4

主题

34

回帖

46

积分

新手上路

积分
46
发表于 2025-1-20 07:35:27 | 显示全部楼层
eric2013 发表于 2025-1-20 06:21
可以的,频率跨度不要太大。

频率跨度大行不行,我需要实现在1ms内 最少发1个脉冲,最多发100个脉冲

8路要发出的脉冲数随机

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
 楼主| 发表于 2025-1-21 08:16:42 | 显示全部楼层
asj 发表于 2025-1-20 07:35
频率跨度大行不行,我需要实现在1ms内 最少发1个脉冲,最多发100个脉冲

8路要发出的脉冲数随机

这种的完全没问题。我以为你是一个1Hz,一个1MHz的频率。
回复

使用道具 举报

4

主题

34

回帖

46

积分

新手上路

积分
46
发表于 2025-1-21 08:21:39 | 显示全部楼层
eric2013 发表于 2025-1-21 08:16
这种的完全没问题。我以为你是一个1Hz,一个1MHz的频率。

谢谢大佬,我研究一下
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-1-21 22:29:16 | 显示全部楼层
asj 发表于 2025-1-20 07:35
频率跨度大行不行,我需要实现在1ms内 最少发1个脉冲,最多发100个脉冲

8路要发出的脉冲数随机

可以使用一个定时器的八个通道分别触发8个dma通道,将定时器频率加快,可以定制很多数字波形了,代价就是消耗内存,而且如果GPIO都是在同一组,一个dma通道就足够了
回复

使用道具 举报

4

主题

34

回帖

46

积分

新手上路

积分
46
发表于 2025-1-22 08:00:58 | 显示全部楼层
2859932063 发表于 2025-1-21 22:29
可以使用一个定时器的八个通道分别触发8个dma通道,将定时器频率加快,可以定制很多数字波形了,代价就是 ...

一个定时器 的8个通道 如何产生不同频率的 pwm来触发dma? 按照我的思路,产生不同频率的pwm,必须使用不同的定时器。所以8路pwm,需要8个定时器,好在 h7 我看了,定时器多,我用不掉,等这两天有空我试一下
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-1-22 18:21:09 | 显示全部楼层
asj 发表于 2025-1-22 08:00
一个定时器 的8个通道 如何产生不同频率的 pwm来触发dma? 按照我的思路,产生不同频率的pwm,必须使用不 ...

你的定时器频率最够快就可以,代价就是内存,比如你定时器是1mhz的,那通道每次发10个高电平就变成100khz了,但是内存量是正常的10倍
回复

使用道具 举报

4

主题

34

回帖

46

积分

新手上路

积分
46
发表于 2025-1-22 20:26:16 | 显示全部楼层
2859932063 发表于 2025-1-22 18:21
你的定时器频率最够快就可以,代价就是内存,比如你定时器是1mhz的,那通道每次发10个高电平就变成100khz ...

哦,我了解了你的意思,你的意思是传输的数组,有多个连续的相同的,那是比较费内存
回复

使用道具 举报

7

主题

117

回帖

138

积分

初级会员

积分
138
发表于 2025-6-21 17:15:28 | 显示全部楼层
asj 发表于 2025-1-22 20:26
哦,我了解了你的意思,你的意思是传输的数组,有多个连续的相同的,那是比较费内存

那想法不止费内存,要精确控制每一个输出的频率和个数也难,意味着容易错
回复

使用道具 举报

7

主题

117

回帖

138

积分

初级会员

积分
138
发表于 2025-6-22 12:46:50 | 显示全部楼层
本帖最后由 死不低头 于 2025-6-22 12:48 编辑

试过STM32F1 F4 H7的几种输出可调脉冲频率和精确个数的方法:

1,首推比较输出翻转+DMA模式,一个定时器最多可以支持4个,可以实现十多路脉冲进行梯形、S型加减速,中断频率也不高,就是做各种高难度的圆弧插补、电子齿轮、电子凸轮、3轴联动、4轴联动也很方便。缺点一费DMA通道每个脉冲要一个通道,二频率很难上得去因为每个比较值都要累加到下一次,三频率不是十分精确,因为比较值计算不是在定时器比较中断里算的,特别是中断比较多多的情况下,因为每次更新都要一些周期数,不确定。

2,搞一个任意的定时器,在定时器中断里计算每个IO输出需要的时间进行翻转,可以实现任意IO输出脉冲,优点是IO基本上随意指定,做加减速或者联动也很方便。缺点:一是中断频率会比较高(200K左右)中断次数太多,而且输出IO翻转速度不会很高,最多也就是中断频率的一半;二是波形不太好看,如果翻转频率到达中断五分之一频率翻转的时候波形就难看了,要平滑输出还要有优化算法。

3,定时器输出通道比较匹配翻转输出,下一次翻转时间在中断里进行累加,也可以输出很多个脉冲,但是IO引脚不能随意分配,中断频率可能比第二种还高得多(比如4个通道不同步输出不同个数30K脉冲,需要中断30K*2*4),输出波形会比第二种好看很多,控制数量比DMA要可靠。

4,定时器触发DMA控制任意IO输出,就是楼主说的这种方式,试过,要加减速要控制精确个数有难度,没想到好办法,没深入测试,略过。

5,用USART输出脉冲,异步单线半双工模式,用DMA或者不用DMA都可以,频率可以通过波特率调节或者通过需要发送的字节进行调节,速度可以很快个数也比较容易控制,有硬件FIFO或者DMA可以比较小负载控制多个,但是要S型加减速和复杂运动应该不用想了,反正我没想到。同理如果IO引脚够多,SPI也可以,时钟线不用就是。IIC和CAN应该不太好用,有乱七八糟的应答和仲裁什么的。STM32的USART和SPI数量不少,像H7,应该可以剩下10来个,当然缺点还有一个,不能随意指定引脚。

6,一个定时器输出一路PWM,用DMA或者中断进去改周期和占空比就行,有点是中断频率会是方法2的一半,缺点是定时器使用比较多,但是不用不是浪费了吗,ST的定时器还支持各种联动,但是我没试过。

7,主从定时器方式,就是上面6的拓展,好处是可以很长时间进一次中断,缺点有几个,一是定时器不能随意组合,可选的组合非常有限,IO基本固定的。

8,DMA直接触发IO,这个用F4试过,波形不好看,调节频率完全依赖数组,不靠谱。

9,两个高级定时器有重复计数器,很好,但是只有两个。

10,高精度定时器很好,但是我的MCU没有.......

总结下来就是如果只是拿一个MCU专门来做运动控制,STM32应该还不错,如果做主控,分出一部分资源做运动控制,STM32不太合适,它的定时器适合PWM,不适合PTO。
回复

使用道具 举报

5

主题

23

回帖

38

积分

新手上路

积分
38
发表于 2025-6-23 10:29:17 | 显示全部楼层
死不低头 发表于 2025-6-22 12:46
试过STM32F1 F4 H7的几种输出可调脉冲频率和精确个数的方法:

1,首推比较输出翻转+DMA模式,一个定时器 ...

有没有推荐非常适合做PTO 的芯片呢,且非常主流
回复

使用道具 举报

7

主题

117

回帖

138

积分

初级会员

积分
138
发表于 2025-6-23 12:11:33 | 显示全部楼层
VDVA 发表于 2025-6-23 10:29
有没有推荐非常适合做PTO 的芯片呢,且非常主流

大厂里NXP的LPC55S69应该不错,TI的很多也行,国产HPM和HC32。适合做PTO的首先最好定时器个数要多,最好每个通道都有各自的计数器,如果定时器能和32位计数器通过硬件互联或者DMA互联,基本上可以不进中断跑0-2的32次方个脉冲,够用了。

说这么多,其实就是需要32计数器/定时器多,并且能够外设互联,或者CPU核心多,高端MCU都没问题,主要还是成本。

其实低成本里最合适的可能是树莓派的RP2350B了,发脉冲和做运动控制核多才是王道,而且它32位定时器计数器还很多,但是这玩意不是拿来做工控的,IO太少,适合工业的通信接口也基本没有,还不知道稳定性怎么样。

最可惜的就是HC32F4A0这个,价格也很便宜,和需求匹配度90%以上,就差最后两步:32位的DCU只有4个能做独立目标,如果是8个都能做独立的,或者直接加到12个独立的,那拿来做PTO得爽死;另外就是它有一组定时器4个共8个通道,默认就是输出50%占空比的脉冲,只能改频率非常适合做PTO,但是它没缓冲寄存器,需要进中断或者用DMA来动态改频率,如果像其它定时器一样有个缓存来自动更改,完全不用进中断也不用DMA了。

如果有稍微复杂一点的应用需求,最靠谱还是上多核/多芯片的,或者专门用一个核/芯片来做这个控制,毕竟现在一个F4或者性价比款的H7也就十几块钱。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 20:03 , Processed in 0.064108 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表