|
【年中粉丝节】+超声波距离传感器 今天分享下板子上比较大的传感器,就是超声波距离传感器。使用超声波距离传感器就比较简单了。 首先看下超声波测距传感器的原理,一端发射声波,当声波被物体阻挡就会反射回来。被接收端收到,只要我们算好这中间的时间差,加上声音传播速度就能算出距离,有如下公式: 原理图是这样的比较负责了,用了一个555定时器产生38Khz的方波,接收端其实是使用了一个CX20106A的红外解码芯片,其实这样是频率对上了,之后是为了程序方便,初始化一个定时器中断,每10US中断一次,然后把接收端也放一个中断,这样,开始发射时计数清空,然后定时器中断计数,这样来算时间,之后通过IO中断,来判断接收到了。在根据上面公式就能算出距离了。 - void Ultrasonic_Port()
% P6 H! v8 U3 k! }$ U
# X2 E' B( h) B( x; i7 ~/ V3 ?- {" f6 t, Y" Z9 L; c
- 2 x; |) m8 |. M. J. D
- ) R9 w% V: \( Y
- + B [: ?+ X- c
- GPIO_InitTypeDef GPIO_InitStructure;
4 I& D, t1 w, P7 e6 D4 U# ~ - # @6 a: \1 L9 p. P/ x1 s
-
1 A- A* e0 Z1 S8 t: I5 n
. r1 X8 l |# X+ P- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);" G6 O; k- E2 u8 d: Y
/ G: m; A) s( e) l- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);9 V7 K0 \& c! s9 a2 F6 Q; B" m
8 Q; q. c$ g8 l- //改变指定管脚的映射 GPIO_Remap_SWJ_JTAGDisable JTAG-DP 失能 + SW-DP使能$ r# N8 l, [& D, }) |6 D
- x. R0 U0 a( a5 l2 j- GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);' b9 _( L/ v6 R! d( l4 d
+ W# e, G$ m; {" h-
: D7 ]! A/ S, \ K/ z
: A" ~" ^9 x7 _ ]8 p/ e- //PB6-SCL PC2-ADDR
8 i# L8 M' d1 p! G; b+ I - / |# |' t' Q1 A* D
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //PA15
! |& d$ @, @' b1 T/ B - " s) K( C: E8 k# F9 _; q3 _; ?6 ~2 w# A
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; b& }4 ?3 [4 O6 S2 P) J2 Z
, N# T* _# V! _- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
& w! X4 B; p% q( R+ D+ V7 O4 J& o
% h- V" j7 J+ x7 n% q, p- GPIO_Init(GPIOA, &GPIO_InitStructure);
! G/ K f; b/ j' p - 5 N3 C3 q3 K" v3 |- C& U7 E
- & f' E% u! m& [8 n
- 2 k1 B* ]4 _& ~- z9 @( |
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;7 V9 U8 `6 g0 J! ?% B( o$ N
- " @2 ~" y/ @! Z3 {* m
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 T- H. ]7 S. i8 ]
" F- a9 x7 c* ?3 |% W- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
, U8 K! ~3 B4 J) {$ V9 \5 \/ j - ( O" z, V: @# S: Q0 y* a0 Y
- GPIO_Init(GPIOB,&GPIO_InitStructure);) y5 w2 |2 H/ s% n1 J: @- A" [
) Z+ Z4 U# H; n5 o- p- }
4 g, H7 D! ^$ r9 J) C
% H, \" W# \ u/ {- ], l-
& j8 F1 Y. I4 K6 t5 p* P - ) @$ |1 Z# ]) G1 d9 V
-
' r& y1 t- k8 V+ ?0 M; g! ~. e+ D - 7 j6 F E w5 O4 @. h0 Z" v
- void Ultrasonic_TIM(uint16_t arr,uint16_t psc)
) |' {- P* t# P4 X
( S4 p3 c% x0 Q4 ?) l- N3 F- {
3 ^! g2 w( r, F0 M - 8 Y$ v" o7 g W7 @
- 9 p% Q. i" @2 X% q
, L, ~) H ?5 P% K. m2 _+ ?/ F8 n- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
" T5 K+ f# M! w; B, ?$ I
' ^3 D/ H2 M% R* x7 y: h- NVIC_InitTypeDef NVIC_InitStructure;% ], A2 c9 V3 n: v' Q7 L7 A
- 4 K8 I& T6 M+ l8 t4 F9 w) B
- 0 R4 _/ s% ?8 `1 i. @- q
- 2 c. N: c" R* j/ d3 M
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
$ D3 `. l! p; D
3 j! g$ P/ b* N' a+ A4 u- ( s l1 e' \1 K
" e1 I# [5 C7 {- //定时器TIM3初始化
/ L6 i1 |$ s7 h6 j6 Z
) h9 C) }( g- {% r- }$ n- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值" u, k8 Y1 x# F M( l
- 7 a; |9 |, Z$ J
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
3 d, |0 E) S. i' B: }
: W6 C! H8 w. H" L- //TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
/ N/ }8 G% P2 s9 L! ~
( `: b; x) X7 o1 ^- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式6 ^0 U5 q5 u" n/ `2 D
- ) [' f% B" u( `8 [- ]# O) M
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位# g9 @) i/ M0 ]. I
- ) h" ?$ n5 S1 ]& Z: }4 w, b
-
( R- i. U# {2 s' x3 N7 m& k5 S
( x6 L A4 ?/ j9 S0 t0 A, x' o- //中断优先级NVIC设置
; Q. A. J+ N5 k4 A1 e% q' f4 R - 5 D: t2 T# M; t# o% x9 s
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
" {6 Y/ D; e) o/ v - & C8 r3 N& {/ a4 T* L5 c
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级, E0 \5 o4 W8 d5 }' v
- 0 X$ n$ g2 L( _, x% Y
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8; //从优先级3级
$ p! f) i; I& W5 b! e' H - e5 R/ ]8 p8 _6 L3 v% F. H0 w
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
. v% A1 r- C, S* V. a7 ~1 ~& C, K - ( w5 \. Y4 b- l
- NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器+ l& t# X0 |& P1 _/ i& _
- # ^/ z1 M8 [6 x5 T
-
1 S8 ], E8 i! T' H! S
5 |- @' }; ]( c* v% k- L- TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断1 b: E7 S/ a% y6 b7 l8 D6 y. |' Y
- % ], a4 x4 \5 L3 Z9 N; e9 N; g6 }
- TIM_Cmd(TIM3, DISABLE); //使能TIMx
6 `+ k! U( ^: A - 2 E" @. k0 K; U
- }
. e% x+ V! _9 h* q1 E; X2 p
' n* Q. w$ a/ O+ e5 g0 f- . [1 U4 k: P6 h( n
- % }' ]6 J! L( w6 T* w+ i
- void Ultrasonic_EXTI()% e* L6 c" j! I0 }: R1 B# J
- * f* Y' a6 j' l1 W
- {
+ j" g* D' C& f$ k! z6 l( O- D! ? - + Y! a( u+ D8 F! a7 S! N
- EXTI_InitTypeDef EXTI_InitStructure;# `5 q0 D" @, }4 T/ g5 R
- $ k( v! Y1 r m) x, }" R7 L9 A
- NVIC_InitTypeDef NVIC_InitStructure;7 D. ]2 i- h# ?1 }5 f
- ; F/ E# \7 Y' m
-
" @8 }+ Y2 b( ^) u( k
0 B s+ m! j# t- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
* u! k( x( E% C" y" \2 y
% J0 L+ Z6 x! K4 o9 o" ]- 3 I6 J8 C7 U: g/ P' Z6 @
- 8 ]% @; A" S8 I0 F/ q" T$ r7 v! J
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟, T' K0 _- P( Z' q6 g A5 `, j7 B
8 h! Q! G& m# Q( t$ A! X- 4 r/ u1 Q T; u; D2 g6 q
- " \5 Q/ Z4 a, C) r( C- i
- //GPIOE.2 中断线以及中断初始化配置 下降沿触发( M3 E" Y: m. `& u+ T
+ \- O4 i$ E4 w: G* B: V- GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8);' e$ p1 N) d1 N9 E7 v
- ' k" M( s6 e$ D7 u+ g$ B
-
- g. m- l }7 g2 y* ^ - % G/ V m5 K2 C! i/ K
- EXTI_InitStructure.EXTI_Line=EXTI_Line8; //KEY2
7 d; z3 |/ e' n0 }% F9 G8 ?: ?
7 A9 q" M. e" P0 c4 n/ m) N) a- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; " k% D& `# Q2 I" @8 c
- 5 D( A+ J4 j- z+ A5 e
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;4 t/ w( [5 o1 Y
- 4 w% p' o& M6 q& v2 y
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
% D' Z, L8 x& @ - 8 }+ n% q5 y" D8 E, J7 C3 B5 D
- EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
4 e! [) d: H+ Q& N' a8 N4 |" p% W
# w4 B3 C% d) M+ t0 y9 ]* k8 [1 \- 8 e5 o" [ I4 O" r1 u% {
- 1 @0 P* s) m& |% ^# p& a+ H
- NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键KEY2所在的外部中断通道3 }8 `1 o9 \9 U+ }/ s
- 4 K$ e2 Z( q/ y2 p8 k# w- z4 K
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级2,* l5 p9 a1 m5 U
1 _# i8 [4 I" E/ F- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7; //子优先级2
. P9 n4 w# N2 \! z9 r" I% i0 X
* X7 v1 w: i9 z8 d M- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道4 Z+ A3 m3 Z9 I% G) I( N- a
- P6 R" q' V) }! u6 c
- NVIC_Init(&NVIC_InitStructure);
/ e5 q" ^; Z \ W0 w( W3 N
5 I5 i* [0 n- R- + b) I: L& v4 B; [) a
3 a: A8 x: ?9 _8 p- }
+ v5 { M5 v5 x) Y, b; V
6 F1 a' F( `! ]# h5 P( r: K- 8 k ~0 h# N7 B! r( K
- " J3 e0 B$ p7 O$ _
- void Ultrasonic_Init()* D, r2 {" ?4 t; |: l0 W
- ; ]; R( h( o0 z8 [, @9 D% `9 E @- Z
- {6 H: L! c, V, k& r8 m( K
: z/ B' Q3 I$ m/ Y5 Z- Ultrasonic_Port();
( ?0 a; Z, Y* d4 C
3 s2 k4 _1 N; P4 A0 i2 W- Ultrasonic_TIM(9,71);//10us
4 F1 |+ m* A J/ x - V: b) z: y$ m; r6 o9 p
- Ultrasonic_EXTI();& s/ w" Q/ ]+ [/ f% h k3 U" w
- ' Q9 ^( V! F/ O1 y2 B8 [9 R
- }
( k4 V' H/ f2 b- h) Z
8 Z( }6 T1 `$ y4 k- $ K7 j! Q0 ~+ w) J
9 {+ I; r0 D! \- - d) X0 Z+ P% H; m1 Z
7 ^ ~$ m5 |) Z) k, p" g- //超声波测距- M* t- F+ ^0 T/ ^. k. z
6 X( h8 t6 Y3 x: @/ N5 W, Y# S R- void Ultrasonic_Ranging()5 R1 i* f* D: ~9 H9 f3 P
( P" o9 m5 `- z# v! C- {; V2 Y' w% `" {: M% C
* T! s o; G; a' g! s+ l- INC = 1; //关发射
" P+ C1 b) i& q- [' r5 Y
5 U- T, Q3 p* ^6 I- delay_us(3);0 A. d+ A$ \/ Q/ u8 B& r
4 u G1 `. C% t' Z, C; A- INC = 0;
+ e- T. E9 Y& u - 7 O+ |1 [7 u# X2 b
- ! a- K7 q2 B( H& ^# e
- 3 s! X9 j' u9 d7 }1 k/ {
- TIM_Cmd(TIM3,ENABLE);
/ J. J7 I2 t. l
' ^( G4 C! u6 _4 u, G4 I- //EXTI_ClearITPendingBit(EXTI_Line4);: t/ l5 B5 S: }! T( h ], M
( X$ M \. C; N5 D- TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
l7 `2 ?# s" [. M - ' R' s/ T0 t2 [7 S
- ( n3 E1 |8 |- Q& X* Y
7 d' G0 q8 T2 W6 O' R8 ?2 O- Ultrasonic_Num = 0; // 定时器清零
$ ^, p% W# [1 P# R& k5 u: p
' H# Y s: @6 U* o% h) [) |- m# u-
$ N0 K) E1 p& T o
, c, {( U4 z: E/ ^3 w+ L- delay_ms(30); //等待一段时间,等待发送超声波控制信号) v/ C. _- V, ~9 f1 f# M
# [" w \- @. L$ G- INC = 1;8 C# l; t0 T2 l/ M
0 U. j7 r; r M, y5 m7 |' F2 q- delay_ms(5);2 |3 |" w7 k" _1 Q! \/ D
! P. D' v6 g4 v- }- W! ^; `- ], u
- 9 ]5 J2 i! V- ]. \! H! P N) f
-
; g \# E" v- N2 ] - 5 h; Z F) i& V/ [
- //定时器3中断服务程序% ~$ a5 Z) M% a$ c4 a2 i
- 0 T& W) o' N8 X5 n" z1 r1 `2 }
- void TIM3_IRQHandler(void) //TIM3中断$ w, Q3 `- P' i3 i* v7 o
- . I* L- u8 d) r' z
- {
$ j+ y3 U. D7 R$ T3 ^ - 9 f# T6 y5 m5 Q- V' c
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) //检查TIM3更新中断发生与否
0 k2 p" ?! b2 K" e3 l ]
8 m9 V$ X8 e5 O& p. d/ @- {
: w: X: L" Y8 O, ~
. O4 B- ^' T% k6 C1 ~- Ultrasonic_Num++;
" {+ \7 w) k0 [5 o( i
7 q$ V9 r6 Q( T- }7 c+ }& o* V) p: ^+ d, g) m
& \ b# Q; O& S7 q- TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx更新中断标志: g3 k% d+ L- T& k
- 5 E$ Y. X: I7 S) J k! V
- }% i0 w8 T5 K( B4 n9 \+ b# M4 _
- $ M s9 W/ ^/ Z- e
- " X0 L4 F6 q% J
- 9 U8 @3 \% \. _) \( v% H
- //外部中断2服务程序
; d8 D- C1 @* E" q: P7 \ - ! i7 v& m- K# f: R) e. f5 t
- void EXTI9_5_IRQHandler(void)
& W7 N1 g1 D% n! e9 J, T3 ]
+ O) b9 T# ^. V8 F- {
- f* r( t7 |+ J0 o/ N# K
# i- v* ]3 o% S% \- if(EXTI_GetITStatus(EXTI_Line8) == SET)
, n/ t+ e; q/ D# x3 X
7 {+ a# F" c9 y2 k) l& T- {
5 X5 W# ~* ~$ G$ V, ] w6 E
& A; Y: S7 n/ [% m3 G# d1 G; O- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8) == RESET)
5 f, u- R9 B% ^9 Z
% K7 K$ t% f5 V: y! \- { 0 h0 b7 {; i( t
; }* a3 E% n+ |) a# v* n" a2 o5 F- TIM_Cmd(TIM3,DISABLE);
8 m4 V% ^& ^1 i/ O& N( ?
, H8 z2 S% x& Q3 U# L6 j- Ultrasonic_Value = Ultrasonic_Num;$ X# Q: Y/ X# G
- 8 x3 F4 @8 j' Y" _
- Ultrasonic_Value =(float)Ultrasonic_Value*1.73; // 计算距离定时10us,S=Vt/2(减2是误差补尝)% }/ @9 X9 s9 K3 Y: w% V
- 3 o$ h" |) J5 k3 [% V
- dis = (uint16_t)Ultrasonic_Value;# x4 c7 l2 u: ~
- - G$ X5 {5 Y- S" N- X0 m" ^
- }
! l% R6 e0 R: a: ~1 y
/ [& i' M' `$ J8 \) e- EXTI_ClearITPendingBit(EXTI_Line8);
! T) ?. h5 K# O9 [* l( b+ x# j
& U5 I5 X- |- X- }
9 X3 s* i" N. f
8 n' v- T* F% m1 D5 \6 N4 O+ c- }
复制代码 9 n+ H6 U }) `
实际测算还是会有点误差的。
`. w* a2 m8 A |