一.TIMER stm32框图
$ {9 z9 H) ~" r0 G; h8 x
" c' K3 o- p) Y) R
6 c; E: I" K0 Z: H, V# G M7 W$ `( o% b, o/ B& c1 a: @8 u) n' U
如图:" A, I' a+ ^$ f7 T/ ?* i' a2 a K( J
3 O9 |7 B$ i& t1 M. O! q1 S 1为时钟源8 J4 q- P3 Z$ M* k" O) [
' \( `5 E- L* t; z6 a( L6 H
● 内部时钟(CK_INT)
/ C. n# V7 K! t# i# m0 ?* B+ T+ J1 X1 Z: P+ ^/ s4 M
● 外部时钟模式1:外部输入脚(TIx); ^3 |0 k4 S& r, l2 r" U3 n/ R
% {* L% G b# J2 Q3 O: `● 外部时钟模式2:外部触发输入(ETR). L! w+ {. F# n' p7 Y
+ a: e% ~" w. W+ `9 }6 @● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以 配置一个定时器Timer1而作为另一个定时器Timer2的预分频器5 r5 F C# Y% Z2 F: R
3 o" ?1 x e, C9 L; f' x* B. n( j/ X
本历程采用内部时钟源,也就是以下的path- z. x0 Z/ _7 S( D: Y
# j) _$ c' I! j; }: q, V, B
此处需要注意一点:如果使用内部时钟,如果TIMER所在的总线是1分频,那么就是所在总线的时钟频率,如果不是1分频,那么时钟频率就是所在总线频率*25 \1 z5 }! ?, X( m
; W0 f5 U& m# G. N: E6 r: a& I
如系统时钟为72M,TIMER2所在APB1为1分频,那么TIMER时钟频率为72M*1- X1 Y4 o1 Y& \1 `1 _/ H
1 Q6 r/ b0 W+ ~1 v+ W1 @
如系统时钟为72M,TIMER2所在APB1为2分频,那么TIMER时钟频率为36M*2
1 C6 O' s7 p& \7 I5 u& k0 O) l! a5 Z3 o, y6 e
虽然都为72M,但是计算方法也不同,对于频率系数比较大的就能看出差异,例如stm32 f407
" Z7 F# M2 `6 M, x: I9 k, A5 x9 t# L% j; _
2 b/ N: U$ a$ W2 [0 A
" q' [% {4 d( T2为时基单元- ]/ v; s0 i2 z$ o- Q9 I* P
) Q1 d; m: z t. w' }PSC预分频数,还有重装载值,计数器CNT是寄存器根据重装载值和方向进行递增递减1 d! m: r/ X- b# d& d7 O) i# g/ h
2 X$ O, s: j) C$ M, [5 ^$ I" {
3为输入捕获,最基本的用途可以计算上升沿和下降沿的时间
?1 l7 a, V- [2 W' _5 \' K6 }$ j4 e( M3 ]; y( g3 b; ~
4为输出,即PWM,可以自己输出波形,控制占空比
2 }2 ~ Q, x3 a
" t' h& M: Y/ i+ C3 _1 T; y: c二.寄存器图2 I6 M6 d9 t" B! Z4 _4 [0 N3 e
* L' J% B1 I+ v
. u: {! {# o3 L t/ Z
E* g' b% R& v( c$ F* ?4 @, TTimer的寄存器比较多,本历程只是实现最基本的定时功能,输入捕获,PWM暂时不做讨论3 q- K$ S, ], x
; C X5 ]! U4 C& P O6 a" m三.编程步骤. f& {' z& k' T% x
1. 使能TIMER时钟
. x$ [& ~: F0 o* C p9 V Z0 Z; m$ i# g" B2 N
2. 设置重装载值和分频系数+ m% W5 B/ O4 {* d3 |
# a) z( n( n7 m1 n1 X- m
3. 计数器清零
1 H3 l4 ~6 ]& E* X1 ^- r7 o* z0 d+ w6 B" K$ q5 h# `" A
4. 设置触发中断的方式( n8 C n+ E7 h, r
$ w O& T+ k& |
5. 使能TIMER$ b, O& B7 }3 D2 s5 i: c0 N" J
7 _( o: ?/ _1 U8 j J" @# ?; H2 e$ m
6. 使能TIMER NVIC中断
8 `2 g% X. ~8 K) _
; E( P, C2 W+ C v% S( z( `7. TIMER中断函数编写5 O( @2 I% N5 T6 J2 F6 C
" c* s+ I, D- i( \' \四.程序解析. m" F/ f. R% K" E% E0 _
程序调用API
. z! ~3 G# \6 t5 ^9 w/ n% o7 s- [cpp] view plain copy) T! y: v2 o/ z1 P6 O5 e
- Time2_Enable(19999,7199);
复制代码 调试如下
& b2 `) L4 z6 B; I/ m( `- [cpp] view plain copy0 v, v* J* |" q' I) H2 i8 D/ Y
- RCC->APB1ENR = RCC_APB1ENR_TIM2EN; // 72M clock
复制代码 1.使能TIMER时钟,为72M,如图
& P+ r7 n' X+ E- A8 ~
( F& S5 I7 p) l- u }5 d
# }; S# G: c; n- [cpp] view plain copy
( N% z4 K4 \" I* j, W - TIM2->ARR= arr;
' X+ h! {3 e: N. H# ? - TIM2->PSC= psc;
复制代码 2. 设置重装载值和分频系数,如图
$ \: u" P, @8 \. I$ I9 o- ]% o
* H5 Q/ |+ e& x
7 A% g% y& p0 { n( Q4 w @- [cpp] view plain copy
* M" L9 }* y. r* l5 \4 T - TIM2->EGR = TIM_EGR_UG;
复制代码 3.计数器清零3 g8 i k8 |) X% R" Q/ ?- b
- [cpp] view plain copy+ @/ ?; j$ f% z8 r, Y! D, j! n6 v0 |
- TIM2->CR1= TIM_CR1_URS; 3 Q0 u+ ^9 y1 e1 N
- TIM2->DIER= TIM_DIER_UIE;
复制代码 4. 设置触发中断的方式+ m& Y8 k4 \7 w; @6 S9 `8 I+ }
/ t- K: p' i* B2 X: Z6 m2 j
5.使能TIMER,如图:9 ]1 q$ y) I Q7 k6 D0 l
1 P+ N8 L6 T) w6 f1 a
& l( ~. u% b% v* j1 K) N7 D' B- [cpp] view plain copy
$ E4 t8 c6 ?% `& O9 U- D- A - NVIC_SetPriority(TIM2_IRQn,1);
$ {9 ?. }( g( B# l' Q+ a - NVIC_EnableIRQ(TIM2_IRQn);
复制代码 6.使能TIMER中断
; `5 i# ]2 `7 _5 j- [cpp] view plain copy6 f0 S$ ^5 h; Y c7 |
- voidTIM2_IRQHandler(void) $ }* @: w; B) ]* d) O, A/ n
- { 8 G' E, T( f: x: [& U
- TIM2->SR &= ~TIM_SR_UIF;
5 ?) H- |1 w( M -
3 e& w$ Q3 B8 H9 W5 J: P/ ?) F - printf("timeout! CNDTR=%d\n",DMA1_Channel5->CNDTR); ) R: \" {, W( w0 [2 m
- }
复制代码 7.编写TIMER中断函数$ \) H- f* T8 b' Q, D# @
程序运行图. e- p' b8 w0 X' i
3 c: T4 Y4 ~; O& f每2s产生一次中断. A0 C4 Q4 Q4 g
: `3 i2 }8 ~; z72M = 72000000HZ6 l8 a9 v" v$ k/ Y0 k
: k8 n7 E, K: e8 ]9 y
分频72004 u# [* i& F0 e7 w1 H+ _0 O
6 z J7 Y1 F% h72000000/7200 = 10000
( O" b( w$ X( Y+ x0 [0 B; M8 [3 x+ t( G$ u) e; V
所以一个周期是 1/10000$ g7 @- ^/ V1 n
( M6 J2 n1 p' b9 \9 y然后出发中断时20000个周期,所以2s一次中断, e$ m6 P4 l. J
! O( }7 ?: ~3 j, d. C- t, c |