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

用HC-SR04和STM32F103ZET6做超声波测距

[复制链接]
gaosmile 发布时间:2021-1-19 11:26
背景:最近整理东西,发现了一个蓝色的小模块,上面还有两个像喇叭的小东西,关键上面还有丝印,用蓝底白字写着“HC-SR04”,于是勾起了我的好奇心,动动小手指,百度找到了这个小板子的信息,原来是一个超声波测距模块,还挺有意思的,而且只引出来了四个引脚,应用也比较简单,下面简单介绍下这个模块以及简单的超声波测距方案。
- R9 {5 M. M' [7 h% Y
1.HC-SR04模块实物图和工作原理
! N2 |' D. ?- L9 b) r& @( o% `
1.1实物如下图,可以看到这个模块是双面贴片的,整体感觉大气,印出来了四个引脚,分别是GND,Echo,Trig,VCC具体功能见下方
9 I7 |9 h4 n7 z$ R" a' J
微信图片_20210119102913.png 微信图片_20210119102916.png 1.2首先这个模块是要单独供电的,需要给VCC接5V,GND就不多说了关键是Echo和Trig这两个脚,可以看下方的时序图。
' A/ z& a) l: C  J6 H
a.需要给触发信号即Trig一个大于10us的方波信号

' t( t1 }: m# R- b4 n9 @
b.模块内部会产生一个8*40KHz的声波,因为是内部产生的,所以引出的四个脚测不出来这个信号,或许可以从PCBA里面其它地方测出,我没深入研究
0 k, p/ W# o& o0 }
c.输出回响信号,即Echo会返回一个高电平信号,这个高电平的持续时间和测量距离有关。

: ^$ U! e( D1 e
计算测距方法:我可以用一个遮挡物挡在两个突出物上方,通过初中的只是我们都知道距离=速度*时间/2,速度在空气中的速度约等于340m/s,时间即Echo的高电平信号。所以我们可以很简单的就测量出遮挡物到模块的距离。

, n0 m0 ]" h( A4 l. i  x/ p
微信图片_20210119102919.png   A8 k- {5 h( U

% X! l2 _. n) n/ {% U( x; T9 `$ K2.要掌握的知识点和设备
& \: ]- L: g. ~+ N
2.1硬件环境

0 P% i9 @. ]# ^/ p1 l
我这边用的是HC-SR04模块+STM32F103ZET6开发板+示波器,示波器是帮助分析用,可以验证设计和实际是否一致的工具,可以不要。开发板也只是起一个连接串口调试助手,产生PWM以及输入捕获的一个功能,并不一样要和我一样的开发板,理论上任何一个开发板都可以实现这个功能。

! a7 Q" H# r6 w. d) H
2.2软件知识
  A/ k4 T! q; `. u: a
要用上面这套工具实现超声波测距的功能,需要的代码知识点也说过了,这里再提一下。
# b2 v+ M+ Z) y
a.PWM输出一个脉冲大于10us的方波到Trig,可以用STM32的定时器输出
, Q9 {+ {% g' D3 h
b.输入捕获Echo接受到的高电平信号,通过测量接受到的高电平时间,即可通过距离=速度*时间/2计算出距离。
( `) E6 }; a& E7 \& \
c.串口调试,我们要通过串口调试助手打印出测量的时间和距离,可以方便直观的看到我们的结果。
& z& v: D5 e7 F$ E  ^8 q
理论上掌握上面三个技能就可以实现超声波测距的这个简单的项目,当然条条大路通罗马,上面的方式也不是唯一的一种。譬如我可以用信号发生器产生方波,就可以不用定时器了。毕竟工具只是工具而已。# K: Y) G7 H+ B8 z1 d9 Y
# n( t. `- u" L. S
3.代码编写,代码是参考的正点原子的PWM输出和输入捕获,因为项目原理上面说过了,基本就是这两个功能的叠加。我本来想用HAL库来做,但是CUBEMX生成的代码调试没成功,所以最后还是用的原子的标准库来做的。下面代码截取的是main.c和time.c。也是这个项目里面最重要的两个部分。

  1. 9 r# @3 S5 {$ H1 W6 A4 N
  2. extern u8  TIM5CH1_CAPTURE_STA;                //输入捕获状态                                                   
    & ?5 j  ^: ^" W, P+ W2 |) q
  3. extern u16        TIM5CH1_CAPTURE_VAL;        //输入捕获值        
    , m5 E, l9 [$ V# F+ ~; q0 M2 y
  4. int main(void)
    # [4 v2 m( z6 i* V
  5. {               , n) M0 s) Y$ @
  6.          u32 temp=0;3 E4 w- h. M: H$ Q1 I
  7.         double ss=0;
    : P3 z; s; x5 N8 J% F  i1 T. _1 P
  8.         delay_init();                     //延时函数初始化         
      o; l+ o4 U- V. B) E( d7 I8 }: n
  9.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);         //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    5 S$ c6 [8 U5 Z! s4 u% G9 s' E
  10.         uart_init(115200);         //串口初始化为115200
      K2 z: W* f# S7 b; V8 t5 Q- N
  11.          TIM3_PWM_Init(71,199);                 //不分频。PWM频率=72000/(899+1)=80Khz
    " B$ G4 [$ l2 W5 X! _) R
  12.          TIM5_Cap_Init(0XFFFF,72-1);        //以1Mhz的频率计数
    ) b: z' g0 G  Y+ k+ D. F
  13.            while(1)' d8 i, u; K$ `9 H
  14.         {
    ' `" K% E" D5 t. O
  15.                  delay_ms(10);5 C+ |0 T* V. H1 B/ S
  16. //                TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);
    3 j7 S6 Y, v1 W6 x  b6 R" H  f
  17.                 TIM_SetCompare2(TIM3,63);
    $ q  G4 s* a, F
  18.                 if(TIM_GetCapture2(TIM3)==300)TIM_SetCompare2(TIM3,0);                                 
    & q5 W" {5 K  b# p
  19.                  if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
    ) U, d' R4 s+ n! x" y
  20.                 {
    ' O+ y  V# p. q9 O6 V
  21.                         temp=TIM5CH1_CAPTURE_STA&0X3F;" t1 }( @0 C7 r/ S; I  r, o9 o
  22.                         temp*=65536;//溢出时间总和
    , u* J+ S% I$ M$ N
  23.                         temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
    % U7 N8 e) v9 W& h* C; O9 n" H! ?
  24.                         ss=temp*340/2/1000;* a6 I7 P' F- V% f  s- W3 c
  25.                         printf("高电平时间:%d us\r\n",temp);//打印总的高点平时间5 o  A8 g8 a- j6 u$ @+ N
  26.                         printf("测试距离为:%3.0f mm\r\n",ss);" }# v' v& q0 M) c! l5 z
  27.                         TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
    ) s/ p6 H3 R- F) c3 \- q  V
  28.                         delay_ms(500);
    8 G, }( J  J4 p
  29.                 }# c; o# Y" `3 u5 L* p) F) W
  30.         }
    ' A; H4 B, @7 T, x) z4 I
  31. }2 q: ~6 F& _- |0 b/ X: K1 C% W1 @
复制代码

  1. : [  Z8 l- H& l
  2. void TIM3_Int_Init(u16 arr,u16 psc)" M3 p& @& A! h  z
  3. {9 J+ k3 [& t8 F9 W6 Q1 c
  4.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    " `) Q3 V& K/ T5 e. Q
  5.         NVIC_InitTypeDef NVIC_InitStructure;+ Z3 ]: {- L/ ]: c, Z
  6. * M3 A0 ~; P8 C/ x! i) H
  7.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    / J1 L: w& O$ L( j* D3 d
  8. 8 e& ?4 [, x9 \0 Y
  9.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms
    0 R. @/ f% @! J" j& J' X/ o
  10.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  . x* C( D# \' h5 C
  11.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim1 T& D8 c% @/ D' u$ F8 }
  12.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    1 g5 W9 E3 q) j& n
  13.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位% r" R& u4 t+ S3 Y9 ^  t! A
  14. 7 J, ^# v9 H% f% H( f
  15.         TIM_ITConfig(  //使能或者失能指定的TIM中断4 o9 k: w9 R; Z
  16.                 TIM3, //TIM22 ~$ q8 u! R, v6 ]
  17.                 TIM_IT_Update  |  //TIM 中断源, ^1 v. q6 s, \+ D% ?
  18.                 TIM_IT_Trigger,   //TIM 触发中断源8 P* b% L+ U8 _+ W% Z- [: U
  19.                 ENABLE  //使能( i+ B# R  \) a5 F1 D2 F9 E; W' w
  20.                 );( I) O6 Z7 z) c+ x( F6 U/ X
  21.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    # V8 c7 r# g, H1 i4 l# B, z- G- e4 W
  22.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    0 h% @; O, Z" x$ v, K* s+ @
  23.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级4 t0 X' @7 C" h, Q( z* K
  24.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    : u0 Z' j2 m  ]' D
  25.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器& v- ]. f# X7 Z' S
  26. ! r1 a% L3 G4 @+ ~. S
  27.         TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设3 k  U+ Y' \; F2 T1 U2 q# y/ H# k
  28.                                                          ( n/ y, n8 ~5 \* b% y8 m) a/ |; ?
  29. }: p; ^4 q4 Q% ], u
  30. & y# V" [+ y' ?. S2 S7 r+ Y% I' k
  31. void TIM3_IRQHandler(void)   //TIM3中断
    : |& `6 R( |) {8 k
  32. {5 }5 `! m+ L" p2 X
  33.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
    1 K" [% E+ {2 {! b. e2 v8 m. A! a5 E% H
  34.                 {9 E+ W. G9 \* e# D
  35.                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源& B* Q% B( l0 s# l
  36.                 LED1=!LED1;
    % ?2 B* T" n2 L5 h: x
  37.                 }8 V+ I% @# y, x: i2 ~
  38. }. y: G8 @: Z$ i8 k, \- X
  39. : P) c. B& q2 I
  40. 8 ^  }, R( W8 r1 S# |7 w
  41. 4 d+ `/ n- G+ H- T( m9 B, x' C8 v
  42. ) T1 R% ?1 V3 k
  43. //PWM输出初始化! ?' x, v9 J) z3 ]" [1 o7 z, W/ e
  44. //arr:自动重装值
    & ^9 Z; S9 D; R; B/ {" J
  45. //psc:时钟预分频数
    ! w' h3 B8 Y# Z8 g5 h

  46. 2 w0 k7 Z% }/ Y) v2 l4 [4 E
  47. void TIM3_PWM_Init(u16 arr,u16 psc)3 x- O0 y, c* S# o" K$ G
  48. {  " J( `% k  M9 ~( C5 H$ Z1 m  t8 P& w
  49.         GPIO_InitTypeDef GPIO_InitStructure;$ ^1 `$ r/ x9 ~. C! ~/ g
  50.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;* k8 U' e) F, g
  51.         TIM_OCInitTypeDef  TIM_OCInitStructure;
    4 |8 M! w9 e6 |. {
  52.         
    2 _0 |& ^  S. T% J( u5 u' h4 Z

  53. 2 u7 f2 N! ]4 E5 l* p
  54.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    ! a( v" B4 J; w0 L9 d3 O8 x: O1 ]1 M! ~
  55.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟使能* z$ g) w# F7 d, f1 y( ~+ G% y
  56.         7 Y8 C7 I# j# b8 v0 N
  57.         GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5                                                                                //用于TIM3的CH2输出的PWM通过该LED显示
    ; s- X, o, f; g* k

  58. ) C% Z; v  V' B% ?5 {5 s: H
  59.    //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形8 w2 q2 ~/ j) |, r" x& ?$ c; U
  60.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
    ! f# Y' N/ G6 f5 J- `3 x1 J! x% L1 W
  61.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    9 e3 V$ C+ \! L1 W  ?1 p
  62.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;5 {+ u# K! [; l
  63.         GPIO_Init(GPIOB, &GPIO_InitStructure);
    % h4 `; Q% w1 ?+ f3 b8 }* r3 h" ?  l
  64.         //GPIO_WriteBit(GPIOA, GPIO_Pin_7,Bit_SET); // PA7上拉        4 h4 y% e% C. s6 K. x

  65. ) g' T6 @  Q# }, y
  66.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         80K
    * c3 l8 M- R& k9 Q6 s' L9 q  L  L1 H
  67.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频" z0 A8 }4 i% T0 \- b% x
  68.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim5 T2 t6 |+ h1 W3 e
  69.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
      t+ J7 B4 j4 n, H7 i
  70.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    6 E! @" s, ^) L5 A
  71.         
    ( w, E9 m/ I3 G1 A5 h, f
  72.          
    ' C1 k4 i2 D- D! m2 C1 H
  73.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式25 @) ~& d5 F0 ~( ?% _
  74.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    ) C( V( t6 ]2 {" \  n
  75.         TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值$ f' a" F) w0 k& A5 _
  76.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    * B/ r- |0 b: z; p( ^. Y+ G
  77.         TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
    + s; c, E9 a& \9 Q
  78.         TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器) k0 J/ g* E: S4 O
  79.         $ t1 c/ @7 u# p7 B# s/ v
  80.         TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
    # I9 A0 O4 G$ ~- t# s/ N9 U
  81.         , J" w' l, p% M( m

  82. # u- V; q+ {' A8 g3 M2 h" @
  83.         TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设  i' b- O) q) B7 `8 ~7 Q+ h2 L5 y: \
  84. 0 {0 q! T4 y( k  A7 ]0 M" C: E

  85. 1 X" b/ C. ?; f$ r
  86. }1 q9 Y1 e& N+ J5 l' D

  87. 4 \: Q' B! Z* ~' j& ?
  88. //定时器5通道1输入捕获配置3 o% a! w8 X9 K" h" p) T9 M/ `

  89. - m2 F5 e& }2 }9 [
  90. TIM_ICInitTypeDef  TIM5_ICInitStructure;
    ( f( H) i5 c5 u  [. j
  91. 7 R: C8 v% d% Z7 ^* i3 M
  92. void TIM5_Cap_Init(u16 arr,u16 psc)
    ) o8 ]& s7 x' l" W& c
  93. {         1 ]2 ]5 s! J0 y8 E3 t2 v
  94.         GPIO_InitTypeDef GPIO_InitStructure;
    * n4 ~1 w4 d1 ~9 t
  95.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;# C) F6 \+ C% t' p. d( n& I
  96.            NVIC_InitTypeDef NVIC_InitStructure;( _2 _# n3 }3 A3 h$ }+ x. A% M
  97.   U2 ~, W- W7 ?& ]# a/ P3 z" k' R
  98.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);        //使能TIM5时钟" t& {4 W- G7 p; c
  99.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟9 U$ i( L6 X3 B
  100.         
    & e1 {6 N. W% @4 {& ^
  101.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  //PA0 清除之前设置  
    ( h! u  p% F3 l/ \1 J( W+ }
  102.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入  8 \0 q8 s, ?& d& y
  103.         GPIO_Init(GPIOA, &GPIO_InitStructure);. x& ~4 S7 _$ C( r  t3 q' E# `
  104.         GPIO_ResetBits(GPIOA,GPIO_Pin_0);                                                 //PA0 下拉0 l( d( {9 T  M* ^) g
  105.         ! H& f% O0 B2 p  r
  106.         //初始化定时器5 TIM5         
    9 N9 @! o1 f3 ^8 y$ ~0 J. K
  107.         TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
    - G* \& [- T+ p5 ^6 o. p9 m
  108.         TIM_TimeBaseStructure.TIM_Prescaler =psc;         //预分频器   
    + d1 b, [. p8 y" D- A7 [; {
  109.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    ! F  L2 L  E' U! m8 l* Z7 t) I: x
  110.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式0 r# @' G7 P" T% U
  111.         TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    9 v6 G) o( _! d4 E* g' B7 R
  112.   
    5 b3 S. H/ b$ p/ d8 ~0 W- |7 \
  113.         //初始化TIM5输入捕获参数
    2 O5 V6 ^" M+ b1 ]$ n+ w+ q% L# B
  114.         TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01         选择输入端 IC1映射到TI1上
    * D0 p# ^0 N1 m3 \$ S
  115.           TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;        //上升沿捕获/ ]$ {+ |% ]$ |4 ^0 O
  116.           TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
    # `# U( N% [( x8 y
  117.           TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;         //配置输入分频,不分频. y; i4 I7 q5 f# g- l
  118.           TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
    : t9 {  w  m! H) E; `/ [, _8 u
  119.           TIM_ICInit(TIM5, &TIM5_ICInitStructure);0 X- Y: N+ E# Z
  120.         ( \6 L2 T; `$ y' B
  121.         //中断分组初始化% h; D8 D6 L8 ?8 F) w! k- G8 v! g+ g
  122.         NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  //TIM3中断! C" P; P& A3 t9 @
  123.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
    ) W+ z# k' A% A, N# ?' e
  124.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
    9 Z+ a8 i' Q5 F9 ~2 z* r, K0 ]* g
  125.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    9 A- B& j0 n2 ^9 D- Y  m7 ~
  126.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
    " z" K0 @7 G# M) l6 X( F
  127.         
    8 ?- R' L+ Z4 o  H) G) q
  128.         TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断        
    : m) b2 }% d* f# y1 I& ]& G* g
  129.         
    7 H/ F5 ~) W& s: {  ^( B
  130.            TIM_Cmd(TIM5,ENABLE );         //使能定时器55 P0 g& o, s$ [" R. v
  131. }
    7 p# U+ \% ~/ s5 v9 \2 B% b

  132. , `: a7 d" z% U3 m& u# M& [
  133. u8  TIM5CH1_CAPTURE_STA=0;        //输入捕获状态                                                   + y2 L& Q4 F- l
  134. u16        TIM5CH1_CAPTURE_VAL;        //输入捕获值
    : x- R, P( |+ R  `! G+ X

  135. ' O6 l4 h) t/ u8 N
  136. //定时器5中断服务程序         7 u7 U6 v% }5 e$ L% h
  137. void TIM5_IRQHandler(void)& Y8 P9 P1 Z  }9 J7 N
  138. {
    : l2 A, b# Y3 ^2 C2 D
  139. ! W  U, ]6 s# R5 \* s  F5 m5 g
  140.          if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获        
    / Y! h' v4 r" @& ?! g6 j( \3 C  E$ V
  141.         {         + w! V; Y1 O% A$ N( D
  142.                 if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
      n# U8 b# t- k
  143.                  0 q0 ~) S0 T: ]
  144.                 {            ) }2 H! f) [' L" u% s2 K& a7 l
  145.                         if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了# Y! }2 r! B" R! V5 P% s0 t
  146.                         {
    0 j+ F& T! y$ i
  147.                                 if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了; S* {% U6 {- u) @1 \* z& V
  148.                                 {
    . h, p7 @& `$ Z9 M
  149.                                         TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
    9 @4 a% F. k$ S
  150.                                         TIM5CH1_CAPTURE_VAL=0XFFFF;/ d: ]4 K) S6 o$ @: E! {
  151.                                 }else TIM5CH1_CAPTURE_STA++;& X3 n" @6 K' K: s& y$ o
  152.                         }         
    6 E7 L" l6 }- A4 U* C6 C/ D* z
  153.                 }
    0 \/ z* @, w  M# }% [" e
  154.         if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
    6 ]+ N. O7 R; r6 ^
  155.                 {        & v! c: z, z4 d+ ^
  156.                         if(TIM5CH1_CAPTURE_STA&0X40)                //捕获到一个下降沿                 ; b1 R: s' o% L1 l7 o: E
  157.                         {                                 8 T+ A( w: c; [6 q" n7 k$ i
  158.                                 TIM5CH1_CAPTURE_STA|=0X80;                //标记成功捕获到一次高电平脉宽
    * h% \3 k( g7 i# g% c
  159.                                 TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);+ T+ J; c- ~) R5 s* c
  160.                                    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
    8 f/ ~* a  c- S* R! B
  161.                         }else                                                                  //还未开始,第一次捕获上升沿: f0 M) W2 Z8 e" ~. M
  162.                         {
    + B9 Q6 o; ~2 Y4 X
  163.                                 TIM5CH1_CAPTURE_STA=0;                        //清空* J2 T7 ?9 |1 i# ]6 W
  164.                                 TIM5CH1_CAPTURE_VAL=0;
    ; q( Y7 v" Z/ S7 T' `
  165.                                  TIM_SetCounter(TIM5,0);9 Z( O) X' f2 a. m
  166.                                 TIM5CH1_CAPTURE_STA|=0X40;                //标记捕获到了上升沿
    " x8 O/ H7 @; k3 H1 H" S
  167.                                    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);                //CC1P=1 设置为下降沿捕获
    ( o2 s! W' Y0 \4 c
  168.                         }                    
    9 `" |- r* C8 b" h% r  h
  169.                 }                                                                                    ' O" H7 j  E3 V0 g3 T7 f! e/ f
  170.          }
    & H9 B- U8 Y- @" L  [2 E' _

  171. , k! Z* ?2 ~1 {) S
  172.     TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位, U% v: k% T) H& o/ x* r# S1 |
  173. $ B3 o5 |) _, ]
  174. }
    " Q  S) a( k5 M4 J7 ]9 g7 t/ N
复制代码
  _+ G- o( `" l! o* d6 ?9 m
4.硬件连接以及实验照片

8 F* v, _, E4 D' Z) z; n% l
4.1硬件连接
$ g. `' X/ r0 V
微信图片_20210119102922.png
7 x# b' K& I) F! O' c/ r) v1 N8 u& I! o4 Q- R; c" Z9 L
4.2串口显示结果

3 g6 V+ U. ~  m6 S8 y0 `5 C
微信图片_20210119102926.png , G' ^7 x' @, h. U
4.3Echo和Trig信号
* g8 r. m- e+ A: Z; X) ]; @- T
微信图片_20210119102929.png 微信图片_20210119112450.png
/ e/ A3 F) R1 x
基本功能是实现了,以上就是对HC-SR04这个模块的简单介绍和使用分享。当然这个模块也很常见,网上类似的分享也挺多的,但和我一样的肯定没有,起码图片都是我新鲜截取拍摄的,这次的测试也是我花了些心思做出来的,我的小目标就是攒齐3个原创文章,贴一个加V的认证,看了下原创活动是到今年年底,也算是今年的一个年度计划吧,希望可以实现。
8 o6 o( p+ e  ?
7 m1 g; J0 g) Q% e( o5 A5 PPS:附件是我在网上找的一个HC-SR04模块的资料,可以参考,但我看了下好像和我手上这个有点儿不一样,但引脚定义是一样的,不影响整体设计思路,可以看看。
  J2 r# z4 w. ?7 O& x) ^$ D! W
! _3 }) ]8 A3 T5 `* T6 A
收藏 评论0 发布时间:2021-1-19 11:26

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版