|
在永磁同步电机的控制中,需要对电机的三相定子施加一定的电压,才能控制电机转动。现在用的较多的是SVPWM(SVPWM的具体原理会在后面另写一篇博客说明),要想产生SVPWM波形,需要控制的三相电压呈如下形式,即A、B、C三相的电压是中间对齐的,这就需要用到stm32定时器的中间对齐模式了。 1、stm32的时钟树 stm32的时钟树如下图所示,简单介绍一下stm32时钟的配置过程。以外部时钟作为时钟源为例。HSE代表外部时钟(假设为8M)、SYSCLK为系统时钟,经过倍频器之后变成168M、SYSCLK经过AHB预分频器(假设分频系数为1)后变成HCLK时钟等于系统时钟SYSCLK,HCLK即AHB外部总线时钟,经过APB预分频器分出APB1时钟(分频系数为2,低速设备SYSCLK/4)与APB2时钟(分频系数为1,高速设备SYSCLK/2) HSE->SYSCLK->HCLK->APB1、APB2。 针对stm32f427的配置源码如下 - static void SetSysClock(void)4 K) j5 T3 q9 _4 P% C+ j
- {
% a$ h, F- F4 [6 G - #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx): h% |* q2 y3 t
- /******************************************************************************/
' q/ p0 h0 H: |" p" D - /* PLL (clocked by HSE) used as System clock source */
+ X" I& b3 O; M1 t - /******************************************************************************/
; e% U9 \: ?+ \; z$ { - __IO uint32_t StartUpCounter = 0, HSEStatus = 0;$ O5 [& `( B, q c! x) @( u
- , G$ c( v# Y# y
- /* Enable HSE */
Y7 ]! l3 t2 ]7 D- x - RCC->CR |= ((uint32_t)RCC_CR_HSEON);2 }& x, s9 H/ w
- / K( m) t- s8 x9 `: H. I6 }2 a, _( y
- /* Wait till HSE is ready and if Time out is reached exit */
; O8 O; b% [0 h: \ - do8 ~; N( o8 F! G! T+ J, P5 m4 H, v! N% b
- {% S+ v0 i$ Q/ B% }$ f
- HSEStatus = RCC->CR & RCC_CR_HSERDY;
1 M/ _; O7 U- d& a% z+ { - StartUpCounter++;
) ^# f* i8 D' S" M - } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));( e5 z- k8 D! n
- 1 W, W1 G H$ k8 M9 }+ F
- if ((RCC->CR & RCC_CR_HSERDY) != RESET)
; r9 V, V' V1 g; f* s3 D3 c5 u - {9 c5 j, ]1 y0 w+ ?
- HSEStatus = (uint32_t)0x01;
. c& l2 |* J. E/ ]# @ - }0 U+ g( j7 t1 X
- else
/ M6 T% _( Q% k( o, ]7 ` - {
( o& m* h4 z; |# Y5 M - HSEStatus = (uint32_t)0x00;
: s/ O$ ^3 [ w( U+ G, W; ^1 u - }7 A6 V! v+ k' U; w0 ?% J# ]
2 j) N' h( D+ z/ t% X! o8 \- if (HSEStatus == (uint32_t)0x01)
+ }) k1 s0 K' ~, Z$ w - {7 C3 ]* m- Y6 Y0 c0 T+ g K
- /* Select regulator voltage output Scale 1 mode */
& j3 Z; \# k# K$ |* W* O" r1 _ - RCC->APB1ENR |= RCC_APB1ENR_PWREN;; |" f c# y9 p$ |5 I
- PWR->CR |= PWR_CR_VOS;
9 q. c% j+ }9 u( J7 L) K y6 O( O - - w8 w9 i/ x& u- Q! D
- /* HCLK = SYSCLK / 1*/
( i% G" o5 B- x+ g+ C - RCC->CFGR |= RCC_CFGR_HPRE_DIV1;//AHB时钟
X( @+ @& X8 F# j+ V5 {$ W - * V c/ t+ q) I5 ~$ m
- #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) * {4 `/ Z% D% \$ Y; S, f1 |- k
- /* PCLK2 = HCLK / 2*/1 W, w1 o. F/ \% J E M E
- RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2时钟
/ M# z8 E- i' \5 d - ! l$ J$ y8 ?+ k% s8 h' F8 v5 s
- /* PCLK1 = HCLK / 4*/
6 S0 L- ^: Z& e8 D; l9 b/ X - RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;//APB1时钟
5 u' J; F" w* i$ t8 m - #endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */6 N% C D! X9 B+ g9 u, B
1 X. `# @! X: f- / N8 w' c1 j* L6 b* C+ Z8 J
- /* Configure the main PLL */
% T5 Q$ G J2 n! T& @6 C! s* | - RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
6 R, u, v# g/ L4 z* S - (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);5 a1 ?8 ?6 o: i$ c* q# V3 m, l! {
- : O/ O8 S% [3 r$ [2 ?0 N5 p8 Y, {
- /* Enable the main PLL */
' ]; x9 ^5 v& r$ n" h0 v - RCC->CR |= RCC_CR_PLLON;7 a# }1 Z5 Y+ R: I" ^0 y* A
- 9 N. i; {; h, p
- /* Wait till the main PLL is ready */
& W2 a: A. D- I* r# n - while((RCC->CR & RCC_CR_PLLRDY) == 0)
; {& A' [* g1 M% x0 o - {
( [) I, A6 h6 [; o) F( F% s - }
$ {4 m5 H) B8 ]2 L% S _3 e6 L5 A - : J6 ^4 r2 x( v
- #if defined (STM32F427_437xx) || defined (STM32F429_439xx)
, P& ?: O2 H4 n9 e& Q& g - /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
_( v: z9 `# y - PWR->CR |= PWR_CR_ODEN;
7 ^- a8 E; M+ _) K% n& f& k7 Z( X - while((PWR->CSR & PWR_CSR_ODRDY) == 0)" j8 ^$ s2 f& b- J
- {! U# n$ o" U) T7 e2 j1 T" n9 [6 u
- }
. a7 j! E1 ~/ A" Q$ Z - PWR->CR |= PWR_CR_ODSWEN;7 T$ N% z8 l# Y9 d- _$ \
- while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
9 N- s K! C# x - {& \2 C. @; z2 z
- } ! h: u7 X0 B# v* _- _: f
- /* Configure Flash prefetch, Instruction cache, Data cache and wait state */1 V: \: Q, e5 h2 @. \$ q8 \
- FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
B, F( d8 c# W! }3 H' b$ b - #endif /* STM32F427_437x || STM32F429_439xx */
; C- s: f9 j6 R# e+ `$ f - ( }8 v0 W- N" [' I
- 0 d+ H, F2 l3 ]- r
- /* Select the main PLL as system clock source */
/ k+ S" H+ H3 i% U - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
/ _" p$ |; P6 Y6 s* k) t - RCC->CFGR |= RCC_CFGR_SW_PLL;
& ?# k! i- }/ C- }) G3 A/ C/ r
+ M, c" c5 \: k7 e+ f/ V$ @- /* Wait till the main PLL is used as system clock source */
) b( S0 P: o! x' q: u5 W, ^! n - while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);. A% \, ]( Y* d2 j
- {, p6 B/ |7 L& O3 b0 W
- }
& m- u. s3 R$ \% p3 g - }
- \$ @4 I/ D- X1 O7 Q - else) j X6 d) j/ Q4 n8 t. @" q
- { /* If HSE fails to start-up, the application will have wrong clock
0 t# q/ @# B4 x" W6 R - configuration. User can add here some code to deal with this error */
W$ ]$ G1 T% i2 X2 b - }
$ @. ^% V1 l! q+ ~" N/ x/ u - }
复制代码 5 n% a R3 b* I7 k, l! h
2、stm32定时器的时钟 stm32定时器分为高级定时器(TIM1与TIM8)、通用定时器(TIM2-TIM5、TIM9-TIM14)、基本定时器(TIM6、TIM7)。不同的定时器使用不同的时钟。 其中TIM1、TIM8、TIM10、TIM11使用的是APB2时钟,而其余定时器使用的是APB1时钟。 在stm32手册中有这么一段话
) c6 M! y3 u& ~* x8 S7 l
根据前面RCC配置可以知道TIM1、TIM8、TIM10、TIM11使用的时钟频率为SYSCLK,其他定时器使用的时钟频率为SYSCLK/2 3、stm32定时器1的中间对齐模式 对齐模式的图示如下图所示,可以看到在中心对齐模式下产生的PWM波形的周期比实际计数周期要大1倍,所以假设要使用中间对齐模式,并且需要产生的PWM波频率为20K,那么对应的定时器时基应该设为40K。
- U7 o/ z/ ^- k
$ E7 _% e) n" X( h0 a0 K( q
在SVPWM波的产生过程中使用的是定时器1的3对互补的PWM通道,它的配置如下 - static void TIM1_Configuration(void)
3 m4 a! j, o4 p2 |9 d8 a' b3 _! f - { ( J/ w# q6 a8 A, N$ M
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;! u. Y' `( H3 X' x6 H6 K- U
- TIM_OCInitTypeDef TIM_OCInitStructure;: B) x5 L% N* D6 n
- TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
9 a7 r8 Y& { N+ F( R/ A U4 ^ A -
/ X. [; {: g2 D* E" q - RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//使能定时器1时钟
) j ? r! f7 E7 k$ U - " g7 Z& T1 g4 U" O. v" C ^
- Time1_Period = (SystemCoreClock / 40000 );//定时器频率为APB2频率的2倍=HCLK 自动重装载为40K,最大值为4200
! \ C# l1 I8 x0 M% l! V -
6 r; t, U% b4 B- g, ~7 C; ]. |; N - Limit_Pluse_Max_Value = Time1_Period * 0.95;
" l) e& O0 M' {. v- l( ] - " c6 ^! ]/ p v( j1 W& ? O
- /* TIM1 Peripheral Configuration */ $ @ ? K. w4 Z
- 4 F+ X7 r* k0 p6 W0 m, |+ {
- TIM_DeInit(TIM1);1 N: @! r# n( L( Q8 [
- 9 C& u$ J+ W$ c+ G. I' a- [- h
- /* Time Base configuration */- ]' r2 [$ Q* G& M3 K
- //配置定时器的计数方式为中间对齐方式,所以产生的PWM波的频率为20K
6 `% R4 \2 v( e% h; i( a' _- N - TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
. M1 f; I/ W% E. l6 A5 _# R - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;//TIM_CounterMode_Up;TIM_CounterMode_CenterAligned1
$ n: J2 F ^- j: \/ Q - TIM_TimeBaseStructure.TIM_Period = Time1_Period - 1;//PERIOD;//定时器时基40K
9 n. q7 v& S: Q1 k - TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;7 ?) d4 l. A7 q( L1 ]& e
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;
+ J8 e3 y9 T' \* i: U - 8 g5 o6 a6 X% d7 B0 J& V" V/ B2 b
- TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);7 z+ o4 t( N0 M8 q6 b+ _7 \$ W
: i | E2 E2 q; E( t' z- /* Channel 1, 2,3 and 4 Configuration in PWM mode */9 q. P. {* _/ ?& `
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - V7 u3 o0 x3 [% O
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; , J1 e) a- l) M; a E+ o; q b$ o5 L
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; * J, F' ? X4 W5 a5 @4 \ C
- TIM_OCInitStructure.TIM_Pulse = Time1_Period / 2;//CCR1_Val; //占空比50%
' u- H% F9 i6 d - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM_OCPolarity_Low;TIM_OCPolarity_High;3 L( F9 l" y. M% i* T* ^( A
- TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;//TIM_OCNPolarity_Low;TIM_OCNPolarity_High; $ C* M0 L* |3 q
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;//TIM_OCIdleState_Set;
# u M6 b1 n0 o9 y - TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
* m0 ]! u8 \+ S4 s - + Z$ t$ ^" ^- d9 @ a
- TIM_OC1Init(TIM1,&TIM_OCInitStructure);
; d% d. f, C0 l3 {% {5 Z - 4 D+ H& q& |# J5 q
- TIM_OCInitStructure.TIM_Pulse = Time1_Period / 2;//CCR2_Val;//占空比50%% _2 W: n) }$ A: X& q! h$ B9 B
- TIM_OC2Init(TIM1,&TIM_OCInitStructure);
: `$ ]% T! b+ {4 e9 ]5 t3 F! I - ! G0 G8 H. W' d1 N- H: w
- TIM_OCInitStructure.TIM_Pulse = Time1_Period / 2;//CCR3_Val;//占空比50%# k. ~2 T/ A' f! m5 d
- TIM_OC3Init(TIM1,&TIM_OCInitStructure);
: w& b2 D' C+ k - $ v3 ^' M! g2 H! R( g/ k( N; W
-
8 Q! \( S4 k& U! x0 W% W* t - // /* Channel 4 Configuration in OC */3 M+ }7 ]3 P$ z+ A9 v
- // TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;3 k; I' }9 \) D$ j! [& b
- // TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;/ W- s" }7 X7 E! ^& {0 c2 W
- // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;9 ^/ h! s1 ?" r2 i9 \) X9 j q
- // TIM_OCInitStructure.TIM_Pulse = 4000;//Time1_Period / 2; //1500;//PERIOD - 1; 3 O. w; z% \" v5 R& A
- //
: @# v/ N( J5 Y# x0 ^: D3 H - // TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; % R! |5 W, d: B# I2 {- b
- // TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; ' K! F( h) }3 O& Z5 x- R
- // TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;8 w. l- ~- N9 R4 [2 S
- // TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
) c W+ j! V- N! J. Q - 6 t1 D7 G+ ^& L: }& j
- // TIM_OC4Init(TIM1,&TIM_OCInitStructure); * X; G8 ]6 Q- s
-
- T! H8 x8 U" f* A8 `0 t* f2 w - /* TIMx->CCMR1的bit3设为1:输出比较寄存器预装载使能 */ // PWM占空比改变只在更新事件时生效
5 q0 R. i) }. N' {* M - TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//A相
% o9 d* ~' [# C. p -
, h$ J D/ @% @- g6 c: n8 I - /* TIMx->CCMR1的bit11设为1:输出比较寄存器预装载使能 */ // PWM占空比改变只在更新事件时生效3 }" ~& U6 k3 Z7 I9 R7 S& c
- TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);//B相 z! V \9 x) T0 P1 `% I3 d- _
-
. \ U7 o9 z# T+ h. ~( Y( C7 v+ ? - /* TIMx->CCMR2的bit3设为1:输出比较寄存器预装载使能 */ // PWM占空比改变只在更新事件时生效" A$ |( U7 {: W3 O w5 c/ f
- TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);//C相. C+ k9 a3 Z3 Q F4 x0 s
5 F1 a+ q/ V5 w7 F w2 f3 V- // TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);//电磁铁
+ c ?+ N4 S l2 C* W& p8 T. H -
0 Z' C) u6 P2 y' r" ~& ~3 q/ | - /* Automatic Output enable, Break, dead time and lock configuration*/6 n: k6 y3 H) R
- TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;8 I' C A- B8 h, v$ o
- TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;/ E8 }, b! G% ?7 d% d- k
- TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; + q$ t- b7 C+ n- f/ _' q3 Z
- TIM_BDTRInitStructure.TIM_DeadTime = 50;) L* t( ^ ^7 l. R i, Y7 b" `
- TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;//TIM_Break_Enable;
/ u& d R% Y- H: p/ E- t$ W* D - TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
, ?6 ?: W/ N, P8 g( T - TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;//TIM_AutomaticOutput_Enable;
* F0 _' C/ P4 P
! w6 b( h0 d# B5 e- c/ s7 x2 @3 ]+ @1 D2 |- TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);( J' O0 M# X4 W/ q/ i1 d: @
- 1 y1 t: g- Z( a7 n/ J
- TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);% G ~5 ^+ @6 U/ g
- - E; o2 I/ a" p# O
- /* TIM1 counter enable */
* z2 |- {6 m6 y, V9 q/ o- R5 T/ E - // TIM_Cmd(TIM1,ENABLE);
" |+ P: D/ P5 b# {* j ?" }+ r/ W
: @4 E) i+ U% _1 K/ Q( L- /* Main Output Enable */
4 M8 ~, F' B, x, H! t; U - TIM_CtrlPWMOutputs(TIM1,ENABLE);//由于使用中间对齐模式,PWM频率为20K
: O6 i3 [1 }+ \5 t! W+ h) x - # [: ^3 `& d; d. R* {/ c3 Z! ?
- //TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//定时器1的溢出中断
0 ]5 { B! f1 W' P - }
复制代码
, l( ]8 P; B7 p0 A5 a; O& |0 h" K
, c* O5 J) T+ e& I5 I; H$ j: | |