|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。! y, m3 F+ O) @+ t1 R0 D
硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。 v# m" d+ n7 i9 o) \5 V
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。/ K) n, k: h6 v. w4 \
超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。. ^$ s* X5 j- ?9 _7 z H, S1 V
超声波的接收电路包含一块CD40106处理芯片。
6 ^+ {8 k4 r' }技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。+ ?: X5 z9 [; p# ~
#include<reg51.h>
5 m9 U+ g" y% @7 O+ b#include <intrins.h>, ?. h c$ z4 G, q' e
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
: M4 c7 |* b& ~6 L U$ H. A! H#define LCM_Data P0 r- f, [8 x% ~3 s% r4 x% I
#define uchar unsigned char+ p) }/ F$ o% S, O) W0 w
#define uint unsigned int
$ S( @- b6 N B. |- e( h9 T9 M#define ulong unsigned long1 I: z& ~. }3 E" |
7 d: B! L9 B8 m1 K# n6 B* N: B
! i! x7 O3 p9 [) u7 L& _extern void cs_t(void);+ |4 z2 Z& j( D& o$ |
extern void delay(uint);8 f: W. ?! Y2 \! N: `; ?
! A- n0 @% m1 ~
& K- n' _' H8 q8 U9 V6 O+ h
7 N. E! o. m9 x- A, J0 W% d8 D, N/ \
void LCMInit(void);5 S( g2 {! _( s$ p% N/ P8 L
void DisplayOneChar(uchar X, uchar Y, uchar DData);
3 J! j3 j* W8 d zvoid DisplayListChar(uchar X, uchar Y, uchar *DData);3 v7 }: V ]" A, k: W T
void Delay5Ms(void);4 \& _6 _1 r/ s
void Delay100Ms(void);
8 a4 w& M6 R( [( c
" y7 |+ X% @: F! k; cvoid WriteDataLCM(uchar WDLCM);
X. x" |: n+ k' C! p" j) i' cvoid WriteCommandLCM(uchar WCLCM,BuysC);% y5 p+ P; B6 p) [1 K$ @! s1 K4 c7 K
( L* B; X0 @$ Z" f
0 g6 J w& ~4 K. L4 E6 n1 d1 Xdata float distant=0.0;
' c2 a- f' ` O; A4 d. b2 N) E0 Duchar ReadDataLCM(void);
+ U7 m( \' s! H! Guchar ReadStatusLCM(void);: e, ^9 i6 A# b9 A, D- m
uchar cdle_net[] = {"--Daoche_Leida--"};
) Y5 P" l% k- ^$ }uchar email[] = {"Juli:"};6 ?8 e4 n! W! T4 ~2 q
uchar cls[]={" "};
: a x4 j; p$ E' uuchar DIS[7];( m1 I' T1 b; S; o* B* }% S1 r
data ulong time;
1 j/ E# N9 L# a! A6 q) b1 ffloat distant;
* I' v- I& P( Z1 `+ Ksbit LCM_RS=P1^1; //定义LCD引脚9 _0 g: Z! H8 T6 G8 i1 w+ A* k/ l
sbit LCM_RW=P1^2;
( W) C" S) Y) q8 A/ G: ysbit LCM_E=P1^3; * ]- K* ?* w/ u0 r
sbit P10=P1^0;, d* B* B4 M7 {3 z
7 ?; P8 t& U' U4 b5 [& {1 i# L
7 W1 d0 B+ m2 J7 V3 J7 x- j' n; Gdata uchar flag;5 g) Q" Q$ A9 y! D/ w4 x G
; O1 ^8 _8 P" |( [8 l& ~9 q# ^
void zhuanhuan(float juli)% W5 s0 q; Z8 X+ L
{
5 E6 j3 O4 C( n7 funsigned long juli1;( G: V: K' o* ~0 K1 _1 k1 c
juli1=juli*100;. K" q9 j7 c- P( m# y
DIS[6]=juli1%10+0x30;" g. ^6 e+ Z7 x" x
juli1=juli1/10;
9 j: e! W5 M9 J1 j* [DIS[5]=juli1%10+0x30;
6 j) x4 h, f9 S8 F7 w6 Vjuli1=juli1/10;
% a0 x+ s+ z7 E5 q8 LDIS[4]='.';% M# R9 R2 ]5 s* W x
DIS[3]=juli1%10+0x30;
1 B% l' q& |6 V5 V6 sjuli1=juli1/10;
7 c% V* }3 c) \DIS[2]=juli1%10+0x30;; ]0 ^; I8 j7 F v, j+ _5 X. W
juli1=juli1/10;3 M" o+ L3 g: v \3 t0 A6 {
DIS[1]=juli1%10+0x30;4 P0 H# s( ?: n1 \1 K
DIS[0]=juli1/10+0x30;
4 a$ w' v* e. e& Q1 ~8 {5 P; U- C* `5 i! |! r
}
5 G) B5 D; ]+ y! \) N
7 r, Y, _. d; M& ~8 i: U# E8 Uvoid main(void)
" G6 W7 d7 {# R{7 D) {1 x3 L1 f
2 B' `- ]& o' S0 s0 p/ r2 V7 v Delay100Ms(); //启动等待,等LCM讲入工作状态
8 ^4 H8 k( ~# W P10=1; . |+ v. `# P* q2 h# \ i, q+ E
TMOD=0x01; //计数器0工作在方式11 z. C7 y+ @, d% E0 U9 @4 n. N
TH0=0;
" b1 m1 \9 _# q4 r0 n: G TL0=0; //计数值初始化. d. w% s) n; o) d. V
IT1=0; //低电平触发中断; h& y4 w7 L; T- W$ ?
EA=1; //开总中断
8 `3 _$ n. o1 k" _2 m //IP=0x04; //设置外部中断1为高优先级中断) y3 ]; N, ~" W& U4 l+ K
flag=0;. M) \+ j1 ?3 ^
LCMInit(); //LCM初始化7 T) f, K4 c. A: N1 R) e
Z$ L2 y. K+ E' _) V
8 U5 w3 _) j' F2 X/ {" S
while(1)
' E1 N, G$ G) p: f4 M* h$ V+ M {2 I! d2 A+ l+ G, H& N' J
cs_t();
6 b5 a ]2 T; _2 t Delay5Ms();
2 E- ^4 X4 P! ^( h" f, R9 N' v ET0=1; //打开计数器0中断% a6 `/ Y5 g# [
EX1=1; //打开外部中断1
0 V0 S' n5 z: `/ R% D TR0=1;
& k- r# }- Y+ g( ]2 A7 U4 d while(!flag)
' d( W2 ~( J' H3 c% K z' ]0 A: c {7 i, @* z2 K, m# R% ^ J _! E
DisplayListChar(0, 0, cdle_net);7 n* m( H/ z6 H! r+ Q7 {, U8 Z
DisplayListChar(0, 1, email);& r$ x: A# Q" f+ S! [
}
& W9 B7 r# {. b; `& m2 a" N$ W: W if(flag==1)1 }5 J0 C5 ?4 R7 e6 N( Z8 j
{
8 M! F& C* E3 N# O; R time=TH0;5 ^* B6 Q w" I/ W! [" s9 U
time=(time<<8)|TL0;: ~& i& X& D6 _% a7 b
distant=time*1.72/100;2 Q. N5 y& g" ]: ?5 ?! }- Z3 q
zhuanhuan(distant);) v( _3 |* U" q) H& p8 U( C
if(DIS[0]=='0') DisplayOneChar(5,1,' ');
- E0 _% N' L- Y( K! y1 C8 Q else DisplayOneChar(5,1,DIS[0]);
/ d/ [( I5 D! Q% \& k if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');7 l# ?# V! s* Q# K1 u% w7 ^
else DisplayOneChar(6,1,DIS[1]);
: f0 d9 t$ m% ` if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');
5 q: s% ], T' p% Y( j$ W; d else DisplayOneChar(7,1,DIS[2]);
1 K* {* x# l% Q! j1 e- N* M4 F. ` DisplayOneChar(8,1,DIS[3]);' f$ ]+ K8 I& |
DisplayOneChar(9,1,DIS[4]);
1 q% Y0 D5 o# T) k. A5 U- { DisplayOneChar(10,1,DIS[5]);
$ M) A, s9 D8 @' R9 ~ DisplayOneChar(11,1,DIS[6]);
" {: j$ R! _& i DisplayOneChar(12,1,'c');
4 n0 m( B: e6 Q L. i DisplayOneChar(13,1,'m');* l9 T' K" E) N- C
flag=0;
n' q" D7 f8 s) y0 _1 }, J" h) T }
( @; F5 ?) _+ G" N' y else
6 g4 q, j2 {1 J {$ _+ \$ F3 b! P$ l2 n7 ~
DisplayListChar(5,1,"error! ");
7 G% l5 u+ k' d1 L; l flag=0;+ W1 N) C/ {) C) S# ]. |
}& N/ K; V7 i4 G6 ~. d
TH0=0;, f7 L9 k, D) R! Z3 Y& K9 Z
TL0=0;. u, L. u: n" K6 V6 s ^1 K2 l
Delay100Ms();: g5 h% k6 X( b, t9 i
}
5 b) o' a; T# g}( g+ \* d* @7 P5 b3 |2 j! N, u* ^
) ?% q- L' K' {- C2 i- @9 ?. V4 v V8 ~* D/ Q; s
; l `+ Q/ V& F% r
void cs_r(void) interrupt 2
, Q* A z/ X5 Y4 B, w{1 B# K/ a& C6 j9 f6 k; j' C
TR0=0;* M5 M% N5 j9 R7 \5 b
EX1=0;# y5 {3 H' W+ W ]
ET0=0;1 N+ h. F" [, t- s/ h4 T
flag=1;! e1 m& Y' l& A1 \$ q
}
" p: g% @3 q! w: y* i# F
& E( L; s* D) `, [( `# ]- ^
5 y* ? s; O8 Z/ X5 a3 }void overtime(void) interrupt 1
7 i/ E$ a) l& l' H{8 h9 N S! e" h! f: b/ a
EX1=0;; Q4 x- j [/ Q6 G8 E7 a1 ^9 l8 p
TR0=0;
9 N6 [9 C7 a b i/ {! A8 NET0=0;# ?3 r. q8 M" O( w
flag=2;. K0 ?/ l: i1 t7 l
}
4 Z, x! b+ N: c4 R0 r# _4 S j
`7 @0 E: t9 A/ E0 ~$ l
: v, r! B) R" n: ~9 {//写数据
: q6 d# H$ L* K# y: R3 N7 @void WriteDataLCM(uchar WDLCM) 4 V0 f! L, O" C! P
{
2 s7 y. l/ n L ReadStatusLCM(); //检测忙
4 V. p/ `9 E1 \) d5 j0 Y1 p$ _; O LCM_Data=WDLCM;: R. X; \0 J1 M7 r
LCM_RS=1;: o! e& W+ C; ]8 G
LCM_RW=0;
- w$ v: }7 U4 ?/ e' y! V" G% j LCM_E=0; //若晶振速度太高可以在这后加小的延时3 s! S' y8 p( T! {
LCM_E=0; //延时
\& j3 G6 P- L* v* n/ ` LCM_E=1;
, @9 x5 @( O( ?5 q+ p/ T1 E}0 _8 ]: y. K: r. H
( p9 F1 X6 h$ E* Q7 u
//写指令
. T3 K% ?5 ]6 E8 b. P0 a9 b$ F! Dvoid WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测) R% ^9 s8 j) N- p7 u: n
{( D! y% i! I8 @
if (BuysC) ReadStatusLCM(); //根据需要检测忙5 z, X3 M) _; A* G
LCM_Data = WCLCM;
4 F# ~4 c- {9 A4 ]5 ~6 j% ~0 A) {4 r8 p LCM_RS = 0;$ o1 `6 a2 w7 L& P
LCM_RW = 0; ( J/ Q0 D& y" b6 J( i' x6 T! W) ^4 {
LCM_E = 0;$ @" O) E. A L! y
LCM_E = 0;
, r- L. a- J" t6 D: D0 } LCM_E = 1; - m& C: C3 f4 I: `
}
* |$ M; J1 _; }( [ c0 A# N; }' I1 a* Q: O9 V' g$ j5 X9 F8 S
//读数据* [. Z7 n% J+ X
uchar ReadDataLCM(void)
1 \/ Y! g$ v( Q6 g k{
& G% D7 H7 p/ O LCM_RS = 1;
7 O4 G& J1 m; X' b4 I LCM_RW = 1;
1 l7 O5 y, } \+ i$ m; s `! N! Y LCM_E = 0;
* \( F& m ^( M, a, o/ h7 ^: d LCM_E = 0;' q9 d4 I |0 }# q/ q+ ~( r
LCM_E = 1;! a W G8 I7 S1 P* r
return(LCM_Data);
$ s- ^' d$ ?& M" w1 o) J# z! Z}" H; A/ z/ m) s
. |0 I$ z' p. t- C//读状态/ }) [3 h$ b2 d/ A
uchar ReadStatusLCM(void)6 ^" E( O6 d; |- |( v
{" O S6 M6 Z7 @5 k9 Q w1 @( p$ B
LCM_Data=0xFF; ! s. q: O# J: G6 @5 R- K; N! Z
LCM_RS=0;! B2 S9 g7 A; L% r/ K
LCM_RW=1;
- l6 E; q/ x4 {8 ~: C1 b LCM_E=0;3 O! r0 {% `. H2 [" c- K4 R
LCM_E=0;# [$ {2 h1 ~# K# T- h; a0 c
LCM_E=1;8 M3 C8 c6 j% ]- ^* i8 i @$ e
while(LCM_Data & Busy); //检测忙信号( y) c, L" m9 A# R: _- O# {4 \1 ?
return(LCM_Data);8 k! |& O# |% S) n. j# q% f
}
; X* }5 Q; I( Q: z% w
) [, i) N6 C. Q+ f0 O! ?, t2 fvoid LCMInit(void) //LCM初始化0 L! M9 t: A. n+ q. e9 Y
{
7 Y- R7 x8 Q- m- ~# g LCM_Data=0;7 I# N% c, D d# {
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号: K7 k3 Y* d! U. i+ P
Delay5Ms();
% \, T/ v- {+ j* S1 C WriteCommandLCM(0x38,0);
5 n5 U g: k; X Delay5Ms();
+ O1 |9 c4 ?9 z WriteCommandLCM(0x38,0);
; ?) d& ]3 v$ W2 k, K Delay5Ms(); 2 W: u5 `2 _; q7 U+ F
0 m; i( Z4 q$ F& U! Q0 w WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号- Q4 \# t/ _' n. p; q. o& z: T
WriteCommandLCM(0x08,1); //关闭显示
U; H4 U$ V8 y& F WriteCommandLCM(0x01,1); //显示清屏4 a( _6 b( k+ b$ E4 G- a. {- ]1 q
WriteCommandLCM(0x06,1); // 显示光标移动设置
6 i' C; y3 g0 k9 b WriteCommandLCM(0x0F,1); // 显示开及光标设置, G% z8 c- w4 T+ h( {
}
( M/ Q' U( X+ h H7 Q0 o |) W6 z# s0 u$ E3 Z' u2 n
//按指定位置显示一个字符& D' [" z( D7 J/ k6 `1 \
void DisplayOneChar(uchar X, uchar Y, uchar DData)+ |2 J& p, z( y* q
{# q( `3 N8 @* j/ u7 O
Y &= 0x1;
8 A1 I4 `* B0 w4 v: a0 \4 f6 B X &= 0xF; //限制X不能大于15,Y不能大于17 ^+ l6 z D9 K; T& x' [* q/ W, B
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
5 f/ T; e& F! Z, C( V6 | X |= 0x80; //算出指令码7 d2 U* y4 V& X$ r0 ~4 { u: F
WriteCommandLCM(X, 1); //发命令字) w+ W0 g! {6 O" Z& B4 @+ I
WriteDataLCM(DData); //发数据+ ?$ `1 T4 c/ {- x) R* U8 x4 p
}+ A8 A& F6 R4 q' s+ p
2 O7 i9 z c: S% J0 ]+ Z
//按指定位置显示一串字符
/ g8 f7 f( K8 N0 }" qvoid DisplayListChar(uchar X, uchar Y, uchar *DData)
' ^+ D, m: r- Y* @( P: z{1 u; _# U2 S( ?% e7 b7 i7 }7 h
uchar ListLength;3 E$ j& U! |9 m _0 M' R
6 ~0 B( x/ U( ? ListLength = 0;, [) b+ U( }/ E+ n% c a
Y &= 0x1;
1 l2 W" U! _7 {4 b( ? X &= 0xF; //限制X不能大于15,Y不能大于1
) P5 O8 x! k+ x5 T3 ] while (DData[ListLength]>0x20) //若到达字串尾则退出
1 W( s8 W+ e% u z+ X5 h9 L3 m {9 ?1 q6 }6 x1 G9 B( }! L% s
if (X <= 0xF) //X坐标应小于0xF* p8 O; `' u& a
{- F- `4 j* g; E
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
- M" X& n& y% V6 I) ]1 |7 z+ U! ~+ _ ListLength++;
8 ?" y$ X5 Q) w! w1 b' |7 }5 f' y X++;/ _6 K, t0 y( G F9 M/ N
}
' }! Q3 l) Q) Y B L1 b& m }7 f7 N0 W$ i- {# X
}" }. D; ?2 e) K2 o8 P1 V
i e( w; `8 ]2 V4 O) D
//5ms延时
( t/ x, c! B ?0 e" Rvoid Delay5Ms(void)- T e9 ?6 A. D( T2 W1 W! l( e' j X
{
5 o1 _6 ?1 t0 b/ @0 n uint TempCyc = 200;
7 d% Y$ }2 P8 T3 J* I! @ while(TempCyc--);
3 S! \ n" N; F7 x2 R, y& P, E}
4 O: G+ p( Y! ^6 h" c" d( a1 {% o1 @" T+ ~5 q
//400ms延时
- ]! G" I# S; C$ Rvoid Delay100Ms(void)
* y0 R K: L7 ~' H$ w7 q{
6 n! i3 S g# R1 q uchar TempCycA = 1;
1 V# m- `. [+ N uint TempCycB;
2 \ T0 @: B& s1 g$ s D9 T while(TempCycA--)1 M4 x; t3 r" r* `# B0 F) n+ z
{
7 z5 M7 x0 U! f8 q* {' q TempCycB=7269;3 c1 W: d8 F+ @5 \6 U, R/ b y
while(TempCycB--);' R& F$ ^8 ~2 @+ j$ Y( D
}
" U$ r/ S0 b5 d. n- I3 W: M} |
|