|
输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能。STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等. 例如:我们用到TIM5_CH1来捕获高电平脉宽,也就是要先设置输入捕获为上升沿检测,记录发生上升沿的时候TIM5_CNT的值。然后配置捕获信号为下降沿捕获,当下降沿到来时,发生捕获,并记录此时的TIM5_CNT值。这样,前后两次TIM5_CNT之差,就是高电平的脉宽,同时TIM5的计数频率我们是知道的,从而可以计算出高电平脉宽的准确时间。 首先TIMx_ARR和TIMx_PSC,这两个寄存器用来设自动重装载值和TIMx的时钟分频。 再来看看捕获/比较模式寄存器1:TIMx_CCMR1,这个寄存器在输入捕获的时候,非常有用;TIMx_CCMR1明显是针对2个通道的配置,低八位[7:0]用于捕获/比较通道1的控制,而高八位[15:8]则用于捕获/比较通道2的控制,因为TIMx还有CCMR2这个寄存器,所以可以知道CCMR2是用来控制通道3和通道4(详见《STM32参考手册》290页,14.4.8节)。 这里用到TIM5的捕获/比较通道1,我们重点介绍TIMx_CMMR1的[7:0]位(其实高8位配置类似)。 再来看看捕获/比较使能寄存器:TIMx_CCER; 接下来我们再看看DMA/中断使能寄存器:TIMx_DIER,我们需要用到中断来处理捕获数据,所以必须开启通道1的捕获比较中断,即CC1IE设置为1。 控制寄存器:TIMx_CR1,我们只用到了它的最低位,也就是用来使能定时器的; 最后再来看看捕获/比较寄存器1:TIMx_CCR1,该寄存器用来存储捕获发生时,TIMx_CNT的值,我们从TIMx_CCR1就可以读出通道1捕获发生时刻的TIMx_CNT值,通过两次捕获(一次上升沿捕获,一次下降沿捕获)的差值,就可以计算出高电平脉冲的宽度。 使能捕获和更新中断(设置TIM5的DIER寄存器)' d7 c: f1 Q$ s0 o" s
因为我们要捕获的是高电平信号的脉宽,所以,第一次捕获是上升沿,第二次捕获时下降沿,必须在捕获上升沿之后,设置捕获边沿为下降沿,同时,如果脉宽比较长,那么定时器就会溢出,对溢出必须做处理,否则结果就不准了。这两件事,我们都在中断里面做,所以必须开启捕获中断和更新中断。 - void init_tim2_cam(u16 psc, u16 arr, u8 way, u8 dir). {5 {& q; o; q
- {* a5 F8 ]: L# c" p, o L% ~$ A
- RCC->APB1ENR |= 1 << 0; //使能定时器2时钟+ L& Q) S( G4 U/ m4 L! v+ ?& t. p6 L+ D) r
- RCC->APB2ENR |= 1 << 2; //使能PortA; j+ U1 X+ L! ^$ I" n# K! M( {& {
" g w; H- A" ~+ A- switch (way)* [! c( N7 d( A* e# a3 i5 Z5 a
- {
3 a' Y; y) P; g5 v( M* P - case 1:) r& T- \5 G/ N. p, d% Q
- GPIOA->CRL &= 0xfffffff0;
; I+ R b- |3 V0 \ - GPIOA->CRL |= 0x00000008;
* L. I9 W" X2 M) d% w+ N - break;& @; O) V0 k6 C6 O3 |
- case 2:
R; k3 l* V$ \0 i* L( C - GPIOA->CRL &= 0xffffff00;
) z6 M/ j" u; V( D1 n( g - GPIOA->CRL |= 0x00000088;$ {' @+ P' M# G* h
- break;
" \& p2 \% A: v5 X7 z/ {. x# w7 W - case 3:9 L9 o+ Z8 } p3 s+ e0 u0 v4 v! m9 {9 G7 P
- GPIOA->CRL &= 0xfffff000;0 T; P3 I5 h4 {) u; B3 q1 a" u! x
- GPIOA->CRL |= 0x00000888;2 `1 y: r5 P; H$ S
- break;, ?( Y& C7 q) J: Z7 _
- case 4:4 x2 i" R: q% E# V4 s* Y' u4 F
- GPIOA->CRL &= 0xffff0000;! e8 V% H- i/ i! v' B$ u9 w
- GPIOA->CRL |= 0x00008888;3 O/ T% l7 B, [3 E
- break;
1 b/ ]6 ?, d1 V& }. Q T - }
, [- r. _$ q' J6 l9 S+ I6 i - + {( l! b( \2 c$ w4 o% {/ r2 B3 y( {( |
- TIMER->PSC = psc;
' I1 c0 _- q# j& P6 k' B - TIMER->ARR = arr;% Q! Y3 I- v$ M4 x, j
- 9 q8 v& `5 K( [8 e! u
- switch (way)
- l( ^: x6 [7 f$ j/ S% G) { - {
$ j2 z1 o; a4 ?/ ?0 [2 b - case 4:
0 T9 X" ~1 c+ f# W2 `9 w - TIMER->CCMR2 |= 1 << 8;: r. t8 N) ~$ w
- if (dir == 0)+ n- a; J' p6 A/ S
- TIMER->CCER |= 1 << 13; //下降沿捕获6 J9 b r. C3 v
- else+ L8 s( H" i2 y* y( u! y Z% S
- TIMER->CCER &= ~(1 << 13); //上升沿捕获
3 X5 R* r+ r9 m( c N - TIMER->CCER |= 1 << 12; t$ g" G2 z3 E I% R0 o; q
- TIMER->DIER |= 1 << 4;
5 ~3 A, |# W5 @# H2 Q - case 3: //CCR3 PA2
0 A! p4 |. i; C7 \, K - TIMER->CCMR2 |= 1 << 0;) Z v) V) [: t9 }9 J1 W
- if (dir == 0)
, |* m" _; a [/ O - TIMER->CCER |= 1 << 9; //下降沿捕获
, D0 E% G3 `# ^: f - else
4 c+ K% x$ E4 i - TIMER->CCER &= ~(1 << 9); //上升沿捕获3 } M, `3 S* m* W' f6 Z- Q4 N% O9 i7 |
- TIMER->CCER |= 1 << 8;& K7 u: g! {3 w% B7 ~8 W5 ~! |
- TIMER->DIER |= 1 << 3;( V$ O# C! u8 M
- case 2: //CCR2 PA1" _/ @6 f0 ~/ c( b
- TIMER->CCMR1 |= 1 << 8; //CCR2配置通道方向:输入
4 O6 t1 P9 K! x3 H" o - if (dir == 0)
, }; y" n* z3 x& N3 u- Y _& Y# o( N - TIMER->CCER |= 1 << 5; //下降沿捕获9 B8 t8 m" r6 j
- else6 h4 m5 Z/ }4 z" }& |9 E
- TIMER->CCER &= ~(1 << 5); //上升沿捕获
- {1 W* f, ~; ?1 R5 w$ V - TIMER->CCER |= 1 << 4; //CCR2通道捕获使能
4 P0 Y @9 L5 R& Y% ~" d2 W) N( Q - TIMER->DIER |= 1 << 2; //CCR2通道允许捕获中断! e7 C( ^5 H6 E9 n
- case 1: //>CCR1 PA0
6 k6 ~0 P3 O! r% W* W - TIMER->CCMR1 |= 1 << 0; //CCR1配置通道方向:输入
& A6 P2 F) B& s8 V' j- Y4 C8 m - if (dir == 0)
- [! R6 Z4 y& x5 y" J( C: Z- {9 g0 b - TIMER->CCER |= 1 << 1; //下降沿捕获6 o' ] |# N1 {/ R# m0 i* G
- else
0 R7 q0 W6 w, P - TIMER->CCER &= ~(1 << 1); //上升沿捕获8 q* H# [$ p; @( B
- TIMER->CCER |= 1 << 0; //CCR1捕获使能
9 q5 `; R1 E! y4 Y" ? - TIMER->DIER |= 1 << 1; //CCR1通道允许捕获中断
( h9 ~& H+ x; T: ]0 t3 t - break;
! f7 ~/ }% a: w - }
" O9 ]$ t9 A! P8 A( L+ L6 c+ e; b; Y' ` - TIMER->DIER |= 1 << 0; //允许更新中断& a. F/ c: J: a% y# W( o
- MY_NVIC_Init(1, 2, TIM2_IRQChannel, 2); //中断+ m0 v; ^3 {9 l( N; R5 M3 U
- TIMER->CR1 = 0x01; //使能定时器
1 h( {! U/ j4 G( k - TIMER->SR &= ~(1 << 0);
; X5 S$ o Z+ Q: L* k' H, \& V( T - }
复制代码 + p" \3 ]. Z; _ a% X' ^
|