背景:最近整理东西,发现了一个蓝色的小模块,上面还有两个像喇叭的小东西,关键上面还有丝印,用蓝底白字写着“HC-SR04”,于是勾起了我的好奇心,动动小手指,百度找到了这个小板子的信息,原来是一个超声波测距模块,还挺有意思的,而且只引出来了四个引脚,应用也比较简单,下面简单介绍下这个模块以及简单的超声波测距方案。
- K5 p7 o. _+ {6 Y1.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
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
' 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。也是这个项目里面最重要的两个部分。- + b, Z+ H. F6 ^, ^( q9 K
- extern u8 TIM5CH1_CAPTURE_STA; //输入捕获状态
1 h( \* \5 v! ~, v& r2 M - extern u16 TIM5CH1_CAPTURE_VAL; //输入捕获值 ! w9 v3 ]% g0 V$ Q" x9 k/ V1 P) b
- int main(void)
' [- Y( D9 i. {! w1 U - {
( g! V9 U7 o! O - u32 temp=0;
4 Y2 c& K# \) S, f+ y' q0 { - double ss=0;
; Y; @5 O) H5 Q& w8 X7 }; Z - delay_init(); //延时函数初始化 ( l5 s: ^( H4 e
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
+ t, @/ i% A+ m& J% ~" O - uart_init(115200); //串口初始化为115200
4 H% M: B1 V) _! ~+ _ - TIM3_PWM_Init(71,199); //不分频。PWM频率=72000/(899+1)=80Khz8 h8 O. [/ ~* f
- TIM5_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数
0 P/ N) F1 S, W* i5 j - while(1)
. e0 ?$ n+ U- b, _" r% c+ X - {/ l% _0 f: ]: u7 p7 b) f4 l
- delay_ms(10);$ ^6 @7 C0 A$ B+ z+ B$ m% f1 l
- // TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);: z1 {* N5 M$ h4 k- P
- TIM_SetCompare2(TIM3,63);* ]' D6 t% T" C' _
- if(TIM_GetCapture2(TIM3)==300)TIM_SetCompare2(TIM3,0);
0 Z% i2 m+ t4 S4 i$ A - if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿# C. U1 X+ K x: Y; a1 H
- {
3 c+ r8 q9 r+ U - temp=TIM5CH1_CAPTURE_STA&0X3F;" L! _5 U& g9 j8 L5 R+ S# O
- temp*=65536;//溢出时间总和
2 I6 g; Z% k4 I - temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间& L3 y- ^/ F# m% R, w: [. w5 `
- ss=temp*340/2/1000;
5 W# n9 q3 W" L( q$ [: l - printf("高电平时间:%d us\r\n",temp);//打印总的高点平时间5 g! E' n: q( G8 n( m- ~
- printf("测试距离为:%3.0f mm\r\n",ss);
) {8 `# m' ] F8 G( ]0 D% Q! z* |" ^ - TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
2 l- u, h8 i/ m - delay_ms(500);5 @9 ^3 u0 f% O: i) {$ V+ @
- }
" g, q2 n( ^/ g2 L* D9 w - }' ~' m' |" T& M4 J: {1 z. _
- }1 A/ T9 A- |( z4 k1 N
复制代码- ) c' d! h6 M2 `: M Y* f
- void TIM3_Int_Init(u16 arr,u16 psc)( i/ g% z7 v% E8 ?
- {% d7 A$ ~1 i5 ^0 M
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
7 q# s7 Z9 Z1 x$ B" ?, F# c0 T* k3 b% Q - NVIC_InitTypeDef NVIC_InitStructure;! ]9 T* p/ M9 g1 v/ c
2 _1 d. r: {$ }* C+ \, {3 f3 Y Y' Q- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能7 p2 J9 L+ F1 X% q$ e
- 2 Z3 H2 p8 d$ y- ~5 }: _
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms$ i4 E6 t2 X+ {& x% u! A
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率 ) o- w3 |1 E4 A D( L/ s. g
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
* T( k0 d& H& p2 _) ] - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
. K: J* N6 P$ Q: l6 H% I q - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位+ Z# B# }' P) N9 W
& w1 K6 ^8 z0 `; Q- TIM_ITConfig( //使能或者失能指定的TIM中断
& h* M J8 D q# A, @& T h - TIM3, //TIM2
0 l6 \; n" H( M - TIM_IT_Update | //TIM 中断源& M. X8 J& U2 i, Z( ~* n5 b% s6 ]7 J
- TIM_IT_Trigger, //TIM 触发中断源
4 c- Z* M' ]+ H- Z - ENABLE //使能
8 ?2 z6 Q, }# _6 x% z - );
3 d% X$ Z; c5 a/ K9 a) U7 [ - NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断0 Z. r! D7 z; i2 Z/ M9 T& d
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级' S. f. o1 B9 d
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
7 z- d2 e# X; E& o! f - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能8 F1 c" }7 Q/ D2 K( S
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
) h3 g( I9 z2 W( U, M9 p - 2 t/ }9 a: c @# E% P! @4 A7 p3 Q
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设. R( c8 }0 o: i, W( I- _, N
- 1 d) z2 h: u% F: I4 G
- }. n+ v; c; A) _8 P4 |+ {7 G* p
; K: H- N M" ?2 j! o% W; c/ [5 O$ b- void TIM3_IRQHandler(void) //TIM3中断: G3 f! y" N! d; L
- {! u+ J4 _0 d4 i# `+ R
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源6 V( n2 I+ Q) D- [5 x3 k9 N+ \# ^
- {
5 g9 C/ W( i1 c. H - TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源: s0 y" b8 a0 a: A, M
- LED1=!LED1;
g m/ u0 y7 q, e2 b7 H - }
K5 B' b4 w. g- ~ - }
3 F9 B$ Z* ]" b2 z
& E& l. L* K. D1 l0 c
- D1 _ t9 a# w7 }& ?- % o6 N0 F; Y2 U+ U( h/ y& [
4 M0 j8 m2 r) e. E1 k4 J- //PWM输出初始化
: k& Z: w+ O) H4 b) E2 r7 z C - //arr:自动重装值
( Y- V6 |( e7 q1 L3 ]) p - //psc:时钟预分频数
3 w0 g4 u& s4 c% G6 e - 2 U. m) x6 @/ r$ d7 w* f2 B
- void TIM3_PWM_Init(u16 arr,u16 psc)
# E+ M2 z0 u8 x1 J - { ( X" m2 [+ z1 w! r) [
- GPIO_InitTypeDef GPIO_InitStructure;
8 d6 v% y) O. ?* f' a - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
$ c; O: B8 o+ J( i. Z - TIM_OCInitTypeDef TIM_OCInitStructure;
1 w( H5 r: x E# ~: O$ `3 R3 e -
- q" k- H+ ^7 x% g( O2 U) Y5 [
8 U9 ]: Q/ r2 t8 Q5 y- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
3 m9 {- \6 z5 s2 P; ? - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟使能( @ C; [3 C8 o; n* ~; `- x
-
. U( U1 R7 u* F/ W8 ^% e - GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 //用于TIM3的CH2输出的PWM通过该LED显示' ]& u- [/ Y9 ?
4 H: [0 ]8 D6 O9 z/ b# z# y/ l- b6 u- //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形
; u5 z8 w% _/ ]) i: C: K, d( y - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH28 p- e3 A' ^9 w+ M0 o# R6 p
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出. Z5 X) l [0 p2 d' m
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; r; z1 S+ N+ E: ^
- GPIO_Init(GPIOB, &GPIO_InitStructure);' z6 p! d$ t8 D: V! E9 Q& Q
- //GPIO_WriteBit(GPIOA, GPIO_Pin_7,Bit_SET); // PA7上拉 3 }8 `4 F! E! H9 S: p, @5 u' z
- / Q* S5 x3 W& F# p; _8 d
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K2 n i, `5 T. J8 y
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频1 o& \9 t2 c6 P
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
9 X) Y2 i# w5 Q8 Z2 h" f" k - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
0 G# O8 g W1 Y1 y4 q6 w - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
- S/ S0 ~1 Q e/ ? - 6 _- z! N$ Z5 p5 P3 \
- * o1 c/ N; t( T
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
4 q8 Q( V# T0 G8 h! ~+ I - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能5 a; x3 i5 o( s/ x5 \7 p
- TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值4 H, k O6 X4 u0 O" A1 S. t
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高2 P5 M8 |2 o" \: M7 F
- TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx: T$ Y( k! ?; j/ r5 Y
- TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器
2 `" n! K9 L- J' w( W1 V1 I# b4 y -
- P6 T: t8 ^. F$ y! H/ ^- n% c - TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
6 \. U# E8 \2 Q/ ^$ K# z -
+ J5 e5 X# c, h - ' W5 j2 J8 r9 f0 k3 z
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
7 Z) m5 @2 _" H7 j, } - 5 c7 [ g# b; E) F/ f/ l! G$ D1 Z
- $ V5 F; a) L2 w) {2 c
- }
% ]) w" {2 B2 Y - : A& e. c9 w1 U9 m j3 E' @! s
- //定时器5通道1输入捕获配置
2 ?' ?& [8 Z% p7 x c& ^
# d3 {8 X4 \4 C- i6 p- TIM_ICInitTypeDef TIM5_ICInitStructure;/ k' O6 u( }; x
! n) \8 v4 z i: n" F! J- void TIM5_Cap_Init(u16 arr,u16 psc)
) v7 \, O3 G9 }+ e - {
3 y! {1 H& c0 n9 Z2 a- e - GPIO_InitTypeDef GPIO_InitStructure;: n0 ?( [* ^! h; Y. @6 e
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
. C8 u" m$ s, w0 I1 i - NVIC_InitTypeDef NVIC_InitStructure;" E x! q: l; h# J* A' I: ?# h
- - l) @; v4 V! y, P7 i
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5时钟
: K4 s! P+ M \$ l6 F2 H! @0 Z - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
4 L7 d# b# C3 M4 B -
5 n+ S+ N2 v8 q/ g r - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置 + r6 C7 ^ I8 o. n# d8 n+ L. K
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入 . G; \: Y" @) a t: h
- GPIO_Init(GPIOA, &GPIO_InitStructure);
" b# S O4 A, Q- m! j' b - GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉
6 x6 v+ J, E R: {4 p" p -
7 j; j$ e- v6 h {: j - //初始化定时器5 TIM5 0 E1 N3 t8 I" J) Q
- TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值5 C! I& `! k6 s1 y
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器 6 l1 p0 ?; D# D
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim5 K7 l) [' v v+ G" p. ]
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 O6 ?, R9 d- b; ]2 u+ \
- TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
2 q6 R% I% Z6 z. w3 [8 S+ K& ^) H - # [/ i/ K1 h( I3 x. h
- //初始化TIM5输入捕获参数
4 a& Q' A. R4 i5 T - TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI1上$ ]" P9 g0 C: p. A6 `0 T
- TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获# O# L3 W* }( |; t5 e5 I I
- TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 m, N% X O% _; A8 ]2 ]
- TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频3 ]( V; {9 j3 R" J
- TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波5 V9 b- v1 ~6 {) `! c8 D
- TIM_ICInit(TIM5, &TIM5_ICInitStructure);. p; G! K4 `5 t. T
-
6 c, k0 i8 o( \1 c& v$ V7 h& @ - //中断分组初始化
# W4 `& Y! ?# R8 k" x - NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM3中断
5 H. f9 N, a1 F9 g - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
- ~0 J) u6 {( ?7 O - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
5 M: I9 R0 W9 n Q! M - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能2 q+ }3 m' w, D4 ?; ?, E) {/ n6 c
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器5 f. e* v9 ?/ g4 G: r
- ) m. A F3 k6 s& C
- TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断 9 Y7 p! l$ f3 _0 v
- 4 R* l8 _' d: d4 ~6 u
- TIM_Cmd(TIM5,ENABLE ); //使能定时器5' h. B0 h1 r# h/ `- G. b
- }
) C9 K" p- s3 s% y# q) E
4 B" a; t6 d0 S/ t# J- u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态
% P7 f7 D2 `: i - u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
8 `/ A! G% w9 l3 q - 8 \) I8 j2 e& _3 `8 J5 {. y
- //定时器5中断服务程序 9 g) z1 _! K- O: \4 m
- void TIM5_IRQHandler(void)' \, P1 G; q# g b/ t! P( K
- {/ x- p! W, q4 p3 V/ N8 v
9 s9 X! Q7 x. Y4 b* q) [. j! j1 W- if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
2 l; C. ?3 p) U, M$ g - {
5 f7 b% O4 c1 F2 C$ p+ o0 a7 Z - if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
! y; t: {8 J0 J' | - ' \$ ~ Q, U! g; l+ ]# W9 a
- {
* h- W. ], D4 H7 K& b; J$ k& V - if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了, m3 R+ J% {% a1 G) M% w
- {
' t3 n" o) F5 }. c" _% y6 J: D - if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了2 f, j5 y* V" S$ _. \
- {
_* ]$ {+ D+ B. V - TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
: H [( M5 B( ~ - TIM5CH1_CAPTURE_VAL=0XFFFF;
& @$ [0 n/ K* `+ a5 I - }else TIM5CH1_CAPTURE_STA++;
' G% u9 H& L) R) t; d" M l - }
* W/ u' G! i; F. y z! j - }
* ^$ L! F8 X7 `+ Z1 E* z( ~ - if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
2 I% l6 S) S$ Y+ N - {
2 V3 \, G* T( N+ p4 X - if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
& K2 [# A1 n' ~3 I - { ) ^8 R" l5 v$ [5 r
- TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽8 z' f$ X" D U$ u% f4 b L
- TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
T9 x, D/ H5 l+ s P - TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获; S6 s/ j# \; ]# ^- z: P" R
- }else //还未开始,第一次捕获上升沿
0 g/ s/ F9 Z9 g0 J' V - {; X2 F \- O, |* v8 D
- TIM5CH1_CAPTURE_STA=0; //清空
: K q5 k& q+ W7 v) s \, K9 y - TIM5CH1_CAPTURE_VAL=0;. _, M) h& i/ p e$ v
- TIM_SetCounter(TIM5,0);
$ n: m9 C7 v+ L* Z3 C w* | - TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
% n/ ^! Q- u/ i3 y, K, d - TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
( g8 @8 ?9 q. s0 a. y' I2 F/ r - } / R, o9 y& H: C8 m# o; K
- }
! I+ R2 f( T6 y W* E - }- q6 a: r- S* Q$ L) r
- - Z/ O; T( Y7 f! f: y4 y
- TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
4 c* b3 R/ Y" p' ^ - ) j% A5 a8 b# Z/ ~, h/ {8 ^6 t3 I
- }
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
- }& T$ }! T9 v( b" F
: N& l6 {) f+ l; D4.2串口显示结果
' A4 ?, @3 x0 [
8 N& {& l$ b- b6 s7 d O6 ]
4.3Echo和Trig信号
& Q, H3 ]& X1 Y5 O* b
" 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
|