OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 32524|回复: 119

各种方案,精确输出可控脉冲个数,尽量可控周期或占空比(脉冲 dma)

  [复制链接]

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-7-24 23:47:54 | 显示全部楼层 |阅读模式
本帖最后由 nashui_sx 于 2021-1-26 16:26 编辑

通过想象,查阅资料发现大家有以下方式控制脉冲个数,分别做个例子供大家参考
1.
低频定时器翻转io,中断内统计个数           优点:简单                                             缺点:浪费cpu,频率可能低
2.
输出比较模式,中断内统计个数                 优点:可变周期 占空比,路数多的去了     缺点:浪费cpu,频率也可能低
3.pwm
连通外部中断或外部计数数个数          优点:简单                                            缺点:浪费cpu,浪费定时器待测(懒得用这个方法)
4.
高级定时器 重复计数寄存器+单脉冲模式    优点:频率比前俩高点                            缺点:定时器固定了,只能高级定时器,路数少待测(懒得用这个方法)
5.
定时器主从模式                                       优点:周期占空比都可变                         缺点:用两个定时器,路数也少
6.
定时器UP溢出通道dma,改变dma传输长度控制个数     优点:能读取剩余脉冲个数
                                                               
可变占空比,周期,用于可以调速等         缺点:好像没哈缺点(与7比路数少浪费定时器,推荐7)
7.定时器CHx独立通道dma,改变dma传输长度控制个数(上一个用的溢出dma一个定时器只能产生一路有点浪费,改成用通道dma
                                                              一个定时器可以产生3路或4路,dma限制不能是4,例如定时器5、8可以4路
                                                               
优点:能读取剩余脉冲个数
                                                               
可变占空比,周期,用于可以调速等         缺点:好像没哈缺点

有网友高级定时器弄得有问题,增加了部分高级定时器的例子
所有的测试例子为了保证上一个脉冲执行完毕,都加了延时,仅做抛砖引玉,大家用的时候可以添加处理判断执行情况,是覆盖还是追加脉冲
更新帖子实验结果图片出错都删了



1 定时器翻转io-中断内统计个数.rar

269.72 KB, 下载次数: 550

2 输出比较模式-中断内统计个数.rar

279.77 KB, 下载次数: 637

5 定时器主从模式.rar

268 KB, 下载次数: 1034

6.1普通定时器up触发dma,改变dma传输长度控制个数 单定时器单路.rar

285.76 KB, 下载次数: 936

6.2普通定时器up触发dma,改变dma传输长度控制个数 双定时器实现双路.rar

287.39 KB, 下载次数: 1416

7.1高级定时器Chx触发dma,改变dma传输长度控制个数 一个定时器单路(一个定时器最多3.rar

290.18 KB, 下载次数: 497

7.2普通定时器Chx触发dma,改变dma传输长度控制个数 一个定时器双路(一个定时器最多3.rar

290.68 KB, 下载次数: 463

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-5-19
在线时间
18 小时
发表于 2019-7-30 20:02:36 | 显示全部楼层
老哥人特别好 东西也写的特别棒 帮顶
回复 支持 反对

使用道具 举报

3

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
184
金钱
184
注册时间
2017-7-25
在线时间
36 小时
发表于 2019-8-7 14:48:54 | 显示全部楼层
really good.....6666666666666666666666666666666666666666666666666666666666666666666666666666666666666
回复 支持 反对

使用道具 举报

19

主题

59

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
480
金钱
480
注册时间
2016-6-2
在线时间
116 小时
发表于 2019-8-16 15:20:05 | 显示全部楼层
非常感谢分享
回复 支持 反对

使用道具 举报

0

主题

131

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2019-7-1
在线时间
6 小时
发表于 2019-8-21 13:34:31 | 显示全部楼层
感谢楼主分享
IIS7站长  http://www.iis7.com/
回复 支持 反对

使用道具 举报

10

主题

293

帖子

0

精华

高级会员

Rank: 4

积分
623
金钱
623
注册时间
2019-6-3
在线时间
107 小时
发表于 2019-8-21 14:28:18 | 显示全部楼层
有心了老哥,谢谢分享!我一般用第6种方式
回复 支持 反对

使用道具 举报

2

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
282
金钱
282
注册时间
2019-1-15
在线时间
41 小时
发表于 2019-8-21 14:35:16 | 显示全部楼层
感谢楼主分享
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-8-21 14:39:50 | 显示全部楼层
迅得电子 发表于 2019-8-21 14:28
有心了老哥,谢谢分享!我一般用第6种方式

都应该用第六种,可就是有人要用前几种
回复 支持 反对

使用道具 举报

2

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2018-8-23
在线时间
28 小时
发表于 2019-8-26 16:02:57 | 显示全部楼层
楼主输出个数要求大于65536怎么改呢?
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-8-26 16:12:41 | 显示全部楼层
tigerlee 发表于 2019-8-26 16:02
楼主输出个数要求大于65536怎么改呢?

变量控制的就发u64定义  其他的自己处理下分多次发
回复 支持 反对

使用道具 举报

12

主题

329

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2287
金钱
2287
注册时间
2016-5-21
在线时间
952 小时
发表于 2019-8-26 17:23:52 | 显示全部楼层
问问楼主,第6种方法一个STM32芯片可以控制几路独立的步进电机?是独立控制,互不干扰
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-8-26 17:55:33 | 显示全部楼层
xxssl 发表于 2019-8-26 17:23
问问楼主,第6种方法一个STM32芯片可以控制几路独立的步进电机?是独立控制,互不干扰

十几个吧, 一个dma定时器通道触发应该有10来个
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2019-7-30
在线时间
29 小时
发表于 2019-8-27 14:38:13 | 显示全部楼层
我用tim3座主,tim2作从定时器,怎么就不好用啊
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-8-27 16:17:51 | 显示全部楼层
KiwiChi 发表于 2019-8-27 14:38
我用tim3座主,tim2作从定时器,怎么就不好用啊

查表看需要开启隧道 用TIM_SelectInputTrigger 开启 估计你隧道没改吧
回复 支持 反对

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2019-6-28
在线时间
13 小时
发表于 2019-8-29 14:32:22 | 显示全部楼层
感谢分享
回复 支持 反对

使用道具 举报

7

主题

175

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1327
金钱
1327
注册时间
2019-7-11
在线时间
165 小时
发表于 2019-9-20 13:06:39 | 显示全部楼层
好东西 dd
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-7-8
在线时间
8 小时
发表于 2019-10-15 10:23:16 | 显示全部楼层
加精,清晰非常
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-3-26
在线时间
19 小时
发表于 2019-10-16 14:18:06 | 显示全部楼层
你好楼主。听说那一个DMA的方式,如果多路发的话,会占用很大资源是吗?
那一个定时器主从的,是不是6个定时器只能做三路这样啊
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-10-16 14:30:15 | 显示全部楼层
张朋 发表于 2019-10-16 14:18
你好楼主。听说那一个DMA的方式,如果多路发的话,会占用很大资源是吗?
那一个定时器主从的,是不是6 ...

主从一路需要两个定时器   定时器dma方式基本不占用资源吧,最好用这个方案
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-3-26
在线时间
19 小时
发表于 2019-10-17 13:29:10 | 显示全部楼层
本帖最后由 张朋 于 2019-10-17 13:36 编辑
nashui_sx 发表于 2019-8-26 17:55
十几个吧, 一个dma定时器通道触发应该有10来个

像那一个TIM3里面的通道1.3.4是不是也能单独控制输出独立的脉冲呢我按照我们的程序,第二个通道弄不出来,能给个思路吗


测试dma.rar

3.49 MB, 下载次数: 67

回复 支持 反对

使用道具 举报

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
发表于 2019-10-17 14:27:15 | 显示全部楼层
楼主可以说一下,你这个仿真波形怎么出来的呀?
回复 支持 反对

使用道具 举报

5

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2017-6-21
在线时间
67 小时
发表于 2019-10-17 14:56:33 | 显示全部楼层
干货帮顶
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-3-26
在线时间
19 小时
发表于 2019-10-17 15:00:31 | 显示全部楼层
各位高手,我前面的那一个通道的能给指点下吗
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-10-17 16:27:58 | 显示全部楼层
Julius007 发表于 2019-10-17 14:27
楼主可以说一下,你这个仿真波形怎么出来的呀?

20多块钱一个的逻辑分析仪,反正比仿真的好用多了,还能分析协议
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-10-17 16:35:11 | 显示全部楼层
本帖最后由 nashui_sx 于 2019-10-17 16:47 编辑
张朋 发表于 2019-10-17 13:29
像那一个TIM3里面的通道1.3.4是不是也能单独控制输出独立的脉冲呢我按照我们的程序,第二个通道弄 ...

引脚改改
TIM_SetCompare1   TIM_OC1Init   TIM_OC1PreloadConfig 这个函数改改就好了
回复 支持 反对

使用道具 举报

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
发表于 2019-10-17 18:11:12 | 显示全部楼层
nashui_sx 发表于 2019-10-17 16:27
20多块钱一个的逻辑分析仪,反正比仿真的好用多了,还能分析协议

哈哈  这么牛逼的利器,需要楼主让大家共享一下圣果,普天同庆一下!淘宝怎么搜可以买到?
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-10-17 19:45:06 | 显示全部楼层
Julius007 发表于 2019-10-17 18:11
哈哈  这么牛逼的利器,需要楼主让大家共享一下圣果,普天同庆一下!淘宝怎么搜可以买到?

淘宝逻辑分析仪 就好了 20多块的足够了
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-3-26
在线时间
19 小时
发表于 2019-10-17 20:23:02 | 显示全部楼层
nashui_sx 发表于 2019-10-17 16:35
引脚改改
TIM_SetCompare1   TIM_OC1Init   TIM_OC1PreloadConfig 这个函数改改就好了

我上一个传的附件这些我也改了大神,我用单个定时器的,可以做,而且都是独立的,像这同一个定时器里面的两个通道的就是调不出来
回复 支持 反对

使用道具 举报

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
发表于 2019-10-17 23:01:33 | 显示全部楼层
nashui_sx 发表于 2019-10-17 19:45
淘宝逻辑分析仪 就好了 20多块的足够了

找到了,看着真的非常牛逼呀!
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2019-10-7
在线时间
8 小时
发表于 2019-10-24 11:03:06 | 显示全部楼层
楼主 太崇拜你了  可否留个联系方式,我的QQ:1554401381
回复 支持 反对

使用道具 举报

0

主题

36

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
204
金钱
204
注册时间
2015-4-9
在线时间
72 小时
发表于 2019-10-24 11:30:08 | 显示全部楼层
非常感谢分享
回复 支持 反对

使用道具 举报

3

主题

38

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
269
金钱
269
注册时间
2019-5-17
在线时间
47 小时
发表于 2019-10-24 21:18:54 | 显示全部楼层
感谢楼主分享
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-10-25 00:40:45 | 显示全部楼层
wxhm2011 发表于 2019-10-24 11:03
楼主 太崇拜你了  可否留个联系方式,我的QQ:1554401381

群里@你回答你的问题了
回复 支持 反对

使用道具 举报

8

主题

28

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
219
金钱
219
注册时间
2017-8-9
在线时间
81 小时
发表于 2019-10-25 08:57:16 | 显示全部楼层
请问下能用来同时控制多路步进电机吗?
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-10-25 09:42:31 | 显示全部楼层
日落不眠 发表于 2019-10-25 08:57
请问下能用来同时控制多路步进电机吗?

都是单路,多路你改改就好了
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2019-10-7
在线时间
8 小时
发表于 2019-10-28 16:15:51 | 显示全部楼层
wxhm2011 发表于 2019-10-24 11:03
楼主 太崇拜你了  可否留个联系方式,我的QQ:1554401381

群里@你回答你的问题了

@nashui_sx  没有呀,是哪个群呢?我怎么没有印象呢。。。
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-11-10 14:22:55 | 显示全部楼层
张朋 发表于 2019-10-17 13:29
像那一个TIM3里面的通道1.3.4是不是也能单独控制输出独立的脉冲呢我按照我们的程序,第二个通道弄 ...

更新了个7  你看7吧
回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2019-11-13
在线时间
18 小时
发表于 2019-11-13 10:29:24 | 显示全部楼层
大神 有群吗  想加群跟着学习一下
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-11-13 12:04:25 | 显示全部楼层
醉梦226 发表于 2019-11-13 10:29
大神 有群吗  想加群跟着学习一下

没 都是能用的源码 对着学习学习就好了,不行官方群里问问
回复 支持 反对

使用道具 举报

12

主题

72

帖子

0

精华

高级会员

Rank: 4

积分
526
金钱
526
注册时间
2019-7-3
在线时间
164 小时
发表于 2019-11-13 13:16:51 | 显示全部楼层
要是有采集脉冲和周期的就太好了
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-11-13 13:25:11 | 显示全部楼层
回复 支持 反对

使用道具 举报

32

主题

883

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3990
金钱
3990
注册时间
2015-11-14
在线时间
541 小时
发表于 2019-11-13 16:10:42 | 显示全部楼层
谢谢哥们,先收藏
回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2019-11-13
在线时间
18 小时
发表于 2019-11-14 09:56:00 | 显示全部楼层
nashui_sx 发表于 2019-11-13 12:04
没 都是能用的源码 对着学习学习就好了,不行官方群里问问

好的  真是太感谢您了  帮了大忙了  思路很清晰,备注很详细。对我帮助很大很大。
回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2019-11-13
在线时间
18 小时
发表于 2019-11-16 20:07:20 | 显示全部楼层
本帖最后由 醉梦226 于 2019-11-17 12:59 编辑

大神 为啥我把方法六中定时器3修改成定时器2直接就没有波形了呢, 您能帮我看看吗,是不是还有什么遗漏的,所有的对应换了 用的定时器2通道2dma1的通道二(函数名字没有改,里面都做了相应的变化)。
代码如下
#include "tim_dma_pwm_pulse_output.h"
#include "delay.h"
u16 ZhanKongBi=0;
void TIM3_Dma_Pwm_Pulse_Output_Test(void)
{
    TIM3_Dma_Pwm_Pulse_Output_Init();
    delay_ms(500);                                 //延时一点,给下面的正式脉冲有个间隔,便于观察
    TIM3_Dma_Pwm_Pulse_Output(200-1,71,10,10);//周期=200*72/72000000=200us 占空比10%  10个脉冲
    delay_ms(500);
    TIM3_Dma_Pwm_Pulse_Output(100-1,71,20,10);
    delay_ms(500);
    TIM3_Dma_Pwm_Pulse_Output(1000-1,71,30,5);
    delay_ms(500);
    TIM3_Dma_Pwm_Pulse_Output(100-1,71,40,5);
    delay_ms(500);
}
void TIM3_Dma_Pwm_Pulse_Output_Init(void)
{
    GPIO_InitTypeDef         GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef        TIM_OCInitStructure;
    DMA_InitTypeDef          DMA_InitStructure;
    NVIC_InitTypeDef         NVIC_InitStructure;

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  //设置缺省值,这一步最好加上防止放到串口初始化后出问题
    TIM_OCStructInit(&TIM_OCInitStructure);          //设置缺省值,这一步最好加上防止放到串口初始化后出问题
    //TIM_ICStructInit(&TIM_ICInitStructure);        //设置缺省值,这一步最好加上防止放到串口初始化后出问题
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    //使能定时器3时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    //初始化TIM3
    TIM_TimeBaseStructure.TIM_Period = 65535;                    //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =0;                      //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;                 //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    //初始化TIM3 Channe1 PWM模式
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;            //选择定时器模式:TIM脉冲宽度调制模式2
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);                     //初始化通道1
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);            //使能TIM3在通道1上的预装载寄存器
    DMA_DeInit(DMA1_Channel2);                                                 //将DMA的通道1寄存器重设为缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&TIM2->CCR2;               //DMA外设基地址
    DMA_InitStructure.DMA_MemoryBaseAddr     = (u32)&ZhanKongBi;               //DMA内存基地址
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;          //DMA_DIR_PeripheralSRC:从外设读  DMA_DIR_PeripheralDST:从内存读
    DMA_InitStructure.DMA_BufferSize         = 0;                              //DMA通道的DMA缓存的大小,实测不加1少一个,应该是最后一个还没输出就中断关闭定时器了,+1就好了
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;      //外设地址寄存器不变
    DMA_InitStructure.DMA_MemoryInc          = DMA_PeripheralInc_Disable;      //内存地址寄存器递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度为8位
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    //数据宽度为8位
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;                //工作在正常模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;            //DMA通道 x拥有中优先级
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;                //是否开启内存到内存传输(关闭表示只有事件产生才传输一次数据,开启表示一直传输)DMA_M2M_Disable:非存储器到存储器模式(关闭内存到内存模式)  DMA_M2M_Enable:启动存储器到存储器模式(开启内存到内存模式)
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);                               //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
    DMA_Cmd(DMA1_Channel2, ENABLE);               //DMA1_3使能
    TIM_DMACmd(TIM2, TIM_DMA_CC2|TIM_DMA_Update, ENABLE);     //定时器3TIM_DMA_Update使能
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    DMA_ClearFlag(DMA1_Channel2_IRQn);                                         //清除DMA所有标志
    DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);                              //开传输完成中断
    TIM_SetCompare2(TIM2,0);       //通道1
    TIM_Cmd(TIM2, ENABLE);         //使能TIM3
}
void TIM3_Dma_Pwm_Pulse_Output(u16 arr,u16 psc,u8 zhankongbi_temp,u16 geshu)
{
    TIM_SetAutoreload(TIM2,arr);                               //设置重装载寄存器
    TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Immediate); //设置定时器时钟分频,立即生效
    ZhanKongBi=(arr+1)*zhankongbi_temp/100;                    //计算占空比
    TIM_SetCompare2(TIM2,ZhanKongBi);                          //占空比填入比较寄存器
    DMA_Cmd(DMA1_Channel2, DISABLE);                           //DMA失能才能设置
    DMA_SetCurrDataCounter(DMA1_Channel2,geshu+1);             //设置DMA长度,即脉冲数量
    DMA_Cmd(DMA1_Channel2, ENABLE);                            //开启
}
void DMA1_Channel2_IRQHandler(void)//脉冲输出完毕,关闭定时器
{
    if(DMA_GetITStatus(DMA1_FLAG_TC2))
    {
        TIM_SetCompare2(TIM2, 0);
        DMA_ClearFlag(DMA1_Channel2_IRQn);
        DMA_ClearFlag(DMA1_FLAG_GL2);
    }
}


回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-11-17 10:41:08 | 显示全部楼层
本帖最后由 nashui_sx 于 2019-11-17 10:56 编辑
醉梦226 发表于 2019-11-16 20:07
大神 为啥我把方法六中定时器3修改成定时器2直接就没有波形了呢, 您能帮我看看吗,是不是还有什么遗漏的, ...

这乱码看着头疼,最好用7 省定时器

#include "tim_dma_pwm_pulse_output.h"
#include "delay.h"

u16 ZhanKongBi=0;

void TIM3_Dma_Pwm_Pulse_Output_Test(void)
{
        TIM3_Dma_Pwm_Pulse_Output_Init();
        delay_ms(5);                                 //延时一点,给下面的正式脉冲有个间隔,便于观察
        while(1)
        {
                TIM3_Dma_Pwm_Pulse_Output(200-1,71,10,10);//周期=200*72/72000000=200us 占空比10%  10个脉冲
                delay_ms(10);

                TIM3_Dma_Pwm_Pulse_Output(100-1,71,20,10);  
                delay_ms(10);

                TIM3_Dma_Pwm_Pulse_Output(1000-1,71,30,5);
                delay_ms(10);

                TIM3_Dma_Pwm_Pulse_Output(100-1,71,40,5);
                delay_ms(10);
        }
}
void TIM3_Dma_Pwm_Pulse_Output_Init(void)
{
        GPIO_InitTypeDef         GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef        TIM_OCInitStructure;
        DMA_InitTypeDef          DMA_InitStructure;
        NVIC_InitTypeDef         NVIC_InitStructure;

        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  //设置缺省值,这一步最好加上防止放到串口初始化后出问题
        TIM_OCStructInit(&TIM_OCInitStructure);          //设置缺省值,这一步最好加上防止放到串口初始化后出问题
        //TIM_ICStructInit(&TIM_ICInitStructure);        //设置缺省值,这一步最好加上防止放到串口初始化后出问题

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);        //使能定时器3时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        //初始化TIM3
        TIM_TimeBaseStructure.TIM_Period = 65535;                    //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =0;                      //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;                 //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);         
        
                 
        //初始化TIM3 Channe1 PWM模式         
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;            //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
        TIM_OC1Init(TIM2, &TIM_OCInitStructure);                     //初始化通道1
        TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);            //使能TIM3在通道1上的预装载寄存器


        DMA_DeInit(DMA1_Channel2);                                                 //将DMA的通道1寄存器重设为缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&TIM2->CCR1;               //DMA外设基地址
        DMA_InitStructure.DMA_MemoryBaseAddr     = (u32)&ZhanKongBi;               //DMA内存基地址
        DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;          //DMA_DIR_PeripheralSRC:从外设读  DMA_DIR_PeripheralDST:从内存读
        DMA_InitStructure.DMA_BufferSize         = 0;                              //DMA通道的DMA缓存的大小,实测不加1少一个,应该是最后一个还没输出就中断关闭定时器了,+1就好了
        DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;      //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc          = DMA_PeripheralInc_Disable;      //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度为8位
        DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    //数据宽度为8位
        DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;                //工作在正常模式
        DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;            //DMA通道 x拥有中优先级
        DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;                //是否开启内存到内存传输(关闭表示只有事件产生才传输一次数据,开启表示一直传输)DMA_M2M_Disable:非存储器到存储器模式(关闭内存到内存模式)  DMA_M2M_Enable:启动存储器到存储器模式(开启内存到内存模式)
        DMA_Init(DMA1_Channel2, &DMA_InitStructure);                               //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器                  

        DMA_Cmd(DMA1_Channel2, ENABLE);               //DMA1_3使能
        TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);     //定时器3TIM_DMA_Update使能
        
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;   
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;      
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);               
        DMA_ClearFlag(DMA1_Channel2_IRQn);                                         //清除DMA所有标志
        DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);                              //开传输完成中断
        
        TIM_SetCompare1(TIM2,0);       //通道1
        TIM_Cmd(TIM2, ENABLE);         //使能TIM3
}
void TIM3_Dma_Pwm_Pulse_Output(u16 arr,u16 psc,u8 zhankongbi_temp,u16 geshu)
{
        TIM_SetAutoreload(TIM2,arr);                               //设置重装载寄存器
        TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Immediate); //设置定时器时钟分频,立即生效

        ZhanKongBi=(arr+1)*zhankongbi_temp/100;                    //计算占空比
        TIM_SetCompare1(TIM2,ZhanKongBi);                          //占空比填入比较寄存器

        DMA_Cmd(DMA1_Channel2, DISABLE);                           //DMA失能才能设置
        DMA_SetCurrDataCounter(DMA1_Channel2,geshu+1);             //设置DMA长度,即脉冲数量
        DMA_Cmd(DMA1_Channel2, ENABLE);                            //开启
}

void DMA1_Channel2_IRQHandler(void)//脉冲输出完毕,关闭定时器
{
    if(DMA_GetITStatus(DMA1_FLAG_TC2))
    {
                TIM_SetCompare1(TIM2, 0);
                DMA_ClearFlag(DMA1_Channel2_IRQn);                        
                DMA_ClearFlag(DMA1_FLAG_GL2);        
    }
}

回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2019-11-17 10:43:23 | 显示全部楼层
醉梦226 发表于 2019-11-16 20:07
大神 为啥我把方法六中定时器3修改成定时器2直接就没有波形了呢, 您能帮我看看吗,是不是还有什么遗漏的, ...

#include "tim_dma_pwm_pulse_output.h"
#include "delay.h"

u16 ZhanKongBi=0;

void TIM3_Dma_Pwm_Pulse_Output_Test(void)
{
        TIM3_Dma_Pwm_Pulse_Output_Init();
        delay_ms(5);                                 //延时一点,给下面的正式脉冲有个间隔,便于观察
        while(1)
        {
                TIM3_Dma_Pwm_Pulse_Output(200-1,71,10,10);//周期=200*72/72000000=200us 占空比10%  10个脉冲
                delay_ms(10);

                TIM3_Dma_Pwm_Pulse_Output(100-1,71,20,10);  
                delay_ms(10);

                TIM3_Dma_Pwm_Pulse_Output(1000-1,71,30,5);
                delay_ms(10);

                TIM3_Dma_Pwm_Pulse_Output(100-1,71,40,5);
                delay_ms(10);
        }
}
void TIM3_Dma_Pwm_Pulse_Output_Init(void)
{
        GPIO_InitTypeDef         GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef        TIM_OCInitStructure;
        DMA_InitTypeDef          DMA_InitStructure;
        NVIC_InitTypeDef         NVIC_InitStructure;

        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  //设置缺省值,这一步最好加上防止放到串口初始化后出问题
        TIM_OCStructInit(&TIM_OCInitStructure);          //设置缺省值,这一步最好加上防止放到串口初始化后出问题
        //TIM_ICStructInit(&TIM_ICInitStructure);        //设置缺省值,这一步最好加上防止放到串口初始化后出问题

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);        //使能定时器3时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        //初始化TIM3
        TIM_TimeBaseStructure.TIM_Period = 65535;                    //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =0;                      //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;                 //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);         
       
                 
        //初始化TIM3 Channe1 PWM模式         
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;            //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
        TIM_OC2Init(TIM2, &TIM_OCInitStructure);                     //初始化通道1
        TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);            //使能TIM3在通道1上的预装载寄存器


        DMA_DeInit(DMA1_Channel2);                                                 //将DMA的通道1寄存器重设为缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&TIM2->CCR2;               //DMA外设基地址
        DMA_InitStructure.DMA_MemoryBaseAddr     = (u32)&ZhanKongBi;               //DMA内存基地址
        DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;          //DMA_DIR_PeripheralSRC:从外设读  DMA_DIR_PeripheralDST:从内存读
        DMA_InitStructure.DMA_BufferSize         = 0;                              //DMA通道的DMA缓存的大小,实测不加1少一个,应该是最后一个还没输出就中断关闭定时器了,+1就好了
        DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;      //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc          = DMA_PeripheralInc_Disable;      //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度为8位
        DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    //数据宽度为8位
        DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;                //工作在正常模式
        DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;            //DMA通道 x拥有中优先级
        DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;                //是否开启内存到内存传输(关闭表示只有事件产生才传输一次数据,开启表示一直传输)DMA_M2M_Disable:非存储器到存储器模式(关闭内存到内存模式)  DMA_M2M_Enable:启动存储器到存储器模式(开启内存到内存模式)
        DMA_Init(DMA1_Channel2, &DMA_InitStructure);                               //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器                 

        DMA_Cmd(DMA1_Channel2, ENABLE);               //DMA1_3使能
        TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);     //定时器3TIM_DMA_Update使能
       
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;   
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;      
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);               
        DMA_ClearFlag(DMA1_Channel2_IRQn);                                         //清除DMA所有标志
        DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);                              //开传输完成中断
       
        TIM_SetCompare2(TIM2,0);       //通道1
        TIM_Cmd(TIM2, ENABLE);         //使能TIM3
}
void TIM3_Dma_Pwm_Pulse_Output(u16 arr,u16 psc,u8 zhankongbi_temp,u16 geshu)
{
        TIM_SetAutoreload(TIM2,arr);                               //设置重装载寄存器
        TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Immediate); //设置定时器时钟分频,立即生效

        ZhanKongBi=(arr+1)*zhankongbi_temp/100;                    //计算占空比
        TIM_SetCompare2(TIM2,ZhanKongBi);                          //占空比填入比较寄存器

        DMA_Cmd(DMA1_Channel2, DISABLE);                           //DMA失能才能设置
        DMA_SetCurrDataCounter(DMA1_Channel2,geshu+1);             //设置DMA长度,即脉冲数量
        DMA_Cmd(DMA1_Channel2, ENABLE);                            //开启
}

void DMA1_Channel2_IRQHandler(void)//脉冲输出完毕,关闭定时器
{
    if(DMA_GetITStatus(DMA1_FLAG_TC2))
    {
                TIM_SetCompare2(TIM2, 0);
                DMA_ClearFlag(DMA1_Channel2_IRQn);                       
                DMA_ClearFlag(DMA1_FLAG_GL2);        
    }
}

回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2019-11-13
在线时间
18 小时
发表于 2019-11-17 14:25:21 | 显示全部楼层
nashui_sx 发表于 2019-11-17 10:41
这乱码看着头疼,最好用7 省定时器

#include "tim_dma_pwm_pulse_output.h"

嗯嗯  乱码已经改了,找出问题来了,主函数里有个延时所以用逻辑分析仪一直捕捉不到。您说的有道理,已经改成用方法7做了。麻烦了,谢谢您。   
回复 支持 反对

使用道具 举报

0

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2018-11-30
在线时间
26 小时
发表于 2019-11-26 20:33:49 | 显示全部楼层
同样的配置,我用STM32ZET6无法实现一个定时器输出两路PWM 脉冲,只能输出两者中的一路,这是怎么回事?
回复 支持 反对

使用道具 举报

64

主题

446

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1032
金钱
1032
注册时间
2017-7-26
在线时间
275 小时
发表于 2019-11-27 08:47:29 | 显示全部楼层
补充一个   用SPI输出精准个数PWM
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2019-11-17
在线时间
2 小时
发表于 2019-11-27 22:38:38 | 显示全部楼层
搞个带T或S加减速算法的吧。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 08:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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