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

【经验分享】STM32Cube HAL 输入捕获——脉宽测量

[复制链接]
STMCU小助手 发布时间:2022-4-7 16:05
实验内容:使用通用定时器输入捕获测量信号的脉宽(检测按键按下的时间)。
1 z4 [+ ~1 u, [6 L9 [+ K4 z" Z* Q) }. L9 q3 ^3 k! w0 y
一、原理图
5 A8 E$ U. U, F' N
5 @; V* g$ S1 t6 q S2UQH`KQIB]8QVT9A}}_0GG.png 6 P2 I  s6 ]$ W
0 A4 z! J7 q9 V: k  t3 G  R
二、 CubeMX配置
4 G+ l- T7 I0 t/ X2 u
) m* d  J" L8 [( M0 ^Step1.打开 STM32CubeMX,点击“New Project”,选择芯片型号,STM32F103VETx。6 _* ^( K$ l( d& `  k! W$ t2 f8 t
2 T- p, P+ C7 s9 D5 [2 A' S
[4{_]0(A0S4UV4[2WDF0{86.png $ ^0 d2 [9 C2 X6 t, V) E; t

3 h4 U! N3 @+ A; o' y  E Step2.选择时钟源,并配置时钟树。选择Crystal/Ceramic Resonator,并配置系统时钟为72M。
/ m/ X1 e$ v. v
0 |- c( ]! A0 w P]7Z@[K3G]5A6%@~75XJOXQ.png 3 X/ l5 P! K% ?) I- g& M

- i) v$ E. r7 D4 ]1 Q: Q% j: Y2 ^ @H_}RX(4VA9}FKA~9YD@J@J.png
3 K* r4 S0 P" y
" Q/ H" G; L1 f9 @* c- S2 w! bStep3.配置SYS,我们这里选择的是Serial Wire。(正常情况配置不配置不影响,debug可以使用。但是你不可以把这两个引脚用于其他复用功能,如果用于其他复用功能,debug就不起作用了。)
. Y' V- m* g2 U3 n, D
4 i4 N& I5 l5 a6 V) C ]ANUD1142)915ZQ$HZ2[5{D.png ( q( J4 z: Z/ H6 _# ~+ e

4 h$ P' x( ^1 Q  ?  KStep4.串口配置(主要为了在串口调试助手显示测试的时间),因为没有用到中断和DMA所以我们就不过多讲解。7 r; a$ ~8 B7 c9 ?' N0 Y. W
" z9 a& d, i, z1 z3 ?1 R3 Z
O[OB9_5BBG`(6FO]751[4TS.png
9 ?5 G. |6 e7 o, W# `7 D6 Y  ]* Q; q( M5 s) @. D. s
22I99T3B]AS`RF`{BV)MW%X.png ( C/ H" w7 @7 Y& C9 ^3 n/ \" y
3 W; L7 |1 y! `
Step5.接下来进行最主要的定时器配置。原理图中按键引脚PA0和定时器2通道1相关,因此我们选用定时器2进行配置。
7 e, `: D) N- ~: [) M' y: C
! J" r3 P2 U  K3 I3 b5 Y 6PP9TS]JJ~$(G0)0G[YP~~7.png
- h& t+ z' N/ O& d* I0 r# z7 e6 G* S! |  d
PT[JGPZ}N[L(W~E)2{@AL{P.png 2 y' T" a! M2 k; g' h* g4 p

! u- C  z% h, h6 n6 }  S1 O 到这里关于相关参数配置基本已经完成,只需要根据之前文章《STM32Cube HAL:GPIO输入/输出(一)》Step4-Step8,设置相关工程参数和生成代码。
" `3 e" O/ m, w" T5 }- ?1 a# l: _  M
三、添加功能代码: `: g+ O" |8 Z& [; v" X
5 D, U  \$ }) Z' {4 c2 ?
1、我们等会会向串口调试助手发送数据,进行实验结果的验证。 发送数据我们采用printf函数,所有需要重定向c库函数printf到串口。注意使用时需要在keil设置中勾选微库(use mircolib),同时需要添加头文件#include <stdio.h>。重定向代码如下(usart.c)! v- v9 q* ^& Y% c/ E
+ b0 c% m  a" o0 ]% D- G$ |* O6 Q
  1. //重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数( q# D2 y3 b- `: S
  2. int fputc(int ch, FILE *f)
    $ o  u! ^. e* _" T+ ~1 ?" d7 z" |. X
  3. {
    0 i3 M2 ^4 x5 }' H
  4.         /* 发送一个字节数据到串口DEBUG_USART */
    / O9 l1 B# o8 z5 J8 s2 }% }
  5.         HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);        
    . ^' H8 K! e! ^/ T
  6.         
    , r1 v5 P$ H* A1 ]4 F
  7.         return (ch);3 F3 r8 `. e' n+ ?
  8. }+ H. J& f4 j3 k0 B

  9. / A' N( G: f* g& D' V, t: x
  10. //重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
    5 J. x% c4 b1 T# [( S) t
  11. int fgetc(FILE *f)
    9 U* M" ^# P- `: I- m
  12. {               
    ( v! r/ L6 b/ }4 u$ ]
  13.         int ch;
    4 w/ k0 V* L3 j# _. m
  14.         HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);        # J/ J  L. S0 f3 Y
  15.         return (ch);" c: X/ f2 K' g+ t; f" Z
  16. }
    ; k( L0 f2 ?' H) G
复制代码
; n2 [, s, ]" M/ v6 Y7 _4 U
2、定义相关变量,以及使能相关定时器和计数处理代码(main.c)
5 {3 `; `. L0 I6 {/ y( d0 o* {7 }! R) K% x; |% s" I9 Q% j  u
  1. //全局变量% k& R9 T( Z5 t, V3 P3 K- V: @: M2 V+ z
  2. uint32_t ccr_cnt,period_cnt;//CCR寄存器值,中断次数1 c1 B' C9 U! d  p$ V. T
  3. uint8_t tri_flag,end_flag;//触发方式标志位,捕获标记位
复制代码
  1. //局部变量! V6 R  M( E. V- e
  2. uint32_t cnt_cl=72000000/72;;//计数器时钟& `8 D* e( [2 g2 h
  3. float time;//按键时间
复制代码
  1. //使能相关定时器以及计数结果处理代码" d  H7 Q6 X) V/ u( ~

  2. 2 i1 Q5 M+ Q- [! {- [
  3.         __HAL_TIM_CLEAR_FLAG(&htim2,TIM_IT_UPDATE);//清除中断标志位,防止一使能定时器就进入中断
    % ]" M1 h8 d0 f" R. w& ^
  4.     HAL_TIM_Base_Start_IT(&htim2);//使能定时器及更新中断4 k( d% J$ U& r% s
  5.         HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//使能定时器及捕获中断
    2 o6 Y0 V- Y. z, u6 |, c* G0 @$ d

  6. ; y& F, E/ ^8 f2 Z5 \
  7.         printf("\r\n——————————开始按键测试——————————\r\n");0 k+ D% D" X7 f) k! U% G
  8.         ! d. x& O* Q/ `
  9.   while (1)
    # J. c2 ]2 q2 G/ a  N6 j% M' P0 m
  10.   {; |/ Z& l, ^* p) H
  11.                 if(end_flag==1)//结束捕获* |/ t" a/ D* h' G6 q2 _) E
  12.                 {& ]1 s4 S- E0 E0 X3 u8 W4 z: Z
  13.                         time=(float)(period_cnt*1000+(ccr_cnt+1))/cnt_cl;//结果强制转换为浮点型8 l' F# i  O- P+ g" U% w0 ~
  14.                         printf( "\r\n测得高电平脉宽时间:%.2fs\r\n",time);//输出结果保留小数点后两位) U! C9 {2 M) O% {( P3 ]( u
  15.                         end_flag=0;               
    * w0 H# t! f( @4 H0 u1 a* L/ `
  16.                 }
    * A' ]& t/ R! R
  17.   }
复制代码

, I  N6 t) V+ y$ x$ A* q# [% c+ i' S/ B& }
3、中断回调函数(更新中断和捕获中断)(main.c)
' x5 Q0 _8 g, _; N
+ S+ q' y$ b; |7 U* S
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)* P  Z9 n8 p/ q
  2. {
    3 C1 o8 j+ J+ }2 t, v1 W
  3.         period_cnt++;//中断计数2 ^# N- B% b: \! F
  4. }+ C0 j, \8 p. s' j; o
  5. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    2 J/ G5 e, l3 \
  6. {
    / {7 Z5 j! c* ]5 v8 A; n
  7.         + r/ Y- ^& h1 ^) r: t
  8.         if(tri_flag==0)//上升沿触发时进入(tri_flag  0 上升沿触发 / 1 下降沿触发)
    " T  c. I: o+ _' c6 v& p
  9.         {( R& l( n/ ^9 M* h. J6 o2 G5 S% B
  10.                 period_cnt=0;//中断次数清零9 B  `' ?2 ]2 W
  11.                 __HAL_TIM_SET_COUNTER(&htim2,0); //计数器清零2 ~2 i. v0 o" `" C- a( F
  12.                 ccr_cnt=0;//存捕获寄存器获取的值的变量清零
    ) i" N* ]$ t& [  @; D
  13.                 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);//改变触发极性-下降沿触发. L: ]: J0 G6 m4 u6 q, E0 M
  14.                 tri_flag=1;) R. G/ {, ^3 C9 t2 o) Z
  15.         }7 n) v8 B* r  s# n: [+ k0 u
  16.         else//下降沿触发时进入
    6 H0 Y( U+ D, Z2 m$ t5 T
  17.         {$ {& x% Y, ?9 `
  18.                 ccr_cnt=__HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1);//获取捕获寄存器的值
    ( t" y4 D  p6 ~$ [" G
  19.                 //ccr_cnt=HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//功能同上
    ( c& V5 i0 J) T$ c4 o4 M8 @
  20.                 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);//改变触发极性-上降沿触发3 b- L6 N) C) |7 T* h- [$ Y, U
  21.                 tri_flag=0;1 R- Q! G* }) Z4 R( C7 _
  22.                 end_flag=1;//捕获完成标志/ i; i2 E* d4 q. r; W
  23.         }$ q. a  x/ [0 y% P3 O" n+ O* u
  24. }
复制代码
7 v4 U/ p' a) i8 ~! ^. m# {+ p3 A, J, ?
' O) w. J3 Z) P
总体来这个实验还算简单,主要的思路是先捕获第一个上升沿,然后将计数器值,中断计数值以及CCR寄存器(存捕获寄存器获取的值的变量)清零,同时变换为下降沿触发,进行第二次捕获,通过第二次的触发获取中断计数值以及CCR寄存器的值来计算出按键按住的时间。; F1 a0 [6 V4 V/ B) t( V
2 |/ w' v' v2 @" |  U; I

$ H6 }3 @* d2 ]9 w6 i
赞 收藏 评论0 发布时间:2022-4-7 16:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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