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

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

[复制链接]
gaosmile 发布时间:2021-1-19 11:26
背景:最近整理东西,发现了一个蓝色的小模块,上面还有两个像喇叭的小东西,关键上面还有丝印,用蓝底白字写着“HC-SR04”,于是勾起了我的好奇心,动动小手指,百度找到了这个小板子的信息,原来是一个超声波测距模块,还挺有意思的,而且只引出来了四个引脚,应用也比较简单,下面简单介绍下这个模块以及简单的超声波测距方案。
- K5 p7 o. _+ {6 Y
1.HC-SR04模块实物图和工作原理

) R7 o" C2 a, C* y9 v/ @
1.1实物如下图,可以看到这个模块是双面贴片的,整体感觉大气,印出来了四个引脚,分别是GND,Echo,Trig,VCC具体功能见下方

9 O/ [1 g- f# Q% r2 y/ R, F
微信图片_20210119102913.png 微信图片_20210119102916.png 1.2首先这个模块是要单独供电的,需要给VCC接5V,GND就不多说了关键是Echo和Trig这两个脚,可以看下方的时序图。
& H/ O, {9 ?( h' G9 l, c
a.需要给触发信号即Trig一个大于10us的方波信号

9 F/ E0 e2 T  F) j9 x  W
b.模块内部会产生一个8*40KHz的声波,因为是内部产生的,所以引出的四个脚测不出来这个信号,或许可以从PCBA里面其它地方测出,我没深入研究

* ^( ?0 ]) o- R4 k5 d" R
c.输出回响信号,即Echo会返回一个高电平信号,这个高电平的持续时间和测量距离有关。

6 a7 u4 H: ~6 L+ s- s' r! V2 }
计算测距方法:我可以用一个遮挡物挡在两个突出物上方,通过初中的只是我们都知道距离=速度*时间/2,速度在空气中的速度约等于340m/s,时间即Echo的高电平信号。所以我们可以很简单的就测量出遮挡物到模块的距离。

5 C! a9 k" E$ d& h: Z/ V% n
微信图片_20210119102919.png ' k/ m  T! o% ~$ S& ]
( ~1 `# ?/ p" y
2.要掌握的知识点和设备

/ R% R4 H1 A# x
2.1硬件环境

1 Y* p2 P  E- g9 E. o
我这边用的是HC-SR04模块+STM32F103ZET6开发板+示波器,示波器是帮助分析用,可以验证设计和实际是否一致的工具,可以不要。开发板也只是起一个连接串口调试助手,产生PWM以及输入捕获的一个功能,并不一样要和我一样的开发板,理论上任何一个开发板都可以实现这个功能。
; b5 z3 i1 x8 S6 ^$ f  r
2.2软件知识

& s, v( D- O$ |4 O$ O; B& q( Z1 b
要用上面这套工具实现超声波测距的功能,需要的代码知识点也说过了,这里再提一下。

! u: r. z. @9 @5 y5 I4 \' R5 N
a.PWM输出一个脉冲大于10us的方波到Trig,可以用STM32的定时器输出

; x' }$ C" v' o$ @8 A" c
b.输入捕获Echo接受到的高电平信号,通过测量接受到的高电平时间,即可通过距离=速度*时间/2计算出距离。
: Z& l2 ~7 P( r
c.串口调试,我们要通过串口调试助手打印出测量的时间和距离,可以方便直观的看到我们的结果。
+ S3 k% Q7 H% n$ E" g$ z
理论上掌握上面三个技能就可以实现超声波测距的这个简单的项目,当然条条大路通罗马,上面的方式也不是唯一的一种。譬如我可以用信号发生器产生方波,就可以不用定时器了。毕竟工具只是工具而已。
( v+ g, e3 K5 s" ~# P6 `: I* Z3 d
8 d6 i  W' j  \) c3.代码编写,代码是参考的正点原子的PWM输出和输入捕获,因为项目原理上面说过了,基本就是这两个功能的叠加。我本来想用HAL库来做,但是CUBEMX生成的代码调试没成功,所以最后还是用的原子的标准库来做的。下面代码截取的是main.c和time.c。也是这个项目里面最重要的两个部分。
  1. + b, Z+ H. F6 ^, ^( q9 K
  2. extern u8  TIM5CH1_CAPTURE_STA;                //输入捕获状态                                                   
    1 h( \* \5 v! ~, v& r2 M
  3. extern u16        TIM5CH1_CAPTURE_VAL;        //输入捕获值        ! w9 v3 ]% g0 V$ Q" x9 k/ V1 P) b
  4. int main(void)
    ' [- Y( D9 i. {! w1 U
  5. {               
    ( g! V9 U7 o! O
  6.          u32 temp=0;
    4 Y2 c& K# \) S, f+ y' q0 {
  7.         double ss=0;
    ; Y; @5 O) H5 Q& w8 X7 }; Z
  8.         delay_init();                     //延时函数初始化         ( l5 s: ^( H4 e
  9.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);         //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    + t, @/ i% A+ m& J% ~" O
  10.         uart_init(115200);         //串口初始化为115200
    4 H% M: B1 V) _! ~+ _
  11.          TIM3_PWM_Init(71,199);                 //不分频。PWM频率=72000/(899+1)=80Khz8 h8 O. [/ ~* f
  12.          TIM5_Cap_Init(0XFFFF,72-1);        //以1Mhz的频率计数
    0 P/ N) F1 S, W* i5 j
  13.            while(1)
    . e0 ?$ n+ U- b, _" r% c+ X
  14.         {/ l% _0 f: ]: u7 p7 b) f4 l
  15.                  delay_ms(10);$ ^6 @7 C0 A$ B+ z+ B$ m% f1 l
  16. //                TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);: z1 {* N5 M$ h4 k- P
  17.                 TIM_SetCompare2(TIM3,63);* ]' D6 t% T" C' _
  18.                 if(TIM_GetCapture2(TIM3)==300)TIM_SetCompare2(TIM3,0);                                 
    0 Z% i2 m+ t4 S4 i$ A
  19.                  if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿# C. U1 X+ K  x: Y; a1 H
  20.                 {
    3 c+ r8 q9 r+ U
  21.                         temp=TIM5CH1_CAPTURE_STA&0X3F;" L! _5 U& g9 j8 L5 R+ S# O
  22.                         temp*=65536;//溢出时间总和
    2 I6 g; Z% k4 I
  23.                         temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间& L3 y- ^/ F# m% R, w: [. w5 `
  24.                         ss=temp*340/2/1000;
    5 W# n9 q3 W" L( q$ [: l
  25.                         printf("高电平时间:%d us\r\n",temp);//打印总的高点平时间5 g! E' n: q( G8 n( m- ~
  26.                         printf("测试距离为:%3.0f mm\r\n",ss);
    ) {8 `# m' ]  F8 G( ]0 D% Q! z* |" ^
  27.                         TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
    2 l- u, h8 i/ m
  28.                         delay_ms(500);5 @9 ^3 u0 f% O: i) {$ V+ @
  29.                 }
    " g, q2 n( ^/ g2 L* D9 w
  30.         }' ~' m' |" T& M4 J: {1 z. _
  31. }1 A/ T9 A- |( z4 k1 N
复制代码
  1. ) c' d! h6 M2 `: M  Y* f
  2. void TIM3_Int_Init(u16 arr,u16 psc)( i/ g% z7 v% E8 ?
  3. {% d7 A$ ~1 i5 ^0 M
  4.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    7 q# s7 Z9 Z1 x$ B" ?, F# c0 T* k3 b% Q
  5.         NVIC_InitTypeDef NVIC_InitStructure;! ]9 T* p/ M9 g1 v/ c

  6. 2 _1 d. r: {$ }* C+ \, {3 f3 Y  Y' Q
  7.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能7 p2 J9 L+ F1 X% q$ e
  8. 2 Z3 H2 p8 d$ y- ~5 }: _
  9.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms$ i4 E6 t2 X+ {& x% u! A
  10.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  ) o- w3 |1 E4 A  D( L/ s. g
  11.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    * T( k0 d& H& p2 _) ]
  12.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    . K: J* N6 P$ Q: l6 H% I  q
  13.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位+ Z# B# }' P) N9 W

  14. & w1 K6 ^8 z0 `; Q
  15.         TIM_ITConfig(  //使能或者失能指定的TIM中断
    & h* M  J8 D  q# A, @& T  h
  16.                 TIM3, //TIM2
    0 l6 \; n" H( M
  17.                 TIM_IT_Update  |  //TIM 中断源& M. X8 J& U2 i, Z( ~* n5 b% s6 ]7 J
  18.                 TIM_IT_Trigger,   //TIM 触发中断源
    4 c- Z* M' ]+ H- Z
  19.                 ENABLE  //使能
    8 ?2 z6 Q, }# _6 x% z
  20.                 );
    3 d% X$ Z; c5 a/ K9 a) U7 [
  21.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断0 Z. r! D7 z; i2 Z/ M9 T& d
  22.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级' S. f. o1 B9 d
  23.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
    7 z- d2 e# X; E& o! f
  24.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能8 F1 c" }7 Q/ D2 K( S
  25.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
    ) h3 g( I9 z2 W( U, M9 p
  26. 2 t/ }9 a: c  @# E% P! @4 A7 p3 Q
  27.         TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设. R( c8 }0 o: i, W( I- _, N
  28.                                                          1 d) z2 h: u% F: I4 G
  29. }. n+ v; c; A) _8 P4 |+ {7 G* p

  30. ; K: H- N  M" ?2 j! o% W; c/ [5 O$ b
  31. void TIM3_IRQHandler(void)   //TIM3中断: G3 f! y" N! d; L
  32. {! u+ J4 _0 d4 i# `+ R
  33.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源6 V( n2 I+ Q) D- [5 x3 k9 N+ \# ^
  34.                 {
    5 g9 C/ W( i1 c. H
  35.                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源: s0 y" b8 a0 a: A, M
  36.                 LED1=!LED1;
      g  m/ u0 y7 q, e2 b7 H
  37.                 }
      K5 B' b4 w. g- ~
  38. }
    3 F9 B$ Z* ]" b2 z

  39. & E& l. L* K. D1 l0 c

  40. - D1 _  t9 a# w7 }& ?
  41. % o6 N0 F; Y2 U+ U( h/ y& [

  42. 4 M0 j8 m2 r) e. E1 k4 J
  43. //PWM输出初始化
    : k& Z: w+ O) H4 b) E2 r7 z  C
  44. //arr:自动重装值
    ( Y- V6 |( e7 q1 L3 ]) p
  45. //psc:时钟预分频数
    3 w0 g4 u& s4 c% G6 e
  46. 2 U. m) x6 @/ r$ d7 w* f2 B
  47. void TIM3_PWM_Init(u16 arr,u16 psc)
    # E+ M2 z0 u8 x1 J
  48. {  ( X" m2 [+ z1 w! r) [
  49.         GPIO_InitTypeDef GPIO_InitStructure;
    8 d6 v% y) O. ?* f' a
  50.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    $ c; O: B8 o+ J( i. Z
  51.         TIM_OCInitTypeDef  TIM_OCInitStructure;
    1 w( H5 r: x  E# ~: O$ `3 R3 e
  52.         
    - q" k- H+ ^7 x% g( O2 U) Y5 [

  53. 8 U9 ]: Q/ r2 t8 Q5 y
  54.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    3 m9 {- \6 z5 s2 P; ?
  55.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟使能( @  C; [3 C8 o; n* ~; `- x
  56.         
    . U( U1 R7 u* F/ W8 ^% e
  57.         GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5                                                                                //用于TIM3的CH2输出的PWM通过该LED显示' ]& u- [/ Y9 ?

  58. 4 H: [0 ]8 D6 O9 z/ b# z# y/ l- b6 u
  59.    //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形
    ; u5 z8 w% _/ ]) i: C: K, d( y
  60.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH28 p- e3 A' ^9 w+ M0 o# R6 p
  61.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出. Z5 X) l  [0 p2 d' m
  62.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  r; z1 S+ N+ E: ^
  63.         GPIO_Init(GPIOB, &GPIO_InitStructure);' z6 p! d$ t8 D: V! E9 Q& Q
  64.         //GPIO_WriteBit(GPIOA, GPIO_Pin_7,Bit_SET); // PA7上拉        3 }8 `4 F! E! H9 S: p, @5 u' z
  65. / Q* S5 x3 W& F# p; _8 d
  66.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         80K2 n  i, `5 T. J8 y
  67.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频1 o& \9 t2 c6 P
  68.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    9 X) Y2 i# w5 Q8 Z2 h" f" k
  69.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    0 G# O8 g  W1 Y1 y4 q6 w
  70.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    - S/ S0 ~1 Q  e/ ?
  71.         6 _- z! N$ Z5 p5 P3 \
  72.          * o1 c/ N; t( T
  73.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
    4 q8 Q( V# T0 G8 h! ~+ I
  74.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能5 a; x3 i5 o( s/ x5 \7 p
  75.         TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值4 H, k  O6 X4 u0 O" A1 S. t
  76.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高2 P5 M8 |2 o" \: M7 F
  77.         TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx: T$ Y( k! ?; j/ r5 Y
  78.         TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器
    2 `" n! K9 L- J' w( W1 V1 I# b4 y
  79.         
    - P6 T: t8 ^. F$ y! H/ ^- n% c
  80.         TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
    6 \. U# E8 \2 Q/ ^$ K# z
  81.         
    + J5 e5 X# c, h
  82. ' W5 j2 J8 r9 f0 k3 z
  83.         TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
    7 Z) m5 @2 _" H7 j, }
  84. 5 c7 [  g# b; E) F/ f/ l! G$ D1 Z
  85. $ V5 F; a) L2 w) {2 c
  86. }
    % ]) w" {2 B2 Y
  87. : A& e. c9 w1 U9 m  j3 E' @! s
  88. //定时器5通道1输入捕获配置
    2 ?' ?& [8 Z% p7 x  c& ^

  89. # d3 {8 X4 \4 C- i6 p
  90. TIM_ICInitTypeDef  TIM5_ICInitStructure;/ k' O6 u( }; x

  91. ! n) \8 v4 z  i: n" F! J
  92. void TIM5_Cap_Init(u16 arr,u16 psc)
    ) v7 \, O3 G9 }+ e
  93. {         
    3 y! {1 H& c0 n9 Z2 a- e
  94.         GPIO_InitTypeDef GPIO_InitStructure;: n0 ?( [* ^! h; Y. @6 e
  95.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    . C8 u" m$ s, w0 I1 i
  96.            NVIC_InitTypeDef NVIC_InitStructure;" E  x! q: l; h# J* A' I: ?# h
  97. - l) @; v4 V! y, P7 i
  98.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);        //使能TIM5时钟
    : K4 s! P+ M  \$ l6 F2 H! @0 Z
  99.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
    4 L7 d# b# C3 M4 B
  100.         
    5 n+ S+ N2 v8 q/ g  r
  101.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  //PA0 清除之前设置  + r6 C7 ^  I8 o. n# d8 n+ L. K
  102.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入  . G; \: Y" @) a  t: h
  103.         GPIO_Init(GPIOA, &GPIO_InitStructure);
    " b# S  O4 A, Q- m! j' b
  104.         GPIO_ResetBits(GPIOA,GPIO_Pin_0);                                                 //PA0 下拉
    6 x6 v+ J, E  R: {4 p" p
  105.         
    7 j; j$ e- v6 h  {: j
  106.         //初始化定时器5 TIM5         0 E1 N3 t8 I" J) Q
  107.         TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值5 C! I& `! k6 s1 y
  108.         TIM_TimeBaseStructure.TIM_Prescaler =psc;         //预分频器   6 l1 p0 ?; D# D
  109.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim5 K7 l) [' v  v+ G" p. ]
  110.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式  O6 ?, R9 d- b; ]2 u+ \
  111.         TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    2 q6 R% I% Z6 z. w3 [8 S+ K& ^) H
  112.   # [/ i/ K1 h( I3 x. h
  113.         //初始化TIM5输入捕获参数
    4 a& Q' A. R4 i5 T
  114.         TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01         选择输入端 IC1映射到TI1上$ ]" P9 g0 C: p. A6 `0 T
  115.           TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;        //上升沿捕获# O# L3 W* }( |; t5 e5 I  I
  116.           TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上  m, N% X  O% _; A8 ]2 ]
  117.           TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;         //配置输入分频,不分频3 ]( V; {9 j3 R" J
  118.           TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波5 V9 b- v1 ~6 {) `! c8 D
  119.           TIM_ICInit(TIM5, &TIM5_ICInitStructure);. p; G! K4 `5 t. T
  120.         
    6 c, k0 i8 o( \1 c& v$ V7 h& @
  121.         //中断分组初始化
    # W4 `& Y! ?# R8 k" x
  122.         NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  //TIM3中断
    5 H. f9 N, a1 F9 g
  123.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
    - ~0 J) u6 {( ?7 O
  124.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
    5 M: I9 R0 W9 n  Q! M
  125.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能2 q+ }3 m' w, D4 ?; ?, E) {/ n6 c
  126.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器5 f. e* v9 ?/ g4 G: r
  127.         ) m. A  F3 k6 s& C
  128.         TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断        9 Y7 p! l$ f3 _0 v
  129.         4 R* l8 _' d: d4 ~6 u
  130.            TIM_Cmd(TIM5,ENABLE );         //使能定时器5' h. B0 h1 r# h/ `- G. b
  131. }
    ) C9 K" p- s3 s% y# q) E

  132. 4 B" a; t6 d0 S/ t# J
  133. u8  TIM5CH1_CAPTURE_STA=0;        //输入捕获状态                                                   
    % P7 f7 D2 `: i
  134. u16        TIM5CH1_CAPTURE_VAL;        //输入捕获值
    8 `/ A! G% w9 l3 q
  135. 8 \) I8 j2 e& _3 `8 J5 {. y
  136. //定时器5中断服务程序         9 g) z1 _! K- O: \4 m
  137. void TIM5_IRQHandler(void)' \, P1 G; q# g  b/ t! P( K
  138. {/ x- p! W, q4 p3 V/ N8 v

  139. 9 s9 X! Q7 x. Y4 b* q) [. j! j1 W
  140.          if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获        
    2 l; C. ?3 p) U, M$ g
  141.         {         
    5 f7 b% O4 c1 F2 C$ p+ o0 a7 Z
  142.                 if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
    ! y; t: {8 J0 J' |
  143.                  ' \$ ~  Q, U! g; l+ ]# W9 a
  144.                 {            
    * h- W. ], D4 H7 K& b; J$ k& V
  145.                         if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了, m3 R+ J% {% a1 G) M% w
  146.                         {
    ' t3 n" o) F5 }. c" _% y6 J: D
  147.                                 if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了2 f, j5 y* V" S$ _. \
  148.                                 {
      _* ]$ {+ D+ B. V
  149.                                         TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
    : H  [( M5 B( ~
  150.                                         TIM5CH1_CAPTURE_VAL=0XFFFF;
    & @$ [0 n/ K* `+ a5 I
  151.                                 }else TIM5CH1_CAPTURE_STA++;
    ' G% u9 H& L) R) t; d" M  l
  152.                         }         
    * W/ u' G! i; F. y  z! j
  153.                 }
    * ^$ L! F8 X7 `+ Z1 E* z( ~
  154.         if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
    2 I% l6 S) S$ Y+ N
  155.                 {        
    2 V3 \, G* T( N+ p4 X
  156.                         if(TIM5CH1_CAPTURE_STA&0X40)                //捕获到一个下降沿                 
    & K2 [# A1 n' ~3 I
  157.                         {                                 ) ^8 R" l5 v$ [5 r
  158.                                 TIM5CH1_CAPTURE_STA|=0X80;                //标记成功捕获到一次高电平脉宽8 z' f$ X" D  U$ u% f4 b  L
  159.                                 TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
      T9 x, D/ H5 l+ s  P
  160.                                    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获; S6 s/ j# \; ]# ^- z: P" R
  161.                         }else                                                                  //还未开始,第一次捕获上升沿
    0 g/ s/ F9 Z9 g0 J' V
  162.                         {; X2 F  \- O, |* v8 D
  163.                                 TIM5CH1_CAPTURE_STA=0;                        //清空
    : K  q5 k& q+ W7 v) s  \, K9 y
  164.                                 TIM5CH1_CAPTURE_VAL=0;. _, M) h& i/ p  e$ v
  165.                                  TIM_SetCounter(TIM5,0);
    $ n: m9 C7 v+ L* Z3 C  w* |
  166.                                 TIM5CH1_CAPTURE_STA|=0X40;                //标记捕获到了上升沿
    % n/ ^! Q- u/ i3 y, K, d
  167.                                    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);                //CC1P=1 设置为下降沿捕获
    ( g8 @8 ?9 q. s0 a. y' I2 F/ r
  168.                         }                    / R, o9 y& H: C8 m# o; K
  169.                 }                                                                                    
    ! I+ R2 f( T6 y  W* E
  170.          }- q6 a: r- S* Q$ L) r
  171. - Z/ O; T( Y7 f! f: y4 y
  172.     TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
    4 c* b3 R/ Y" p' ^
  173. ) j% A5 a8 b# Z/ ~, h/ {8 ^6 t3 I
  174. }
    8 u4 u" S" s+ ]% }  [; i
复制代码

8 i1 v$ d  J8 n! O4.硬件连接以及实验照片

" @% B+ I+ u- O( ]; `- p
4.1硬件连接

! T2 ]; P, H5 l5 k) H3 d* U
微信图片_20210119102922.png
- }& T$ }! T9 v( b" F
: N& l6 {) f+ l; D4.2串口显示结果

' A4 ?, @3 x0 [
微信图片_20210119102926.png 8 N& {& l$ b- b6 s7 d  O6 ]
4.3Echo和Trig信号

& Q, H3 ]& X1 Y5 O* b
微信图片_20210119102929.png 微信图片_20210119112450.png
" v  g  x6 \3 V+ r# n: N8 E
基本功能是实现了,以上就是对HC-SR04这个模块的简单介绍和使用分享。当然这个模块也很常见,网上类似的分享也挺多的,但和我一样的肯定没有,起码图片都是我新鲜截取拍摄的,这次的测试也是我花了些心思做出来的,我的小目标就是攒齐3个原创文章,贴一个加V的认证,看了下原创活动是到今年年底,也算是今年的一个年度计划吧,希望可以实现。
; d+ B1 ]  [0 l. J  H) J# N/ V2 }) T  k+ \$ {. t. O. `
PS:附件是我在网上找的一个HC-SR04模块的资料,可以参考,但我看了下好像和我手上这个有点儿不一样,但引脚定义是一样的,不影响整体设计思路,可以看看。
' q- B6 l  L. p7 R" m0 `) B
2 B6 l; d$ t/ D" W# T+ \5 Z$ m
赞 收藏 评论0 发布时间:2021-1-19 11:26

举报

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