使用芯片:STM32F103RCT67 X# C2 o$ ` L, @) M
0 U2 X6 c: }, Q, s
思路:定时器设置为1MHZ的计数频率,定时计数器增加一就是增加1us
9 P- @* a2 A1 j; o% L# }; h; q5 \% V" B8 E% ?* N+ J
① 首先设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;& U8 O$ ~, _) X# i$ r3 o
② 然后切换为下降沿捕获,捕获下降沿记录此刻的时间计数值;; ]) s2 P3 Z# U/ j
③ 最后设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;6 y2 ~& A. l6 Y5 c0 H
; s9 B' X2 x; P- Q, e6 Q+ p4 `! @对于16bit定时器,最大可计数0xFFFF,也就是65535us,那么:高电平持续的时间 = 定时器溢出计数 * 0xFFFF + 当前计数值
+ A# e8 p" l- ~6 i# A对于32bit定时器,最大可计数0xFFFFFFFF,也就是4294.967295s,这个时间足够测量脉冲宽度的了,那么:高电平持续的时间 = 当前计数值- f! X8 E4 k5 i @! U
, @9 R$ I& p% ?7 l- {
高电平持续的时间 = ② - ①
& [3 X1 Q n/ u9 {) g; L4 P周期 = ③ - ① A, E: _2 g+ B0 V# V9 v/ q# l8 m+ X5 u
, n |( p. Y/ n; g% r2 L6 s4 ~6 x5 P定时器配置
3 L( a; [- D: [7 b/ N设置定时器2的计数频率为1MHz,输入捕获使用通道一,也就是PA0引脚,将PA0引脚设置为下拉模式,目的是为了在空闲时间保持信号稳定:* B$ S+ k# y4 c6 I& a' L0 `
* d" p4 U) M6 x. l8 Z3 M
' W, h4 n* U. F
0 l7 G% j( V6 y
9 d# u; W0 i5 a$ v
: X; n8 k( ~# s* Z5 P% Q, N! W( e2 K
6 J7 j+ G1 B9 Q
( }& i' v* w* J( p中断分组设置0 `$ f. s0 E" p3 y, D# `. @
# v' S% `# Z5 @$ E# C
% M1 n! }0 I. C' Q) s( Y! u; g$ z/ T' E8 v, [
代码配置
5 V' f9 z' I1 Ytim.c中添加如下代码:
5 F r" R% g, V) y1 a$ W% [
L# ?0 I! c3 \7 S2 l" F
$ m( j/ m P( N& S2 y5 h) Y- __IO uint32_t TIM2_TIMEOUT_COUNT = 0; ///< 定时器2定时溢出计数% \7 {! L! W# Z- o. w3 b
- uint32_t TIM2_CAPTURE_BUF[3] = {0, 0, 0}; ///< 分别存储上升沿计数、下降沿计数、下个上升沿计数
9 [0 _/ X) Q; J, K ?3 N0 H7 w - __IO uint8_t TIM2_CAPTURE_STA = 0xFF; ///< 状态标记8 }4 x, F, ^$ ~# f) U( J+ [
2 q2 h' n( L0 N* u1 e, f: _- j- /**
' \& v3 L E. \: F' q - * 设置TIM2输入捕获极性
, |7 b* Y/ d; t& I9 T( Q - * @param TIM_ICPolarity:/ A8 z' K0 ]! Z4 t5 c$ {* Y, ?
- * TIM_INPUTCHANNELPOLARITY_RISING :上升沿捕获/ h* ~; L9 ~4 g6 V/ A: @
- * TIM_INPUTCHANNELPOLARITY_FALLING :下降沿捕获
! ]' \5 [3 E u" j6 o - * TIM_INPUTCHANNELPOLARITY_BOTHEDGE:上升沿和下降沿都捕获 F0 j9 b/ i+ r- h5 ~' ~6 W7 I
- */% O8 P- B% J' _2 f
- inline void TIM2_SetCapturePolarity(uint32_t TIM_ICPolarity)
5 D: j# V# m' i - {; u. M8 M4 ~1 ~3 s
- htim2.Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
6 S" P% K! E$ {3 L; ^ l - htim2.Instance->CCER |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
+ p# H9 A: A0 E' J' L - }
) o9 s9 h, r2 w. B0 ~: g - # Y1 G0 P1 ]# m+ g5 [' R
- /// 定时器2时间溢出回调函数+ K1 I: V5 g& @) S3 l1 r
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)* x8 ?& d$ R$ D( X( d2 a
- {6 f W7 l0 G5 s
- if (htim->Instance == htim2.Instance)* O+ D8 ^+ P. d$ \- A: y
- {9 s8 h5 N1 O( R* [$ V* @2 a
- TIM2_TIMEOUT_COUNT++; // 溢出次数计数; I8 H! F) _+ \, w; h9 `9 p8 Q
- }0 f5 k1 ]& Z t2 s! O# N
- }
1 g! _9 d8 Y7 K, h5 e0 { - % r u* H" ~ ?/ d) x* o
- ///< 输入捕获回调函数8 e& B0 j* l4 U6 x: k. i. M. I
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
) ~) {$ q3 e5 e6 c7 }8 q1 ] - {2 F6 T5 w, i! { ~) F( U0 {: @1 {7 n! i
- if (htim->Instance == htim2.Instance)
/ Q$ v) f2 o$ j" y, y N8 B o - {
) h* Z8 i: o; K2 S( }6 D; o - switch (TIM2_CAPTURE_STA)- ^+ p3 w/ Z' b' f+ [
- {
: \8 e& d" v/ v$ d% q0 A _6 D - case 1:
0 W+ {! j- o6 h9 n" y( C - {% y) H. `; O! G) C5 U t' {
- printf("准备捕获下降沿...\r\n");
( Y5 T: W, O, N" T0 \: } - TIM2_CAPTURE_BUF[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
- a. g$ Y8 a2 t. b) v1 k8 G - TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_FALLING); // 设置为下降沿触发
* i; ~% u! y4 r- _$ V - TIM2_CAPTURE_STA++;. `; W& v) R; i. ^/ O- n1 k
- break;; @# H% E3 P. j v5 G# w
- }
+ { R9 e0 c5 b g1 J, \( J' v" X - case 2:
4 ~% z3 @ V9 o( b% b - {' X+ ?/ |9 \2 z% }. ]$ s V9 o2 w3 b% N
- printf("准备捕获下个上升沿...\r\n"); M) B. C( d" I) ?
- TIM2_CAPTURE_BUF[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
' |+ n( K( e, f2 j; L - TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING); // 设置为上升沿触发
& N5 M3 C$ i( U6 ~0 K4 E - TIM2_CAPTURE_STA++;
$ D0 E; P* R* t& ~; s5 _ - break;* O( C+ l! B/ U! s% }
- }: k+ _3 o* t2 p) t5 i" r
- case 3:
! ~* Q. E2 v# T! G: H3 q - {2 ]1 D% T7 |* o* Y& X
- printf("捕获结束...\r\n");, M. o) c/ m$ L8 J
- printf("# end ----------------------------------------------------\r\n");$ R8 H, m/ s0 } D0 \- z9 H
- TIM2_CAPTURE_BUF[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
$ Y( W; \- M( j+ H$ }, h: ]& `* l1 ] - HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1); // 停止捕获
9 K, U- Y7 b% q* V, U1 o - HAL_TIM_Base_Stop_IT(&htim2); // 停止定时器更新中断
1 _- }* |( G% y1 u+ S n+ Z - TIM2_CAPTURE_STA++;( Z7 a) |- W7 e1 }7 O9 a; q, j
- break;; M( @$ I( p- ], ]) U
- }. b- a8 b# Y1 T( o. ?4 H
- default:$ E# L" u, _) ?$ B4 C
- break;4 k' t/ b' m& [/ Q0 Z
- }7 U+ B6 ?8 z$ z1 q& I4 [6 z
- }) E( `% t: K: y. Z/ C
- }: g3 Z4 }* ~) C& H% H# O
- ) K- ^+ A( i8 s& d0 ]( t
- ///< TIM2轮训状态切换4 o# l0 F# |5 q% W
- inline void TIM2_Poll(void)
8 D4 G4 E8 ?! ~0 ` f! b/ B. Z, e - {
- R P8 n% ~2 l" d& J! E" { - switch (TIM2_CAPTURE_STA)8 B8 m/ E7 o+ F) {" l# `! W7 n, a
- {( N; n8 {! @% J0 m" ~
- case 0:
' b' ~; u8 m2 L3 C* O0 D - {
, U/ O; L6 h/ k7 H - printf("# start ----------------------------------------------------\r\n");9 D2 _& M- W$ i4 V
- printf("准备捕获上升沿...\r\n");; b& }! w5 t6 j7 D
- TIM2_TIMEOUT_COUNT = 0;
5 _8 J& G: t- }, ^ - __HAL_TIM_SET_COUNTER(&htim2, 0); // 清除定时器2现有计数
. Q% J. O1 m6 v+ p ` - memset(TIM2_CAPTURE_BUF, 0, sizeof(TIM2_CAPTURE_BUF)); // 清除捕获计数! B8 W* l& j9 O. \+ y
- TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING); // 设置为上升沿触发
# ~1 v) `0 A, F6 \5 H - HAL_TIM_Base_Start_IT(&htim2); // 启动定时器更新中断 W; T2 ?$ f: t7 h
- HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 启动捕获中断
& f$ h# r0 W2 v2 D/ g - TIM2_CAPTURE_STA++;: T, ]: Y+ R; y! \( W& F
- break;' x9 Y9 M- E2 l" F/ ?, x
- }( P" `; v3 Z1 U4 v/ c
- & V, F Q0 W- Q5 W4 A# s- k
- case 4:% D1 q6 y I6 u0 t% j
- {$ a1 `4 u( D# a3 C
- uint32_t high = TIM2_CAPTURE_BUF[1] - TIM2_CAPTURE_BUF[0];# s: ]1 S8 N7 q( u+ o- o5 Q
- uint32_t cycle = TIM2_CAPTURE_BUF[2] - TIM2_CAPTURE_BUF[0];" U0 g- {9 f$ n4 }+ _
- float frq = 1.0 / (((float)cycle) / 1000000.0);# i5 n+ z# g- F: t
- TIM2_CAPTURE_STA++;
$ X0 V. ]5 P( ^9 {
; \9 n' r! {+ g+ V' I' @& ]6 g F- printf("\r\n\r\n");" I5 K( H: u t! X& l2 v
- printf("################################# START #########################################\r\n");+ ~* @& i3 Z, X5 n" ? p
- printf("高电平持续时间:%dms\r\n", high / 1000);
, e5 Q: Q' c. U/ m% K! B$ { - printf("周期 :%dms\r\n", cycle / 1000);! C, e4 v% x& N
- printf("频率 :%fHz\r\n", frq); v4 r3 ?5 ^8 b: g8 M+ V
- printf("################################## END ##########################################\r\n\r\n");# }5 N: @5 _' y9 ]' }, N3 I
- break;
" S- I9 P& i5 p9 [; @1 I - }
- @. t& i/ ` O
% u0 V" T' Q- l) [- default:
+ L. N7 ^" \1 o- @ - break;0 _ `0 h/ J% c, f& F
- }
6 D7 N# _4 \' n3 W8 c - }
复制代码
: b/ ]3 F$ M2 d& {% }main.c:; q7 h4 T% {& |% c# U
$ ]8 }6 l" p3 T- int main()0 v: }0 W* m+ U- M
- {8 a! P; F& M* ^* o
- HAL_Init();
( W6 U6 Q" y& ` - SystemClock_Config();
/ k1 n! t2 i" c$ P4 u9 Y: ^+ y - MX_GPIO_Init();
) x; ~8 {6 |& { - DEBUG_UART_Init();
* x, E4 d; N! S% A# r - MX_TIM2_Init();
/ m6 x* L% V) ?/ p' U1 v' y0 I y - printf("================================ 系统运行! ================================ \r\n");. ?; L C" L1 P7 G' T- }' C
- while(1). m! R! x' c/ f M) l+ C
- {3 ]$ Z1 ?7 h; K8 o* o
- TIM2_Poll();4 r' H7 _: r! B$ C
- DEBUG_UART_RecvHandler();4 j) q7 m, _9 R% ]
- }. B9 g$ l, R9 N) f9 P
- }
复制代码 y. f2 i* K1 p2 S
8 g/ i' ?: E$ }. }( k
说明:串口一接串口调试助手,勾选发送新行,向单片机发送任意字符以此来启动输入捕获。
$ p8 l# X" |# y; v% i
: Z1 h P X- L# U0 i f+ X* C, t) z1 X/ ^1 ]4 m i
2 `0 b# P3 R% P" Q) A& c/ r* c |