你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F103输出互补PWM波

[复制链接]
STMCU小助手 发布时间:2022-3-22 13:00
STM32F103单片机定时器自带互补PWM波形输出功能,利用定时器输出比较模式,不仅可以输出互补的 PWM波,还可以设置输出方波的起始相位和死区时间。
6 H+ E! L8 }9 O( i. z
& w4 |, t" S5 Q- \       下面就总结一下如何实现PWM互补输出。3 O4 L' ]: k, x) `* M# A

2 [6 e% q0 T3 |) f" s7 ~
  1. / s4 R. h+ W, R" I
  2. void TIM1_PWM_DeadtimeInit( u16 arr, u16 psc, u16 ccr1, u16 ccr2, u16 deadtime )
    , p% Q2 i3 `! m9 x8 T: D  z# m$ r
  3. {
    . [8 r2 w# B* y' P3 w  R
  4.     GPIO_InitTypeDef GPIO_InitSturcture;) ?! z" u; I" c! {6 u7 m% T$ R: U0 |
  5.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;1 k6 c& U# _; s0 m1 _. x# v
  6.     TIM_OCInitTypeDef TIM_OCInitStructure;
    0 @' K. J: Z2 I! i
  7.     TIM_BDTRInitTypeDef TIM_BDTRInitStructure;+ H3 P$ z* A) _/ R( e1 h

  8. . b3 ^# K) L% m  m; S
  9.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );
    ' C# f7 ^2 {! P  `; G& G% g
  10.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
    ( [! y9 ?+ ^+ p* _( ^

  11. , f4 R& x# y5 ^1 Q" u, N" S
  12.     //TIM1 互补PWM CH1->PA8  CH2->PA9  CH1N->PB13  CH2N->PB14" I" R& w7 J0 j
  13.     GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    ! C$ s0 y' E: t( z& @0 r
  14.     GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
    3 A9 {0 L1 y% X4 J2 Z! `! W% A; |" Y
  15.     GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;* v) O# n# {2 c+ P% l$ h
  16.     GPIO_Init( GPIOA, &GPIO_InitSturcture );
    9 _: c5 ]9 l* }- w* B
  17. . q2 F' D6 b* ]/ S( _
  18.     GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
    9 i( @. u3 Z0 x: r9 v7 H- b* h
  19.     GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;8 p& G( x7 H. a0 W
  20.     GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
    % k% V- y2 }9 Q8 y0 Q; {
  21.     GPIO_Init( GPIOB, &GPIO_InitSturcture );! m) i2 C/ C; x$ p; q9 C; H' H
  22.     //定时器设置
    / `# R9 [' r* }) R* m# ~) J
  23.     TIM_TimeBaseInitStructure.TIM_Period = arr;
    4 x7 |9 V' A5 _% ~, E
  24.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;2 ]2 o- B, m# |8 I# a  }, i. o
  25.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;4 \8 U; z+ }8 D% ~  S6 g. J  ]
  26.     TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x00;
    2 f" k  a  v# n4 w
  27.     TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;% P" A" j& Q$ B4 c) E( B
  28.     TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure );, I/ X0 e) `0 v* O/ x" z
  29.     //通道1 捕获比较模式设置
    ; x( D: c" f" d. ?  F# x/ Z/ Q
  30.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;                                 //翻转,当 TIMx_CCR1=TIMx_CNT时,翻转OC1REF的电平
    7 H( t! }  Q, V9 W) g. ]: ?5 G
  31.     TIM_OCInitStructure.TIM_Pulse = ccr1;                                                        //100
    # u5 w+ Y4 _( J& p5 B
  32.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                //CCER的CC1P,输入/捕获输出极性
    , ]8 \; \. _" n) ~$ j/ B& k
  33.     TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
    ) y1 f( B; Q4 I& q
  34.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;         //CER的CC1N,输入/捕获输出使能4 n# q' ^' I6 c) a
  35.     TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;* @  K" Z0 W0 s+ n
  36.     TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //OIS1位
    - u  i4 j! @- w% W3 G- S7 W
  37.     TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;  //CR2的OIS1N位,当MOE位0时,输出空闲状态位OIS1N./ b; i4 e, g: r1 o% k4 t
  38.     TIM_OC1Init( TIM1, &TIM_OCInitStructure );9 Q7 S; R% P: g2 r/ d. b
  39.     //通道2 设置
    3 _1 w$ s# @' j; e$ \* K% Q! G& ?/ x1 ~2 c
  40.     TIM_OCInitStructure.TIM_Pulse = ccr2;                                                        //316
    ) ?0 {) I1 _/ \7 c( W
  41.     TIM_OC2Init( TIM1, &TIM_OCInitStructure );
    0 c% p1 D1 q2 p  I! v/ p
  42.     //刹车和死区设置
    6 K. n3 T8 C! R- J9 f
  43.     TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;         //OSSR:运行模式下“关闭状态”选择1 j" b$ r& y4 U+ L( W& d
  44.     TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;         //OSSI:空闲模式下“关闭状态”选择  ^8 b& x! s8 ~! J! g: e! w' S/ G
  45.     TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;                         //锁定设 置,级别为1' B4 g% [! u' F1 C4 x- D" _
  46.     TIM_BDTRInitStructure.TIM_DeadTime = deadtime;                                        //死区延时时间8 c! }8 a8 J- [4 |* Y/ K7 E
  47.     TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;                        //禁止刹车输 入2 T* x! y) ^0 _6 [+ I! t
  48.     TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;                 //刹车输入极性
    - J4 [5 r" A2 T$ {
  49.     TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; //自动输出使能
      e  p4 v, N6 L/ n7 c, C" {
  50.     TIM_BDTRConfig( TIM1, &TIM_BDTRInitStructure );
    : |- \4 p# m* Y3 _* H8 n: r
  51. 1 t+ O& T- ?1 D  K2 {  K
  52.     TIM_CtrlPWMOutputs( TIM1, ENABLE );
    & ?) Q& _0 B4 a; j1 Z% o; W( Y
  53.     TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Enable );
    6 X6 [  Q4 [* x0 _- U$ ^3 B/ b
  54.     TIM_OC2PreloadConfig( TIM1, TIM_OCPreload_Enable );
    : t5 ]  v; M4 e5 V
  55.     TIM_ARRPreloadConfig( TIM1, ENABLE );
    ; ~/ s! c% `; m% w6 `5 U" q
  56.     TIM_Cmd( TIM1, ENABLE );
    # X" `6 f" n0 t4 |* q- i
  57. }
复制代码
. `0 L9 U0 {8 h

2 ~  d4 _2 v3 [首先初始化IO口,这里使用的是定时器1的通道1和通道2。  e* Z, H+ t! J7 |! n
# a  I8 s! j3 @+ h0 ^
FDVE[VTF`WT2(]]2O~QY8YT.png , i# R+ p* d7 H* p, S
: V/ b/ @2 C+ t$ [0 O. _; Z
PA8为定时器1通道1输出口,PB13为定时器1通道1互补输出口。
8 v, w2 }" x! @: p7 T4 B9 Z. P6 ?
( B3 }$ R( y9 p9 T0 H3 p% Q, v- `; {2 pPA9为定时器1通道2输出口, PB14为定时器1通道2互补输出口。
: [: ]9 b: |0 X; U: U% c# s
. b$ I' e3 }+ @5 q0 [下来初始化定时器,参数arr设置输出PWM波频率,psc设置定时器时钟分频系数。定时器初始化之后,设置定时器工作模式为输出比较模式,其中参数 ccr1 设置通道1的输出方波起始相位,参数cc2设置通道2输出方波起始相位。参数 deadtime 设置互补PWM波形的死区时间。初始化结束后启动定时器。, N5 p+ s9 K1 Y
- J/ @2 j, G+ O, b- P! t4 I2 {
关于输出比较模式的详细说明参考STM32输出比较模式和PWM模式 比较这篇文章。7 `8 x  b# k% m4 @* r& A
6 f* [, v+ {7 L" |; W! ]/ h5 r
下面看主函数设置5 u  I1 X4 r% ]9 x3 K
' U1 [8 ^" ]5 J2 K
  1. #include "sys.h"
    2 n7 w$ s  J; x1 r
  2. #include "delay.h"6 |, i2 d+ ^; I# t9 S! x
  3. #include "usart.h"
    0 p  |- K6 J5 S" Z4 j
  4. #include "led.h"
    $ a8 N( E. V' H: K' s  ^% H
  5. #include "pwm_ch_chn.h"0 o- R$ S% ?' ~7 p( Q  H& P
  6. // LED0  PA8  LED1 PD2
    8 V! C6 A* [) J- @* I# d
  7. int main(void)
    $ J6 d( j0 z- N+ R1 d3 r0 H0 ~
  8. {: \/ m) R* Q/ `: d& T
  9.     delay_init();       //延时函数初始化# j8 t0 S* a7 P6 k9 E% Y3 }$ `( i
  10.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);" C) R8 f$ ?1 r; ^0 Y8 ^$ [
  11.     LED_Init();
    ; ]# i9 o" z# ^( l) t  M1 s
  12.     LED0 = 1;* ~' u" j" J3 U3 K4 ?
  13.     LED1 = 1;# P* ]  `/ c" i" R1 d
  14.     delay_ms(500);, M( o  i; d( n, E. m
  15.     LED0 = 0;
    ; g3 _- }8 o# ~3 Q/ {
  16.     LED1 = 0;
    . {; V& t& a) X$ b+ i
  17.     // Tout=(719+1)*(0+1)/72M=10us   72M/720=0.1M=100K        
    9 x% B' }& u; k6 m3 C+ Z
  18.     TIM1_PWM_DeadtimeInit(719,0,0,0,72);//50KHz
    8 T5 X( C- Y* v" l4 w" B( ?, o
  19.     while(1)
    / h3 q8 \; S4 T: G; ]
  20.     {
    9 G! W$ T& ?. D4 e- c+ d: `- l
  21.                
    6 L. t; S) V3 Y! G1 i$ _6 F
  22.     }
    2 }9 \9 Z' u) M* i: o3 q
  23. }
复制代码
( H4 R" Z* L5 [  ]& U- E9 T
# l! q6 Q4 o9 A
主函数中设置自动装载值为 720,分频系数为0,那么输出方波频率为 72MHz / 720 = 0.1MHz,也就是输出波形频率为100K,由于此处用的是定时器的输出比较模式,所以输出频率为计算值的一半,所以实际输出方波频率为50KHz。ccr1值设置为0,也就是定时器1通道1的输出波形起始相位为0,ccr2的值为0,所以起始相位也为0。死区时间设置为72,为周期数的1/10,也就是2us。
. {; C) J( `2 ?2 n5 l' a( [3 @& d( `& O  J
2 X) c9 B3 q! B( j! Q0 i7 p下面看一下输出波形
2 B: v/ ?/ t+ o3 Z7 G: ^
6 U* X0 R0 V' ^ FKKWZY1O@QDH7@)UJKK6I3C.png
$ x, j0 @. d) n! Y( d2 J
1 z: @/ ^% p  Y3 I" T黄色为 TIM1_CH1波形,绿色为TIM1_CH1N波形,这两个波形是通道1互补波形。
( s' ^4 u- h0 l+ P0 q& a
1 N7 N" F! C. p  F- r9 h蓝色为 TIM1_CH2波形,粉色为TIM1_CH2N波形,这两个波形是通道2互补波形。& e5 m8 B4 f8 b& L
' _$ G; n0 v% F" s( k! c
黄色和蓝色波形起始相位相同。
6 c2 F3 j7 \& y2 C; [2 z, Z0 {0 l! c' M  R6 b3 G3 V
Y0)Z[WR$NZ0J7QK[B@4FC6P.png
% }8 t7 Q0 R9 \
$ h: Y1 y& ^& j% g  G" K& S7 J原波形和互补波形死区时间为1us,刚才计算的死区时间是2us,这里为什么是1us?因为死区时间是上升沿时间差+下降沿时间差,是两个对称的区间。这里只测了一个区间,所以为总时间的一半。5 `$ ~4 z" q! |5 K" X: p

/ \' m, N$ d" A9 L下来同时改变ccr1和ccr2的初始值,看看输出波形相位有没有发生变化。
+ Z% \/ }2 G& b/ X9 \
  1.         TIM1_PWM_DeadtimeInit(719,0,72,144,72);//50KHz
复制代码

, }) h. z4 v8 m& b$ }% f输出波形为% i: F, t/ }# X, p( g9 O: r8 }2 a

! z. ?: K$ N+ \' Y5 @; T; S OYC(ZM1SZKGD(1J`9XI0NGU.png
- L1 D, ^) K: ?$ a6 _8 I# |' T& j" D* _# B3 W
蓝色波形下降沿比黄色波形下降沿滞后了一点,说明起始相位已经发生了改变。
% [( z% P  b4 ~! ~0 |+ S! ]9 ?2 g$ N# K% P# E) ^6 K4 P& K
W10PLLMS`L}JDW0ZOO5[FLU.png
% J3 ]0 C! H1 C4 t& M
% w9 R8 z( D+ l5 g0 @/ E放大波形后可以看到,下降沿滞后的时间为1us,和死区时间相同。# f1 c. ?. o- ~& P4 L& A) W
( {2 y% R9 w5 c

8 J  t9 C4 x$ N" N) D' W
赞 收藏 评论0 发布时间:2022-3-22 13:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版