OpenEdv-开源电子网

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

初学者分享今天通过按键改变频率的方波的思路

[复制链接]

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
发表于 2017-5-4 17:39:52 | 显示全部楼层 |阅读模式
本帖最后由 晓枫 于 2017-5-4 21:08 编辑

      菜鸟一枚,刚花了几个小时才做出通过按键改变频率的方波。
      先说实现的要求:输出100HZ到10KH的方波,通过1KHZ以下按键以100HZ为单位调节。 1KHZ以上以1KHZ为单位调节。
      叙述一下整个思考的过程,开始以为是个简单的代码,就打算直接在main函数里面通过delay()函数改变LED0来实现方波的改变,的确可以实现一次方波的准确,但main函数里指令很多,每个都要消耗时间,通过按键调解时就发现是不可能以100HZ变化的。所以想到了用定时器产生方波,在中断函数里面改变LED0的电平,然后将按键放在main函数里面,以为这样就可以了,但还是不行,最后想到因为中断初始化只执行一次,按键的调节是没有作用了,改变不了中断服务的时间,最后想到将按键检测放到中断函数里面,按键一次初始化执行一次,在按键里面进行方波频率的修改,最后达到了要求。
     菜鸟知道是很简单的程序,但也一定会有初学者不太懂,拿出来给大家分享,也希望大神有好的方法和思路分享出来。感激不尽!
     下面是STM(mini)版的代码。
      分频方波.zip (3.08 MB, 下载次数: 249)
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-4 19:47:53 | 显示全部楼层
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-5-5 09:29:55 | 显示全部楼层
不错,很好,谢谢分享!
回复 支持 反对

使用道具 举报

0

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2017-5-5
在线时间
20 小时
发表于 2017-5-5 18:12:22 | 显示全部楼层
简直不能看,就不能把定时器初始化的函数里的入口参数拿出来,在主函数里赋值吗
回复 支持 反对

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-5 20:04:17 | 显示全部楼层
dawang 发表于 2017-5-5 18:12
简直不能看,就不能把定时器初始化的函数里的入口参数拿出来,在主函数里赋值吗

你试一下在主函数里面赋值,就会只调用一次,就算按键也变不了方波频率,如果可以,你分享出来,谢谢
回复 支持 反对

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-5 20:04:43 | 显示全部楼层
八度空间 发表于 2017-5-5 09:29
不错,很好,谢谢分享!

共同学习
回复 支持 反对

使用道具 举报

0

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2017-5-5
在线时间
20 小时
发表于 2017-5-7 21:11:27 | 显示全部楼层
晓枫 发表于 2017-5-5 20:04
你试一下在主函数里面赋值,就会只调用一次,就算按键也变不了方波频率,如果可以,你分享出来,谢谢

原子的代码PWM调灯光的那个
回复 支持 反对

使用道具 举报

3

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2016-7-27
在线时间
19 小时
发表于 2017-5-7 22:01:13 | 显示全部楼层
对于初学者来说,最重要的就是不断给自己提出新的要求,然后在实现的过程中不断深化自己对知识的认识,我觉得楼主在这点上做的很好。
我想提两点建议:
1. 你应当保持一个好的代码风格,大括号、缩进和空行的风格要统一且易于识别。
2. 用定时器产生PWM,可以直接调用TIM_SetAutoreload、TIM_SetCompareX函数修改ARR(autoReload)和CCR(cuptureCompare)寄存器的值,来修改频率。具体可以参见参考手册定时器的PWM模式原理
回复 支持 反对

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-7 22:39:45 | 显示全部楼层
Ecrhon 发表于 2017-5-7 22:01
对于初学者来说,最重要的就是不断给自己提出新的要求,然后在实现的过程中不断深化自己对知识的认识,我觉 ...

非常感谢你的建议,当初只想到了出结果。没考虑那么多,以后一定会注意的。
回复 支持 反对

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-7 23:06:52 | 显示全部楼层
dawang 发表于 2017-5-7 21:11
原子的代码PWM调灯光的那个

我刚才看了PWM的原理和代码。
TIM_SetCompare1(TIM1,led0pwmval),你应该说的是这个函数,这个函数的确在while里面,会循环执行,但它是改变的是占空比,不是频率。
TIM1_PWM_Init(899,0);//不分频。 PWM 频率=72000/(899+1)=80Khz
这个函数是用来改变频率的,它在while外面,只执行一次,也只能执行一次,初始化多次执行会使频率发生很大的误差,我把按键放在定时器中断函数里面就是因为按键后定时器初始化只能执行一次,按键的时候频率也是有个抖动的,等大概一秒频率才会稳定,只要不再次按键就不会再一次初始化。
这样就保证了频率的改变的准确。
你要是有其他方法希望你也能提出来,共同学习。
回复 支持 反对

使用道具 举报

3

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2016-7-27
在线时间
19 小时
发表于 2017-5-9 00:59:04 | 显示全部楼层
晓枫 发表于 2017-5-7 23:06
我刚才看了PWM的原理和代码。
TIM_SetCompare1(TIM1,led0pwmval),你应该说的是这个函数,这个函数的确在 ...

初始化多次不会造成频率的误差,你看看具体的init函数就可以知道,库函数仅仅是封装了对寄存器的操作,多次初始化无非就是多次操作寄存器,频率误差是不会发生的。
初始化TIM_OCInitTypeDef类型的TIM_Pulse成员设定的是定时器的CCR值;TIM_TimeBaseInitTypeDef类型的TIM_Period成员设定了定时器的ARR值。以向上计数模式为例,PWM是这样产生的:
使能定时器并打开PWM输出后,系统时钟会向定时器不断发送脉冲。定时器有一个预分频器,他能够将系统的时钟频率除以某个数,然后把得到的结果作为定时器自己的频率。在这里我看注释说没有分频,那么定时器的时钟频率 == 系统时钟频率。定时器每收到一个时钟脉冲,就会在计数器寄存器上加一,并跟ARR、CCR的值进行对比。如果与CCR值相等,那么马上(不等这个计数周期完)就根据你设置的PWM模式改变输出电平;如果与ARR值相等,那么在计完ARR值后,计数器清零并重新开始计数。给个公式吧,设你的系统时钟频率为f_s,分频为d,向上计数模式中,ARR值为a,CCR值为c,PWM占空比推导如下:(假设CNT<CCR时为低电平)
定时器时钟频率 f_t = f_s / d;
两次计数器清零之间的间隔,即PWM周期 t = (a + 1) / f_t = (a + 1) * f_s / d;
低电平时间 t_low = c * f_s / d;
高电平时间 t_high = (a + 1 - c) * f_s / d;
占空比 d_r = t_high / t = ((a + 1 - c) / a) * f_s/d;
这就是PWM产生的原理,你需要多快的频率,算一下周期,然后用我说的 TIM_SetAutoreload 和 TIM_SetCompare1 或 2 或 3 或 4(不同的数字改变定时器的不同通道)改一下相应寄存器。至于可能涉及到的影子寄存器等相关概念,等你学到定时器的时候再做了解也不迟。
回复 支持 反对

使用道具 举报

0

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2017-5-5
在线时间
20 小时
发表于 2017-5-9 18:14:08 | 显示全部楼层
晓枫 发表于 2017-5-7 23:06
我刚才看了PWM的原理和代码。
TIM_SetCompare1(TIM1,led0pwmval),你应该说的是这个函数,这个函数的确在 ...

静下心来慢慢学,加油
回复 支持 反对

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-9 21:54:25 | 显示全部楼层
Ecrhon 发表于 2017-5-9 00:59
初始化多次不会造成频率的误差,你看看具体的init函数就可以知道,库函数仅仅是封装了对寄存器的操作,多 ...

好的。找时间一定认真看你说的,谢谢。
回复 支持 反对

使用道具 举报

7

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-4-13
在线时间
36 小时
 楼主| 发表于 2017-5-9 21:54:44 | 显示全部楼层
dawang 发表于 2017-5-9 18:14
静下心来慢慢学,加油

共同努力
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-8-21 11:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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