你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32使用HAL库进行脉冲宽度和周期测量

[复制链接]
STMCU小助手 发布时间:2022-4-10 23:06
使用芯片: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
8[4}G`FDCF54{JG}]@4O9TB.png
' W, h4 n* U. F NG9OV6{[MUZ]J)5X}`C8583.png
0 l7 G% j( V6 y
9 d# u; W0 i5 a$ v NTLDI)_~LVR1`A]ZFP5WDCG.png : 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
6N3V6OFD3XI6X(HW1EPLGIQ.png
% 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

  1. $ m( j/ m  P( N& S2 y5 h) Y
  2. __IO uint32_t TIM2_TIMEOUT_COUNT = 0;                        ///< 定时器2定时溢出计数% \7 {! L! W# Z- o. w3 b
  3. uint32_t TIM2_CAPTURE_BUF[3]   = {0, 0, 0};                ///< 分别存储上升沿计数、下降沿计数、下个上升沿计数
    9 [0 _/ X) Q; J, K  ?3 N0 H7 w
  4. __IO uint8_t TIM2_CAPTURE_STA = 0xFF;                        ///< 状态标记8 }4 x, F, ^$ ~# f) U( J+ [

  5. 2 q2 h' n( L0 N* u1 e, f: _- j
  6. /**
    ' \& v3 L  E. \: F' q
  7. * 设置TIM2输入捕获极性
    , |7 b* Y/ d; t& I9 T( Q
  8. * @param TIM_ICPolarity:/ A8 z' K0 ]! Z4 t5 c$ {* Y, ?
  9. *        TIM_INPUTCHANNELPOLARITY_RISING  :上升沿捕获/ h* ~; L9 ~4 g6 V/ A: @
  10. *        TIM_INPUTCHANNELPOLARITY_FALLING :下降沿捕获
    ! ]' \5 [3 E  u" j6 o
  11. *        TIM_INPUTCHANNELPOLARITY_BOTHEDGE:上升沿和下降沿都捕获  F0 j9 b/ i+ r- h5 ~' ~6 W7 I
  12. */% O8 P- B% J' _2 f
  13. inline void TIM2_SetCapturePolarity(uint32_t TIM_ICPolarity)
    5 D: j# V# m' i
  14. {; u. M8 M4 ~1 ~3 s
  15.     htim2.Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
    6 S" P% K! E$ {3 L; ^  l
  16.     htim2.Instance->CCER |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
    + p# H9 A: A0 E' J' L
  17. }
    ) o9 s9 h, r2 w. B0 ~: g
  18. # Y1 G0 P1 ]# m+ g5 [' R
  19. /// 定时器2时间溢出回调函数+ K1 I: V5 g& @) S3 l1 r
  20. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)* x8 ?& d$ R$ D( X( d2 a
  21. {6 f  W7 l0 G5 s
  22.     if (htim->Instance == htim2.Instance)* O+ D8 ^+ P. d$ \- A: y
  23.     {9 s8 h5 N1 O( R* [$ V* @2 a
  24.         TIM2_TIMEOUT_COUNT++;                                                                                // 溢出次数计数; I8 H! F) _+ \, w; h9 `9 p8 Q
  25.     }0 f5 k1 ]& Z  t2 s! O# N
  26. }
    1 g! _9 d8 Y7 K, h5 e0 {
  27. % r  u* H" ~  ?/ d) x* o
  28. ///< 输入捕获回调函数8 e& B0 j* l4 U6 x: k. i. M. I
  29. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    ) ~) {$ q3 e5 e6 c7 }8 q1 ]
  30. {2 F6 T5 w, i! {  ~) F( U0 {: @1 {7 n! i
  31.     if (htim->Instance == htim2.Instance)
    / Q$ v) f2 o$ j" y, y  N8 B  o
  32.     {
    ) h* Z8 i: o; K2 S( }6 D; o
  33.         switch (TIM2_CAPTURE_STA)- ^+ p3 w/ Z' b' f+ [
  34.         {
    : \8 e& d" v/ v$ d% q0 A  _6 D
  35.         case 1:
    0 W+ {! j- o6 h9 n" y( C
  36.         {% y) H. `; O! G) C5 U  t' {
  37.             printf("准备捕获下降沿...\r\n");
    ( Y5 T: W, O, N" T0 \: }
  38.             TIM2_CAPTURE_BUF[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
    - a. g$ Y8 a2 t. b) v1 k8 G
  39.             TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_FALLING);                                        // 设置为下降沿触发
    * i; ~% u! y4 r- _$ V
  40.             TIM2_CAPTURE_STA++;. `; W& v) R; i. ^/ O- n1 k
  41.             break;; @# H% E3 P. j  v5 G# w
  42.         }
    + {  R9 e0 c5 b  g1 J, \( J' v" X
  43.         case 2:
    4 ~% z3 @  V9 o( b% b
  44.         {' X+ ?/ |9 \2 z% }. ]$ s  V9 o2 w3 b% N
  45.             printf("准备捕获下个上升沿...\r\n");  M) B. C( d" I) ?
  46.             TIM2_CAPTURE_BUF[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
    ' |+ n( K( e, f2 j; L
  47.             TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);                                        // 设置为上升沿触发
    & N5 M3 C$ i( U6 ~0 K4 E
  48.             TIM2_CAPTURE_STA++;
    $ D0 E; P* R* t& ~; s5 _
  49.             break;* O( C+ l! B/ U! s% }
  50.         }: k+ _3 o* t2 p) t5 i" r
  51.         case 3:
    ! ~* Q. E2 v# T! G: H3 q
  52.         {2 ]1 D% T7 |* o* Y& X
  53.             printf("捕获结束...\r\n");, M. o) c/ m$ L8 J
  54.             printf("# end ----------------------------------------------------\r\n");$ R8 H, m/ s0 }  D0 \- z9 H
  55.             TIM2_CAPTURE_BUF[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
    $ Y( W; \- M( j+ H$ }, h: ]& `* l1 ]
  56.             HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1);                                                                        // 停止捕获
    9 K, U- Y7 b% q* V, U1 o
  57.             HAL_TIM_Base_Stop_IT(&htim2);                                                                                                // 停止定时器更新中断
    1 _- }* |( G% y1 u+ S  n+ Z
  58.             TIM2_CAPTURE_STA++;( Z7 a) |- W7 e1 }7 O9 a; q, j
  59.             break;; M( @$ I( p- ], ]) U
  60.         }. b- a8 b# Y1 T( o. ?4 H
  61.         default:$ E# L" u, _) ?$ B4 C
  62.             break;4 k' t/ b' m& [/ Q0 Z
  63.         }7 U+ B6 ?8 z$ z1 q& I4 [6 z
  64.     }) E( `% t: K: y. Z/ C
  65. }: g3 Z4 }* ~) C& H% H# O
  66. ) K- ^+ A( i8 s& d0 ]( t
  67. ///< TIM2轮训状态切换4 o# l0 F# |5 q% W
  68. inline void TIM2_Poll(void)
    8 D4 G4 E8 ?! ~0 `  f! b/ B. Z, e
  69. {
    - R  P8 n% ~2 l" d& J! E" {
  70.     switch (TIM2_CAPTURE_STA)8 B8 m/ E7 o+ F) {" l# `! W7 n, a
  71.     {( N; n8 {! @% J0 m" ~
  72.     case 0:
    ' b' ~; u8 m2 L3 C* O0 D
  73.     {
    , U/ O; L6 h/ k7 H
  74.         printf("# start ----------------------------------------------------\r\n");9 D2 _& M- W$ i4 V
  75.         printf("准备捕获上升沿...\r\n");; b& }! w5 t6 j7 D
  76.         TIM2_TIMEOUT_COUNT = 0;
    5 _8 J& G: t- }, ^
  77.         __HAL_TIM_SET_COUNTER(&htim2, 0);                                                                                        // 清除定时器2现有计数
    . Q% J. O1 m6 v+ p  `
  78.         memset(TIM2_CAPTURE_BUF, 0, sizeof(TIM2_CAPTURE_BUF));                                                // 清除捕获计数! B8 W* l& j9 O. \+ y
  79.         TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);                                        // 设置为上升沿触发
    # ~1 v) `0 A, F6 \5 H
  80.         HAL_TIM_Base_Start_IT(&htim2);                                                                                                // 启动定时器更新中断  W; T2 ?$ f: t7 h
  81.         HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);                                                                        // 启动捕获中断
    & f$ h# r0 W2 v2 D/ g
  82.         TIM2_CAPTURE_STA++;: T, ]: Y+ R; y! \( W& F
  83.         break;' x9 Y9 M- E2 l" F/ ?, x
  84.     }( P" `; v3 Z1 U4 v/ c
  85. & V, F  Q0 W- Q5 W4 A# s- k
  86.     case 4:% D1 q6 y  I6 u0 t% j
  87.     {$ a1 `4 u( D# a3 C
  88.         uint32_t high  = TIM2_CAPTURE_BUF[1] - TIM2_CAPTURE_BUF[0];# s: ]1 S8 N7 q( u+ o- o5 Q
  89.         uint32_t cycle = TIM2_CAPTURE_BUF[2] - TIM2_CAPTURE_BUF[0];" U0 g- {9 f$ n4 }+ _
  90.         float frq = 1.0 / (((float)cycle) / 1000000.0);# i5 n+ z# g- F: t
  91.         TIM2_CAPTURE_STA++;
    $ X0 V. ]5 P( ^9 {

  92. ; \9 n' r! {+ g+ V' I' @& ]6 g  F
  93.         printf("\r\n\r\n");" I5 K( H: u  t! X& l2 v
  94.         printf("################################# START #########################################\r\n");+ ~* @& i3 Z, X5 n" ?  p
  95.         printf("高电平持续时间:%dms\r\n", high / 1000);
    , e5 Q: Q' c. U/ m% K! B$ {
  96.         printf("周期          :%dms\r\n", cycle / 1000);! C, e4 v% x& N
  97.         printf("频率          :%fHz\r\n", frq);  v4 r3 ?5 ^8 b: g8 M+ V
  98.         printf("################################## END ##########################################\r\n\r\n");# }5 N: @5 _' y9 ]' }, N3 I
  99.         break;
    " S- I9 P& i5 p9 [; @1 I
  100.     }
    - @. t& i/ `  O

  101. % u0 V" T' Q- l) [
  102.     default:
    + L. N7 ^" \1 o- @
  103.         break;0 _  `0 h/ J% c, f& F
  104.     }
    6 D7 N# _4 \' n3 W8 c
  105. }
复制代码

: b/ ]3 F$ M2 d& {% }main.c:; q7 h4 T% {& |% c# U

$ ]8 }6 l" p3 T
  1. int main()0 v: }0 W* m+ U- M
  2. {8 a! P; F& M* ^* o
  3.     HAL_Init();
    ( W6 U6 Q" y& `
  4.     SystemClock_Config();
    / k1 n! t2 i" c$ P4 u9 Y: ^+ y
  5.     MX_GPIO_Init();
    ) x; ~8 {6 |& {
  6.     DEBUG_UART_Init();
    * x, E4 d; N! S% A# r
  7.     MX_TIM2_Init();
    / m6 x* L% V) ?/ p' U1 v' y0 I  y
  8.     printf("================================ 系统运行! ================================  \r\n");. ?; L  C" L1 P7 G' T- }' C
  9.     while(1). m! R! x' c/ f  M) l+ C
  10.     {3 ]$ Z1 ?7 h; K8 o* o
  11.         TIM2_Poll();4 r' H7 _: r! B$ C
  12.         DEBUG_UART_RecvHandler();4 j) q7 m, _9 R% ]
  13.     }. B9 g$ l, R9 N) f9 P
  14. }
复制代码
  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
赞 收藏 评论0 发布时间:2022-4-10 23:06

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版