一.TIMER stm32框图
1 B5 O" C: U" H$ W/ g
9 a5 L8 C4 w" X; e0 g7 \. s
$ y2 O. i" \* N: U
+ E1 [; u/ n! V8 e如图:
! S5 y" X3 D. F1 U6 J
$ h+ L7 s. T2 w @ 1为时钟源: }+ g. o7 _& x2 F. K% B/ w$ n
- H8 a- t& H6 U1 j
● 内部时钟(CK_INT)
! b% d4 x3 H- B+ `6 J# }* r
1 L7 X5 f9 E% }- i● 外部时钟模式1:外部输入脚(TIx)( p# w8 q6 W! ] _$ F
3 K; J8 Y/ {2 C+ I
● 外部时钟模式2:外部触发输入(ETR)6 {9 y1 R$ a6 I3 |! j- N$ h% w3 A* w2 N! q
/ A# c8 t" u; e; `
● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以 配置一个定时器Timer1而作为另一个定时器Timer2的预分频器
3 H+ A, z# Y8 I' X7 h# y! y0 Z) Y2 P3 f) G$ k( G3 z
本历程采用内部时钟源,也就是以下的path
% i' d$ I+ `6 f, u* v# Y' |: {& R7 o2 r; M$ ^2 Q# b
此处需要注意一点:如果使用内部时钟,如果TIMER所在的总线是1分频,那么就是所在总线的时钟频率,如果不是1分频,那么时钟频率就是所在总线频率*2
3 v9 X( R0 x' w6 Q4 e$ o; m3 s1 w _' c, h
如系统时钟为72M,TIMER2所在APB1为1分频,那么TIMER时钟频率为72M*1
2 c; V; x' P4 ^# s
# H+ W1 e2 ]% f( }% S& P Z8 O3 C如系统时钟为72M,TIMER2所在APB1为2分频,那么TIMER时钟频率为36M*2
1 |0 T$ C. k, `. h& H: o8 z: K2 m
虽然都为72M,但是计算方法也不同,对于频率系数比较大的就能看出差异,例如stm32 f4078 H7 ~: ~1 y# S, h0 \
0 @( P. u. f# ?( J7 R
9 z. m! X$ _& C9 p# Z
! D8 S! h# O: [- _- b2为时基单元
* L4 N: t8 S( w- m
. A# F/ f# K: c- jPSC预分频数,还有重装载值,计数器CNT是寄存器根据重装载值和方向进行递增递减) q: o# R3 m+ K7 l) C
- w: O' ]8 n! m, C. x1 w2 c+ V! M" Z3为输入捕获,最基本的用途可以计算上升沿和下降沿的时间
9 V% J+ q3 M' @+ Q
; I6 w7 r8 v# @4为输出,即PWM,可以自己输出波形,控制占空比$ z8 @1 v8 n8 A) ^
6 t% z( }- ~; }6 F5 L! h
二.寄存器图
% u6 P1 u8 ?2 m; } [
+ T" ]" O3 G/ @- [9 \! f
* A0 r( v6 k5 M4 k' I
5 k' a L- _0 O% j% e( ~, q+ ETimer的寄存器比较多,本历程只是实现最基本的定时功能,输入捕获,PWM暂时不做讨论9 a& E; X; I( G8 Y2 N: b9 z
- a$ I; F) ~" [4 c
三.编程步骤# ~/ |6 Y8 p7 s) e
1. 使能TIMER时钟( S# f) U* `# A: Z3 o! `
6 l* Y8 M6 h& u2. 设置重装载值和分频系数
3 P- ^2 a( k- f# L }' g/ k) F; O
3. 计数器清零
0 `1 {7 A* B* ?" X$ T! @3 N5 x# v
4. 设置触发中断的方式* N( Q5 r2 H/ a6 K6 i- `3 y4 H
" x- F0 p' ^" G7 y) ]! ]8 G5. 使能TIMER
7 u6 N) X; {7 u0 F' t2 O) s( ^* ~6 J7 L0 s5 O
6. 使能TIMER NVIC中断) h" M5 w$ ]/ `( z
( C+ L6 J* r% o; e/ B
7. TIMER中断函数编写
8 n8 L+ J: |! q6 X( Z" S
. r- Y; D/ u7 ^# Z" ]$ M( h四.程序解析
1 w2 V; i w0 L' Y! Q, l( g4 L程序调用API* n2 e7 w8 `7 M( F* r
- [cpp] view plain copy
7 Q0 z" z+ X1 \7 v - Time2_Enable(19999,7199);
复制代码 调试如下. s! c/ F! a0 T
- [cpp] view plain copy6 K0 N/ V3 ?: u, Y) G& X% v1 m# I1 A
- RCC->APB1ENR = RCC_APB1ENR_TIM2EN; // 72M clock
复制代码 1.使能TIMER时钟,为72M,如图) Q" ~$ N) \8 B4 L
4 J/ s) x, K3 b4 S6 j% G
7 H5 z4 [) F/ Y* w5 N
- [cpp] view plain copy
0 f* g' k( {/ y, O; t1 V: l. G# A' ~# f - TIM2->ARR= arr;
, x/ @3 [6 V* A3 U3 Q3 _ - TIM2->PSC= psc;
复制代码 2. 设置重装载值和分频系数,如图" T0 [% S& R4 C
$ I9 B3 e& h" p9 g* i0 N( M3 O, p
I$ c/ G$ W$ p" j& W8 A# B
- [cpp] view plain copy
8 E. H0 @; G- }0 q1 p0 c: ? ] - TIM2->EGR = TIM_EGR_UG;
复制代码 3.计数器清零
% y# {# p8 ?: M' I) b0 J1 ]+ U# L- [cpp] view plain copy! T' I; a* T) m' N% ~) _, O
- TIM2->CR1= TIM_CR1_URS; , o" F( _( q. E# |
- TIM2->DIER= TIM_DIER_UIE;
复制代码 4. 设置触发中断的方式
* _/ U7 F. T) B: S* O
) W. o+ t' y" ^; T. g5.使能TIMER,如图:3 R o' {$ E3 P1 A5 M9 U) X. V1 Z
5 Z& @6 k- O' o8 Z$ e. O0 Q4 z
* f. B: L4 j- A1 x) @- [cpp] view plain copy
* U4 `2 r$ d" A# P$ ^, `! W( j - NVIC_SetPriority(TIM2_IRQn,1);
6 @" B1 V0 L9 V/ g _9 X3 a - NVIC_EnableIRQ(TIM2_IRQn);
复制代码 6.使能TIMER中断
8 v! k& b5 u7 Y9 C3 ?) q# B# T- [cpp] view plain copy
, Q) N1 o6 _' I9 x - voidTIM2_IRQHandler(void)
- Y9 z" F0 |, d, A* |8 H - {
1 H9 p5 h# ]7 f) r! Z, Z3 |* U - TIM2->SR &= ~TIM_SR_UIF; " K; f5 V) q' W6 z0 l6 \
- ) T) V/ c; [ [+ e
- printf("timeout! CNDTR=%d\n",DMA1_Channel5->CNDTR);
1 F0 `3 z* h+ b p- `# I4 T - }
复制代码 7.编写TIMER中断函数8 u# O) a& Y8 r* H/ N& ]+ M
程序运行图
( \! F N2 |1 \! f/ _" J
' `5 [& ]& _) _% S( a2 j: T每2s产生一次中断
, e1 B' u, A$ D
" j- Z3 {; f: L0 _2 q/ ^72M = 72000000HZ, x/ i- I, e# \; w+ h1 ]
3 {4 {, d) Z# G, a" V" ]分频7200
8 X ~. I# A: w: P8 ]& p7 Q1 p1 T U7 p6 r2 U
72000000/7200 = 100008 a& L8 M" H+ O6 }
8 |( P9 H, k% D所以一个周期是 1/10000) I$ {! Z! K: @' R
# F ^' q P* e5 D/ q8 x3 D9 E
然后出发中断时20000个周期,所以2s一次中断
* X2 A+ X! T( t; Y+ X/ O: @& s- d
+ x1 g3 \& q1 ~1 Y |