背景:最近整理东西,发现了一个蓝色的小模块,上面还有两个像喇叭的小东西,关键上面还有丝印,用蓝底白字写着“HC-SR04”,于是勾起了我的好奇心,动动小手指,百度找到了这个小板子的信息,原来是一个超声波测距模块,还挺有意思的,而且只引出来了四个引脚,应用也比较简单,下面简单介绍下这个模块以及简单的超声波测距方案。
- R9 {5 M. M' [7 h% Y1.HC-SR04模块实物图和工作原理! N2 |' D. ?- L9 b) r& @( o% `
1.1实物如下图,可以看到这个模块是双面贴片的,整体感觉大气,印出来了四个引脚,分别是GND,Echo,Trig,VCC具体功能见下方9 I7 |9 h4 n7 z$ R" a' J
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
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。也是这个项目里面最重要的两个部分。
9 r# @3 S5 {$ H1 W6 A4 N- extern u8 TIM5CH1_CAPTURE_STA; //输入捕获状态
& ?5 j ^: ^" W, P+ W2 |) q - extern u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
, m5 E, l9 [$ V# F+ ~; q0 M2 y - int main(void)
# [4 v2 m( z6 i* V - { , n) M0 s) Y$ @
- u32 temp=0;3 E4 w- h. M: H$ Q1 I
- double ss=0;
: P3 z; s; x5 N8 J% F i1 T. _1 P - delay_init(); //延时函数初始化
o; l+ o4 U- V. B) E( d7 I8 }: n - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
5 S$ c6 [8 U5 Z! s4 u% G9 s' E - uart_init(115200); //串口初始化为115200
K2 z: W* f# S7 b; V8 t5 Q- N - TIM3_PWM_Init(71,199); //不分频。PWM频率=72000/(899+1)=80Khz
" B$ G4 [$ l2 W5 X! _) R - TIM5_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数
) b: z' g0 G Y+ k+ D. F - while(1)' d8 i, u; K$ `9 H
- {
' `" K% E" D5 t. O - delay_ms(10);5 C+ |0 T* V. H1 B/ S
- // TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);
3 j7 S6 Y, v1 W6 x b6 R" H f - TIM_SetCompare2(TIM3,63);
$ q G4 s* a, F - if(TIM_GetCapture2(TIM3)==300)TIM_SetCompare2(TIM3,0);
& q5 W" {5 K b# p - if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
) U, d' R4 s+ n! x" y - {
' O+ y V# p. q9 O6 V - temp=TIM5CH1_CAPTURE_STA&0X3F;" t1 }( @0 C7 r/ S; I r, o9 o
- temp*=65536;//溢出时间总和
, u* J+ S% I$ M$ N - temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
% U7 N8 e) v9 W& h* C; O9 n" H! ? - ss=temp*340/2/1000;* a6 I7 P' F- V% f s- W3 c
- printf("高电平时间:%d us\r\n",temp);//打印总的高点平时间5 o A8 g8 a- j6 u$ @+ N
- printf("测试距离为:%3.0f mm\r\n",ss);" }# v' v& q0 M) c! l5 z
- TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
) s/ p6 H3 R- F) c3 \- q V - delay_ms(500);
8 G, }( J J4 p - }# c; o# Y" `3 u5 L* p) F) W
- }
' A; H4 B, @7 T, x) z4 I - }2 q: ~6 F& _- |0 b/ X: K1 C% W1 @
复制代码
: [ Z8 l- H& l- void TIM3_Int_Init(u16 arr,u16 psc)" M3 p& @& A! h z
- {9 J+ k3 [& t8 F9 W6 Q1 c
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
" `) Q3 V& K/ T5 e. Q - NVIC_InitTypeDef NVIC_InitStructure;+ Z3 ]: {- L/ ]: c, Z
- * M3 A0 ~; P8 C/ x! i) H
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
/ J1 L: w& O$ L( j* D3 d - 8 e& ?4 [, x9 \0 Y
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
0 R. @/ f% @! J" j& J' X/ o - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率 . x* C( D# \' h5 C
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim1 T& D8 c% @/ D' u$ F8 }
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
1 g5 W9 E3 q) j& n - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位% r" R& u4 t+ S3 Y9 ^ t! A
- 7 J, ^# v9 H% f% H( f
- TIM_ITConfig( //使能或者失能指定的TIM中断4 o9 k: w9 R; Z
- TIM3, //TIM22 ~$ q8 u! R, v6 ]
- TIM_IT_Update | //TIM 中断源, ^1 v. q6 s, \+ D% ?
- TIM_IT_Trigger, //TIM 触发中断源8 P* b% L+ U8 _+ W% Z- [: U
- ENABLE //使能( i+ B# R \) a5 F1 D2 F9 E; W' w
- );( I) O6 Z7 z) c+ x( F6 U/ X
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
# V8 c7 r# g, H1 i4 l# B, z- G- e4 W - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
0 h% @; O, Z" x$ v, K* s+ @ - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级4 t0 X' @7 C" h, Q( z* K
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
: u0 Z' j2 m ]' D - NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器& v- ]. f# X7 Z' S
- ! r1 a% L3 G4 @+ ~. S
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设3 k U+ Y' \; F2 T1 U2 q# y/ H# k
- ( n/ y, n8 ~5 \* b% y8 m) a/ |; ?
- }: p; ^4 q4 Q% ], u
- & y# V" [+ y' ?. S2 S7 r+ Y% I' k
- void TIM3_IRQHandler(void) //TIM3中断
: |& `6 R( |) {8 k - {5 }5 `! m+ L" p2 X
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
1 K" [% E+ {2 {! b. e2 v8 m. A! a5 E% H - {9 E+ W. G9 \* e# D
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源& B* Q% B( l0 s# l
- LED1=!LED1;
% ?2 B* T" n2 L5 h: x - }8 V+ I% @# y, x: i2 ~
- }. y: G8 @: Z$ i8 k, \- X
- : P) c. B& q2 I
- 8 ^ }, R( W8 r1 S# |7 w
- 4 d+ `/ n- G+ H- T( m9 B, x' C8 v
- ) T1 R% ?1 V3 k
- //PWM输出初始化! ?' x, v9 J) z3 ]" [1 o7 z, W/ e
- //arr:自动重装值
& ^9 Z; S9 D; R; B/ {" J - //psc:时钟预分频数
! w' h3 B8 Y# Z8 g5 h
2 w0 k7 Z% }/ Y) v2 l4 [4 E- void TIM3_PWM_Init(u16 arr,u16 psc)3 x- O0 y, c* S# o" K$ G
- { " J( `% k M9 ~( C5 H$ Z1 m t8 P& w
- GPIO_InitTypeDef GPIO_InitStructure;$ ^1 `$ r/ x9 ~. C! ~/ g
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;* k8 U' e) F, g
- TIM_OCInitTypeDef TIM_OCInitStructure;
4 |8 M! w9 e6 |. { -
2 _0 |& ^ S. T% J( u5 u' h4 Z
2 u7 f2 N! ]4 E5 l* p- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
! a( v" B4 J; w0 L9 d3 O8 x: O1 ]1 M! ~ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟使能* z$ g) w# F7 d, f1 y( ~+ G% y
- 7 Y8 C7 I# j# b8 v0 N
- GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 //用于TIM3的CH2输出的PWM通过该LED显示
; s- X, o, f; g* k
) C% Z; v V' B% ?5 {5 s: H- //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形8 w2 q2 ~/ j) |, r" x& ?$ c; U
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
! f# Y' N/ G6 f5 J- `3 x1 J! x% L1 W - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
9 e3 V$ C+ \! L1 W ?1 p - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;5 {+ u# K! [; l
- GPIO_Init(GPIOB, &GPIO_InitStructure);
% h4 `; Q% w1 ?+ f3 b8 }* r3 h" ? l - //GPIO_WriteBit(GPIOA, GPIO_Pin_7,Bit_SET); // PA7上拉 4 h4 y% e% C. s6 K. x
) g' T6 @ Q# }, y- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
* c3 l8 M- R& k9 Q6 s' L9 q L L1 H - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频" z0 A8 }4 i% T0 \- b% x
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim5 T2 t6 |+ h1 W3 e
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
t+ J7 B4 j4 n, H7 i - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
6 E! @" s, ^) L5 A -
( w, E9 m/ I3 G1 A5 h, f -
' C1 k4 i2 D- D! m2 C1 H - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式25 @) ~& d5 F0 ~( ?% _
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
) C( V( t6 ]2 {" \ n - TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值$ f' a" F) w0 k& A5 _
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
* B/ r- |0 b: z; p( ^. Y+ G - TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
+ s; c, E9 a& \9 Q - TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器) k0 J/ g* E: S4 O
- $ t1 c/ @7 u# p7 B# s/ v
- TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
# I9 A0 O4 G$ ~- t# s/ N9 U - , J" w' l, p% M( m
# u- V; q+ {' A8 g3 M2 h" @- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设 i' b- O) q) B7 `8 ~7 Q+ h2 L5 y: \
- 0 {0 q! T4 y( k A7 ]0 M" C: E
1 X" b/ C. ?; f$ r- }1 q9 Y1 e& N+ J5 l' D
4 \: Q' B! Z* ~' j& ?- //定时器5通道1输入捕获配置3 o% a! w8 X9 K" h" p) T9 M/ `
- m2 F5 e& }2 }9 [- TIM_ICInitTypeDef TIM5_ICInitStructure;
( f( H) i5 c5 u [. j - 7 R: C8 v% d% Z7 ^* i3 M
- void TIM5_Cap_Init(u16 arr,u16 psc)
) o8 ]& s7 x' l" W& c - { 1 ]2 ]5 s! J0 y8 E3 t2 v
- GPIO_InitTypeDef GPIO_InitStructure;
* n4 ~1 w4 d1 ~9 t - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;# C) F6 \+ C% t' p. d( n& I
- NVIC_InitTypeDef NVIC_InitStructure;( _2 _# n3 }3 A3 h$ }+ x. A% M
- U2 ~, W- W7 ?& ]# a/ P3 z" k' R
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5时钟" t& {4 W- G7 p; c
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟9 U$ i( L6 X3 B
-
& e1 {6 N. W% @4 {& ^ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置
( h! u p% F3 l/ \1 J( W+ } - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入 8 \0 q8 s, ?& d& y
- GPIO_Init(GPIOA, &GPIO_InitStructure);. x& ~4 S7 _$ C( r t3 q' E# `
- GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉0 l( d( {9 T M* ^) g
- ! H& f% O0 B2 p r
- //初始化定时器5 TIM5
9 N9 @! o1 f3 ^8 y$ ~0 J. K - TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
- G* \& [- T+ p5 ^6 o. p9 m - TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
+ d1 b, [. p8 y" D- A7 [; { - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
! F L2 L E' U! m8 l* Z7 t) I: x - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式0 r# @' G7 P" T% U
- TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
9 v6 G) o( _! d4 E* g' B7 R -
5 b3 S. H/ b$ p/ d8 ~0 W- |7 \ - //初始化TIM5输入捕获参数
2 O5 V6 ^" M+ b1 ]$ n+ w+ q% L# B - TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI1上
* D0 p# ^0 N1 m3 \$ S - TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获/ ]$ {+ |% ]$ |4 ^0 O
- TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
# `# U( N% [( x8 y - TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频. y; i4 I7 q5 f# g- l
- TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
: t9 { w m! H) E; `/ [, _8 u - TIM_ICInit(TIM5, &TIM5_ICInitStructure);0 X- Y: N+ E# Z
- ( \6 L2 T; `$ y' B
- //中断分组初始化% h; D8 D6 L8 ?8 F) w! k- G8 v! g+ g
- NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM3中断! C" P; P& A3 t9 @
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
) W+ z# k' A% A, N# ?' e - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
9 Z+ a8 i' Q5 F9 ~2 z* r, K0 ]* g - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
9 A- B& j0 n2 ^9 D- Y m7 ~ - NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
" z" K0 @7 G# M) l6 X( F -
8 ?- R' L+ Z4 o H) G) q - TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断
: m) b2 }% d* f# y1 I& ]& G* g -
7 H/ F5 ~) W& s: { ^( B - TIM_Cmd(TIM5,ENABLE ); //使能定时器55 P0 g& o, s$ [" R. v
- }
7 p# U+ \% ~/ s5 v9 \2 B% b
, `: a7 d" z% U3 m& u# M& [- u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态 + y2 L& Q4 F- l
- u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
: x- R, P( |+ R `! G+ X
' O6 l4 h) t/ u8 N- //定时器5中断服务程序 7 u7 U6 v% }5 e$ L% h
- void TIM5_IRQHandler(void)& Y8 P9 P1 Z }9 J7 N
- {
: l2 A, b# Y3 ^2 C2 D - ! W U, ]6 s# R5 \* s F5 m5 g
- if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
/ Y! h' v4 r" @& ?! g6 j( \3 C E$ V - { + w! V; Y1 O% A$ N( D
- if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
n# U8 b# t- k - 0 q0 ~) S0 T: ]
- { ) }2 H! f) [' L" u% s2 K& a7 l
- if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了# Y! }2 r! B" R! V5 P% s0 t
- {
0 j+ F& T! y$ i - if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了; S* {% U6 {- u) @1 \* z& V
- {
. h, p7 @& `$ Z9 M - TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
9 @4 a% F. k$ S - TIM5CH1_CAPTURE_VAL=0XFFFF;/ d: ]4 K) S6 o$ @: E! {
- }else TIM5CH1_CAPTURE_STA++;& X3 n" @6 K' K: s& y$ o
- }
6 E7 L" l6 }- A4 U* C6 C/ D* z - }
0 \/ z* @, w M# }% [" e - if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
6 ]+ N. O7 R; r6 ^ - { & v! c: z, z4 d+ ^
- if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿 ; b1 R: s' o% L1 l7 o: E
- { 8 T+ A( w: c; [6 q" n7 k$ i
- TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
* h% \3 k( g7 i# g% c - TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);+ T+ J; c- ~) R5 s* c
- TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
8 f/ ~* a c- S* R! B - }else //还未开始,第一次捕获上升沿: f0 M) W2 Z8 e" ~. M
- {
+ B9 Q6 o; ~2 Y4 X - TIM5CH1_CAPTURE_STA=0; //清空* J2 T7 ?9 |1 i# ]6 W
- TIM5CH1_CAPTURE_VAL=0;
; q( Y7 v" Z/ S7 T' ` - TIM_SetCounter(TIM5,0);9 Z( O) X' f2 a. m
- TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
" x8 O/ H7 @; k3 H1 H" S - TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
( o2 s! W' Y0 \4 c - }
9 `" |- r* C8 b" h% r h - } ' O" H7 j E3 V0 g3 T7 f! e/ f
- }
& H9 B- U8 Y- @" L [2 E' _
, k! Z* ?2 ~1 {) S- TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位, U% v: k% T) H& o/ x* r# S1 |
- $ B3 o5 |) _, ]
- }
" 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
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
, G' ^7 x' @, h. U
4.3Echo和Trig信号* g8 r. m- e+ A: Z; X) ]; @- T
/ 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
|