定时器分类
9 P/ n0 W9 @6 t2 |' b( KG0系列有TIM1、TIM2、TIM3、TIM6、TIM7、TIM14、TIM15、TIM16、TIM17,它们区别如下图' Z) x. D' h* a
! S! R0 u Y2 {$ w2 L其中TIM1为高级定时器;TIM2/3/14/15/16/17为通用定时器,TIM2支持32bit;TIM6/7为基本定时器
4 F" O7 x% z- b0 a; m
/ }" p7 }( l! c2 S
3 @+ G/ r, ] T- Y& p' S4 C
, m! j, V. C) s0 e2 I% k, W/ g* a, g3 V- R& [
5 H8 h l! b9 I& g& N7 `
计时器时序图' D+ x) O9 D- `0 M+ D
TIM1,TIM2,TIM3支持(中央对齐)向上向下模式,方向在向上向下时发生变化,减少对电机的噪声干扰。
3 ^& t! u* c) T+ D% j. o. h+ q/ s& i
9 {1 i& `5 h: X& Z7 V
# T7 L! _6 f( P& _0 H
# B, w- f& u" S. @( j9 p: }
4 ]# v# G6 t4 C 基本PWM模式,边缘或者中央对齐模式
) X3 p# I% a$ b0 j# T8 v& n* m$ _5 a# z0 a: v* ?! l( z7 a
. [, B' {0 w4 r1 i1 L% Q% l
9 J L) {+ r: P8 E 非对称PWM模式
, v# _1 t. ?' @( P8 z, v7 t" W3 p! w. o/ T0 t- p
3 E7 q) r' [# E7 Z, j* q
! S" s7 P, {, B4 b) O三相组合PWM模式3 s* d8 _! N( @
4 W4 W6 r5 D; @$ d3 _$ R% G% S/ P9 K
1 |; f4 O1 f3 z* A+ S) T' ?2 D# f
; q6 S O+ O6 U8 o- W: | 可变频率pwm,由外部信号驱动。 逐周期控制的占空比。$ `9 K2 J& o) L+ V
8 u% y( b6 N0 O( b! g* s8 i3 w" y
5 i7 R; J5 g* |# p" [; o3 I8 P; E4 y" N" B. f
. P: n% z; d7 G7 M# P2 [8 q
3 F4 B) z4 s' {8 Z* i
TIM2定时器实验+ ~" c% a1 z5 H9 ~3 D
本次实验,我们选择TIM2定时器,通过设置预分频系数(PSC减去1)和计数器周期(ARR减去1)的数值,来控制整个定时器周期。让定时器周期进入中断,在中断函数中翻转PC6引脚电平,达到闪烁的目的。( l7 @: r$ Y! D5 C& V' V
/ F( W# e5 V) C4 g4 N L8 L$ \. D
如何计算定时器周期?
) H4 K; W7 C3 }3 t
' ]" Y6 T8 ]' C1、在时钟树中确定好TPCLK频率,这里已最大化频率运行;; T/ u+ b1 f R" h% M
; s# r1 Y2 U2 q6 `, h2 D: V/ W
9 j* E0 L6 I( Y/ L
5 G6 T) q# [9 Y, i- |* D) x2、确定CK_CNT的值 ,CK_CNT=TPCLK / PSC,为了便于计算我们一般都是将CK_CNT的值化为整数,
: G H- b" z4 G+ ~
% m& A7 u$ w; R) o+ z" q如 64MHz / 6400=10000Hz
: x* m3 v5 p0 ]) b
. b1 ~7 P" G5 ~8 T3、确定ARR的值,ARR=CK_CNT* t(s),
# e( P4 S/ E! V5 C R8 A, d: I* I/ F
如要1秒周期,10000Hz*1s=10000。
% d% R% O" x" J1 h- H6 r- L" l# ^ F
) ]- j& m: i5 }" p1 H实验代码
+ B! l* ~- ?( N' @% h- W1、新建芯片工程,"SYS"打开"Serial Wire"调试接口,"RCC"中HSE使用"Crystal/Ceramic Resonator";$ J2 V5 k B% g7 U3 b8 A
6 M: D9 E0 o0 E! X" R( ?, n& b) [2、在"Pinout view"中设置PC6为GPIO_Output,默认电平为low,开漏模式,不上下拉,速率为低
* R$ Q8 W ~6 z8 Q) F1 }& t$ t e* J2 A* s. C: l2 w
/ g: H- |4 D+ r
: P* Z- D) s2 [
' t4 `% L0 b3 c! c- P) X) J' }9 i; d z( u. p
3、设置时钟树,使用HSE、PLLCLK,HCLK为64,APB分频系数为1,APB时钟为64+ e: l( V2 U3 q9 Y3 l/ Q: V+ \
& o9 @; @5 O1 z5 g
) M+ |& U8 }3 m: x2 f4 n
4、 设置TIM2,在TIM2选项卡中,"Clock Source"选择"Internal Clock" E2 g' P: n7 q
* Z+ |7 R! B% q
5、下面"Counter Settings",Prescaler填入"6400-1",Counter Mode(计数模式)"Up",Counter Period填入"10000-1",其他参数默认值' d% x$ t5 J( i; x) L$ p- j
. w U& N' D1 |. C如想要1秒周期,ARR=10000,PSC=TPCLK / CK_CNT
4 W# V! J2 n7 a6 l# m9 t8 F, r0 ?) ^# [. x4 d" V$ G8 s
9 h& i E% v8 o( `) L
5 }) m; T5 `) D0 u; z: O6、在"NVIC"中,配置页面中找到"TIM2 global interrupt"使能,优先级选择"2", H+ R5 v1 {. L( S! a7 C
! _' T' Z- |7 D8 I4 i. @) G9 R+ R
9 O, ~' v. [. Y$ y& X S
# R; O, l+ N) H0 l! N7、在Project Manager中填入项目名,IDE版本“MDK-ARM V5”,在Code Generator打上勾,生成代码。" S. S, P9 V( a* p l1 m* x, Z
" \) `6 A2 F& y- u" m, {
8 J- m* z5 O, _; w; a& I
5 b* ?( Z! ?+ J: a8、在main.c文件,int main函数里面,在代码MX_TIM2_Init()定时器初始化后面加上定时器中断初始化函数
5 e0 m- z& e8 o. g9 ^
+ S7 B7 |: Z: x6 s$ @- int main(void)
1 e5 ?! ~4 O" N$ t4 w - {0 b7 X$ Y/ ?- @
- ** S4 ?- R; T% ~+ V, ?
- **: g* _' \) ^5 z/ \% M/ |& K" l4 k
- MX_GPIO_Init();9 O% S0 Z; A/ c5 x: }! T' u
- MX_TIM2_Init();
- C) ?3 W1 D- A# O. q* L - /* USER CODE BEGIN 2 */- c3 y' L+ A4 w. `; O1 b* @
- HAL_TIM_Base_Start_IT(&htim2); //初始化定时器中断
5 L6 w! d! P2 ^ - /* USER CODE END 2 */
' n: a3 d+ `8 h% T/ K: H& s6 p - **; r; O2 f ?2 z; z% v. m* Y$ S
- **
复制代码 : U6 u5 P+ D" t: j6 j8 m+ N
9、定时器中断函数原型为void TIM2_IRQHandler(void),里面调用了HAL_TIM_IRQHandler(&htim2),该函数有很多个中断回调函数,我们这个定时器更新中断,找到我们需要的函数HAL_TIM_PeriodElapsedCallback(htim),需要手动写这个回调函数,把一下函数复制到main.c文件中+ c& P" h) l3 d4 ]2 R' l
5 }4 D; x# B( }6 t$ `
- /*' }4 @9 K: k# J ~+ C% L0 i: f
- *stm32g0xx_hal_tim.c
7 t- K# W& r/ D4 }/ C1 J; @- j - */
1 t: k: w% U E& \1 |2 r0 B9 W - __weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)$ Q# d* w/ k! q5 p- ^9 ~ n
- {4 N E8 J- B; k5 o, Z
- /* Prevent unused argument(s) compilation warning */+ K. g. z' _& d; e/ _7 M
- UNUSED(htim);! v8 {; U1 C1 @1 Q: ] c
* Z/ q1 ]! {+ C, f6 [- /* NOTE : This function should not be modified, when the callback is needed,+ k9 O, p- {* z H- I
- the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
8 c5 i% u% k# O- X - */' q o" t8 E# q' P7 ^5 r/ @5 c: r2 u+ j
- }
复制代码 , w/ f3 Q4 I+ v* A' \
10、在int main(){}后面编写代码,编译,debug中勾上"Reset and Run"烧录固件,就能在开发板上看到输出闪烁。
% D9 o: {0 z% h# A8 d- N
* A2 l- z/ r0 R7 R; Z8 j- /* USER CODE BEGIN 4 */" I0 S9 N2 T7 W7 _, r/ _/ X4 _9 _
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim). c8 C+ S5 u: b' [) s( f5 K e
- {% u# {& B o: l8 `$ R
- /* Prevent unused argument(s) compilation warning */+ n" c' K* ~6 {6 e
- UNUSED(htim);
" w; k5 D- t! o) ?9 @5 y, u5 v - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_6); //只有定时器有中断,就翻转一次引脚电平
/ E$ T1 @, X( C1 e - }* w. V% O+ m7 F% g
- /* USER CODE END 4 */# |; d& T. k7 D
1 \( K# ]( A6 y! r' |
复制代码 6 O: [8 T1 o+ a! [: w
|