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

【经验分享】STM32F103定时器输入捕获功能

[复制链接]
STMCU小助手 发布时间:2022-3-19 20:55
  STM32F103单片机的定时器不仅能输出PWM波,而且还能捕获输入的PWM波。可以通过定时器的捕获功能测量输入PWM波的周期和占空比。其中定时器的输入捕获功能如下:% j, Q  M: F* Y4 W! G- `/ x; A5 ]) {9 P

9 I0 ^* i! c5 J; k& B  在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。
/ s, e1 y+ x8 U$ v7 Z$ J# W1 j' c+ J8 z0 Q% b/ M: s
  这里就使用捕获模式测量PWM波形的高电平时长,具体实现原理简单的来说就是,当第一个上升沿到来之后,清空计数器,当第一个下降沿到来之后,此时计数器的值就是高电平的值。1 e9 q. I+ _0 @2 H  \  v/ w4 C
设置代码如下:/ k$ ~, U0 n( {4 c: N% ?$ _- H+ U: a

+ z' N& i5 g4 C# x5 A1 J# }
  1. void TIM5_Cap_Init(u16 arr, u16 psc)
      \% l8 n6 S5 S& E
  2. {' L3 a4 K/ F! k8 o/ _
  3.     GPIO_InitTypeDef GPIO_InitStructure;
    - G) B$ n( Z1 Y- y5 w
  4.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    7 D* U- A) S' t' e
  5.     TIM_ICInitTypeDef TIM_ICInitStructure;, r; a2 U( \+ A8 B
  6.     NVIC_InitTypeDef NVIC_InitStructure;
    ; p# i. \- N" m9 ?1 W( G

  7. 1 E6 B$ S* A9 j! F7 U
  8.     //时钟初始化
    ' c& D; ~$ ^0 `& E. ]
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    ' x4 ^6 ?7 v- A1 g3 c
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    ! c& a1 q3 B& s* V, {; g
  11.     //IO口初始化+ r. ~, V; r9 b" Y# h' l2 M
  12.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;' f8 V8 {3 r* U, i1 t# @6 E/ H' a
  13.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;7 o3 z) w/ G2 R% Y) I, B; R" _& P
  14.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    7 P/ q/ X" X  a) s9 v! c
  15.     GPIO_Init(GPIOA, &GPIO_InitStructure);1 `; v* i8 a) U3 n
  16.     //TIM5初始化
    0 f" o5 R1 N( S; m
  17.     TIM_TimeBaseStructure.TIM_Period = arr;. q4 C6 @1 m8 _( b/ C
  18.     TIM_TimeBaseStructure.TIM_Prescaler = psc;
    : x4 h0 }/ A- e/ s( ]* d( l
  19.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;0 {* t" j0 \" r2 r. Q- d% h- |
  20.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  O) k: g7 i+ a& H% S
  21.     TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);) p! u* b) q; i4 O* S$ B. D% V9 E) |
  22.     //TIM5输入捕获参数
      P- v5 y, e' T5 Z$ l" ~4 n
  23.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;                                 //CC1S=01 选择输入端 IC1映射到TI1上
    1 }5 _) d/ O# j
  24.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;           //上升沿捕获
    - Q$ y- Z+ p7 F
  25.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //映射到TI1上
    1 J: j  d- [  b) w$ ~) _  I5 }# ?
  26.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;                         //配置输入分频,不分频
    * ?7 R0 J( J, U, J
  27.     TIM_ICInitStructure.TIM_ICFilter = 0x00;                                                 //IC1F=0000 配置输入滤波器 不滤波) J% t: L, ^  V" `" l" k6 z) y
  28.     TIM_ICInit(TIM5, &TIM_ICInitStructure);
    + v$ q- X* c3 }# h
  29.     //中断分组初始化
    # I. b; ~9 o; t: e; I6 g# L
  30.     NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;9 w' Q& M  l2 _5 F9 `" F% @
  31.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;/ `# V: q/ b4 u
  32.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    " z8 H2 N: [) e" K, M4 ~' y
  33.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    7 e1 t) H8 M; L: C1 ]  q% o$ z
  34.     NVIC_Init(&NVIC_InitStructure);
    . H6 a6 C( e% Y5 H/ `
  35. . ?  i( t) T2 W
  36.     TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);
    7 i, `7 s3 [* ]. p+ k( L
  37.     TIM_Cmd(TIM5, ENABLE);' V% K. `3 y4 K9 F
  38. }
    ( I/ y" j" m1 I* z( R, @  X5 P
  39. % O  ]! I" s7 Z6 g! b

  40. " i: G0 v; d& V
  41. u8  TIM5CH1_CAP_STA = 0;    //输入捕获状态  V3 c, {' l5 @; [- F4 N8 D; ]
  42. u16 TIM5CH1_CAP_VAL;                //输入捕获值6 X! u$ {9 P2 l# T
  43. void TIM5_IRQHandler(void)
    9 c5 r9 z$ _2 ~& j
  44. {( k5 y1 L) [$ k; P1 C/ N  o
  45.     if((TIM5CH1_CAP_STA & 0x80) == 0)
    7 H- \2 r+ d' U# i  c0 ]9 ]1 _* O5 s
  46.     {1 i' T- x6 y8 R3 F- N
  47.         if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)                          //溢出中断
    ( ?% d/ R5 A; C
  48.         {5 H) G. a: S  `  D
  49.             if(TIM5CH1_CAP_STA & 0x40)                                                                  //已经捕获到高电平了8 m1 w& M5 O. c$ U; p1 D- k
  50.             {
    ( F& G. c9 C3 y& F" L. D
  51.                 if((TIM5CH1_CAP_STA & 0x3F) == 0x3F)                                  //高电平太长了# V2 h4 i0 M! k: v  Y' ~- G
  52.                 {- E0 D3 i$ H$ Z+ l
  53.                     TIM5CH1_CAP_STA |= 0x80;                                                  //标记成功捕获了一次
    ' L/ a7 O* c, Q7 n
  54.                     TIM5CH1_CAP_VAL = 0xFFFF;
    * c( \! a; l  C& T) i
  55.                 }
    " G( R5 E& [$ i$ ?: x, k
  56.                 else( d8 v" y. r; C
  57.                     TIM5CH1_CAP_STA++;
    - z1 x3 T( r, i8 o" z3 G
  58.             }' g' N3 h3 S7 V  _" k3 U7 n! K
  59.         }" e6 `& A3 M3 r# T
  60.         if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)                                  //捕获中断$ H( H  b, _2 B! W
  61.         {
    + P6 s! k& [( ^5 m7 Y* C
  62.             if(TIM5CH1_CAP_STA & 0x40)                                                                  //下降沿捕获2 t8 r! c  a; F3 g
  63.             {
    0 P9 m. b1 a( U3 G$ p' D6 K6 H9 [, u: s4 X
  64.                 TIM5CH1_CAP_STA |= 0x80;                                                          //标记成功捕获一次高电平脉宽
    8 J0 i( Q& \2 Z8 x' A$ K
  65.                 TIM5CH1_CAP_VAL = TIM_GetCapture1(TIM5);
    / h+ v1 H( O$ y$ w! M9 y3 x/ V
  66.                 TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);         //设置上升沿捕获
    1 F( ]4 U2 g# B% q: N+ K
  67.             }
    & B1 X* H7 ^+ D$ b& k# x0 E! o
  68.             else                                                                                                            //上升沿捕获* M' T: O2 E3 t0 a- L  E" M5 V
  69.             {
    * ~  I  I+ S$ s1 h3 P5 O
  70.                 TIM5CH1_CAP_STA = 0;                                                                  //清空' L0 C+ M) G9 v0 d
  71.                 TIM5CH1_CAP_VAL = 0;, N7 T+ Z0 N  K
  72.                 TIM_SetCounter(TIM5, 0);
    2 C; }/ U) y; Y! t: e; q
  73.                 TIM5CH1_CAP_STA |= 0x40;                                                          //标记捕获到了高电平
    : y- ~8 {! D/ U" j& @: |% m) d  E
  74.                 TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling); //设置下降沿捕获
    ! D, `3 p3 i& u/ F5 n9 J7 {
  75.             }0 t: {. g. ^  M- S% K
  76.         }
    9 o) h& z1 C% s
  77.     }- @$ u8 Q# Y  R; U2 N" e# {
  78.     TIM_ClearITPendingBit(TIM5, TIM_IT_Update | TIM_IT_CC1);
    6 n) k& s$ m) S3 }3 [8 R6 P4 ~# G
  79. }
复制代码
- w2 P: ~; Y  @  Z+ U/ ?
  这里使用定时器5的通道1来进行捕获,首先设置通道1为上升沿捕获,当上升沿触发中断之后,清空计数器的值,然后将中断设置为下降沿中断。当下一次下降沿中断触发后,此时的时间就是PWM波的高电平时间,接着再将中断设置为上升沿中断,等待下一次高电平的触发。
( Q. X/ H( v# b# V6 `- M2 d: i
1 X+ y/ V; B/ E0 E  每次捕获成功时,在主函数中将高电平时长打印出来。+ _! X7 X7 a# n6 G: k

7 t: _. w/ {, q, }5 C
  1. extern u8  TIM5CH1_CAP_STA;            //输入捕获状态
    + m4 U" e! W: F+ P. r; E& c
  2. extern u16 TIM5CH1_CAP_VAL;                //输入捕获值
    ' ~$ U1 X: q9 s
  3. int main(void)5 F. _8 j# C9 w& e6 n. t
  4. {
    2 i6 U- }; l6 t* b5 w+ l& c
  5.     u32 temp = 0;
    " Q  [/ \6 c4 b# t( ?
  6.     delay_init();                       //延时函数初始化( A2 y  G1 W# F! G4 }, ^" L/ v3 Z
  7.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);! _6 Y+ Y2 I5 @1 g+ Z7 `
  8.     uart_init(115200);2 X6 I+ b  B( U
  9.     LED_Init();
    * ^5 y7 Y" n9 H, U9 A

  10. , e3 R2 C, s, l$ g7 a8 f3 h- q/ N
  11.     LED0 = 1;. e3 K/ k: L* Q9 P" i! p  x
  12.     LED1 = 1;. M: @/ K9 X) W3 B& l: o6 }: L" h
  13.     delay_ms(500);
    4 @$ ~0 ]4 g+ l. ?
  14.     LED0 = 0;" d: b4 r( y& M
  15.     LED1 = 0;
    . J+ x, O; I! H
  16. - S5 u6 \- C3 m
  17.     TIM3_PWM_Init(3600-1,0);             //不分频。PWM频率=72000000/3600=20Khz   PB5输出PWM
    : I) Y' m3 s4 Q1 _
  18.         
    $ c, @; W6 b+ S1 m" p
  19.     TIM5_Cap_Init(0xffff, 72 - 1);                //以1Mhz的频率计数  PA0
    ) z( f& v3 F0 a# y/ F% H0 S

  20. ) O+ Z* M' ~6 g( a1 Z6 {% S
  21.     printf("Input Capture test!!!\r\n");8 a0 B4 {7 Z2 e$ i) m5 b, J$ ]. ]3 U
  22.     while(1). W; p- f8 c0 J$ o: x
  23.     {3 |$ O, V, A7 y' Y
  24.         delay_ms(10);
    ; f/ k! @3 _! P4 O
  25.         TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);% ?' s  f- r6 E. o6 D+ J1 y: t

  26. , P" j8 ?: H1 i& y, R0 Y/ H
  27.         if(TIM_GetCapture2(TIM3)==3600)+ d' Q9 v! R: o3 o
  28.             TIM_SetCompare2(TIM3,0);        ( h  C. |  `  V8 X( W
  29. 7 V/ F" L2 {$ |& J9 F; w4 u6 k
  30.         if(TIM5CH1_CAP_STA & 0X80)                                 //成功捕获到了一次上升沿8 J# F4 n  y: Z; v# C! U9 |
  31.         {3 B% x8 G* r  @) Q! D& b" q+ E
  32.             temp = TIM5CH1_CAP_STA & 0X3F;! V; c3 q  @# V. Q, w$ [6 [
  33.             temp *= 65536;                                                 //溢出时间总和; ]% p; O( X- F9 ]5 T
  34.             temp += TIM5CH1_CAP_VAL;                         //得到总的高电平时间" X8 s$ `/ h  s
  35.             printf("HIGH:%d us %d ms %d s\r\n", temp,temp/1000,temp/1000000);         //打印总的高点平时间7 v; l% p- w/ j- G' S2 f- K$ }
  36.             TIM5CH1_CAP_STA = 0;                                 //开启下一次捕获9 p4 o4 I* F% x+ f
  37.         }
    8 o1 o2 j% Z2 U2 U, Q3 Y
  38.     }8 I5 d' [3 W, Q8 ~
  39. }
复制代码

# z2 p9 t$ z, h6 B4 k7 M0 N1 {
5 f* G; v) C( z4 K; b7 Z8 F# p定时器3用来产生一个PWM波,然后通过定时器5的捕获功能来测量PWM波的高电平时间。
; U9 k8 ]. n* Q  O1 a+ q  S
7 s/ Q; M6 h6 D: x; _7 |: L1 ~1 s0 c& Z+ o
赞 收藏 评论0 发布时间:2022-3-19 20:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

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