PWM控制电机速度的基本原理 PWM(Pulse Width Modulation),也就是脉冲宽度调制。 PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。 为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。) {! Z0 m8 B4 R- b2 }" I R1 d 1 U1 X- d- F w/ C/ v% J 8 V% n5 C5 f: S( c v) E 6 G& S4 o0 e- S" y 上图中的ARR是我们给定时器的一个预装载值,CCRx的上下变化是产生PWM波的关键。我们假设ARR大于CCRx的部分输出为高电平(即t1-t2、t3-t4、t5-t6),ARR小于CCRx的部分输出为低电平(即0-t1、t2-t3、t4-t5),则改变CCRx的值就能改变输出PWM的占空比。因此,想要控制PWM的输出波形,重要的就是如何设置ARR与CCRx这两个寄存器的值了。 - o5 [) e6 F' U/ k$ l" \! \ ) m( t% [5 t, ?! G" X, M STM32定时器中断 * T5 O! W- Y& D( z' E4 n$ ` 为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。 产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。) x2 k$ R; q2 n 原理简介 4 `0 e+ B4 I+ t 使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例: 解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为: ; t* {1 x' W, c1 z& U0 O8 u ' _- [6 s" t; |& n/ N7 x( p $ R \# \ g W% @4 V( f 10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。 4 r& _& r5 f* C s 8 u% D" {/ b: ?$ Q 再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。 ' ] [% J8 ]" ^; F9 F4 h' `- b5 v) w j/ |5 B8 u9 K ?! B. A$ t3 g1 ` $ I% R6 B+ [2 q r; m 看上面这行代码,中断优先级有抢占优先级和响应(即子优先级)优先级两种,抢占优先级即:若程序1正在使用CPU,这时如果程序2要求使用CPU,并且程序2的抢占优先级高,则CPU被程序2抢占;若两者抢占优先级相同,则就算程序2的响应优先级高于程序1,CPU也不能被抢占;若程序1正在使用CPU,程序2和程序3的抢占优先级等于或低于程序1,且程序2的响应优先级高于程序三,则待CPU空出后,程序2先运行,程序3最后运行。TIM3_IRQn是指定将要运行的中断处理程序号。“组2”是设置中断优先级分组的,这是因为寄存器提供了四位来设置优先级,组2代表的是前两位给抢占优先级,后两位给响应优先级。 + h; }$ `9 H1 u: \$ L) K4 T PWM模式、有效电平 . H% k9 t/ u; f$ ]5 ]' [, Z% I 前面介绍完中断,再说一下PWM工作原理。 假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。
J9 ]9 x& h1 @% \1 G 上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。 4 c) W4 e, D$ E5 m p+ L m# ]7 ^) u3 P& X7 w % A. o% r, }2 {3 X1 v; Y 下文具体分析上面的代码。' p7 D; z {7 m* U' P& |2 n5 G 前面4-6行是用来配置GPIO口的。7 ~" @1 @* x8 ^7 E $ g1 m2 A6 c; P0 \4 h& f# ~ " c9 o9 O: G' H, B+ s" n5 | 这两行就是我上门提到的设置定时器的频率和重装载值。 # m4 y7 }2 f$ u' K : `8 X6 ~0 S9 `+ T: r" f" {9 y2 L3 v & K6 G2 f" O8 g9 r 这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。: U. e+ t4 L$ F 6 _+ K) {) F6 ?7 D B. } 这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。 . b" X8 n% M8 J* Q+ f1 ?* A + N& v( c- X3 R' A 2 I- T) Y& H! Y+ Y9 |% e 这行代码只要对高级定时器进行设置,普通定时器无需设置。% S6 v* ^( W/ t* F+ V: m . |: y, I% K7 W . Q5 p0 j! _: e! M, o9 ~: i+ K 这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。 上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:' l% R; u* X( I5 [' @( Z1 i: r ) H- l+ }! Q- N S, S ! O. r3 }, ]- n J6 X: I & q+ U. ]" X. m5 J T PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。 预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。0 `+ K1 A2 v( ?$ q7 b. H0 m$ | ' @. x7 u9 Q+ S" f( S- t6 m8 ~$ W0 { |
HRTIM 指南
NUCLEO-U545RE-Q评测(2)运行环境建立
NUCLEO-U545RE-Q评测 (3)驱动OLED
NUCLEO-U545RE-Q评测 (6)FFT
NUCLEO-U545RE-Q评测 (5)DAC_DMA
NUCLEO-U545RE-Q评测 (4)ADC_DMA_转换
基于STM32 TrustZone 开发HardFault调试与处理
基于STM32在Keil中调试硬件错误的方法
基于STM32的PWM舵机控制经验分享
基于STM32外围电路硬件经验分享