|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。
$ \, O6 H" ]; R硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。2 ]. Z* z! U; `- o1 p" X
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。. d$ @+ k2 l, |: F+ }# a2 e2 `; [
超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。/ }7 [5 j# c7 p4 i7 l
超声波的接收电路包含一块CD40106处理芯片。8 y1 ^$ L& R. ?0 u+ E2 p" D
技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。$ U: s% {/ c, g5 F2 `* G. g
#include<reg51.h>* }) N5 V, Q" j+ p+ v
#include <intrins.h>0 _; M3 Z l7 }" U) B9 t
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
% T& _1 C- u' ^8 s, O, P4 d) ?1 c) ^#define LCM_Data P0
' a+ R! v6 T5 o2 h#define uchar unsigned char2 `& x3 k) r9 V$ k4 }
#define uint unsigned int6 N1 [3 B4 x! K0 S: A
#define ulong unsigned long
* V5 V$ o9 e* t! z/ m2 W
6 s7 i8 p- Z) A3 u% r; r
# @9 f) A9 Z' |& j* j9 Iextern void cs_t(void);
6 p0 R8 b, o% i) e$ y4 textern void delay(uint);
9 r+ v! g8 |; Z% |7 [4 h8 V% r/ a1 ^9 u$ G
/ f' ]7 w1 X0 d8 d* o* T5 J
0 b9 f' L4 o: Y$ Evoid LCMInit(void);
2 t. c F8 V- k. a3 qvoid DisplayOneChar(uchar X, uchar Y, uchar DData);
" r2 a0 \2 N6 m5 g- c1 j# X! } w+ [void DisplayListChar(uchar X, uchar Y, uchar *DData);
% l$ u- v2 }( h* Q- evoid Delay5Ms(void);6 r6 v8 O# d% ^# z6 M) }3 l. J
void Delay100Ms(void);
z# c# T6 T' S1 _& h' a N/ Y( Q, Y* P/ D' V2 M3 W0 A
void WriteDataLCM(uchar WDLCM);# Y- }% p! V+ V g- d: s
void WriteCommandLCM(uchar WCLCM,BuysC);
6 `- X1 C; v3 n* n: G
9 g* X3 E8 n% ^2 N
. C. u8 d8 o# p) d1 J2 z9 Adata float distant=0.0;! W" w8 K+ L6 { ^7 v: s# e
uchar ReadDataLCM(void);
6 p* p) T0 H" Q$ f) suchar ReadStatusLCM(void);
, t: c- G. V3 D6 tuchar cdle_net[] = {"--Daoche_Leida--"};
: P: u; w/ n- M2 T4 g8 b. d: G$ @uchar email[] = {"Juli:"};' S" }, F: d$ m& v
uchar cls[]={" "};
) j1 p: z8 M# R1 i9 o$ X) k$ C4 Ouchar DIS[7];
. {' S$ d* a1 z/ L6 \7 E, ?; ]data ulong time;) h0 S, ?- [, e$ O7 z
float distant;
$ i; l# F) U8 u7 B! z' Ksbit LCM_RS=P1^1; //定义LCD引脚
# O* N; x. P( F& Bsbit LCM_RW=P1^2; 9 l8 q' @+ `3 I0 V% [
sbit LCM_E=P1^3;
* W5 H6 | p/ F9 B. \9 B' O+ E! msbit P10=P1^0;
& ?' x2 f! l) ^& }6 k# D: N! R0 u2 M3 e9 a( [+ Z0 g% u: v9 x: g
5 ]* d& N4 f( a Z$ Bdata uchar flag;; t4 p0 H' H- i9 F
}. H2 F* W4 u, [void zhuanhuan(float juli)
+ M" g( ^( a4 F/ ?{9 H* j! D! i* Z2 o" p# W
unsigned long juli1;/ u6 E& `4 b) N5 S# l6 N
juli1=juli*100;' G+ O v" B& M4 e3 k% O
DIS[6]=juli1%10+0x30;
8 f3 r$ {; {) t f7 V, [' v8 Ejuli1=juli1/10; f E. m) K! s! w
DIS[5]=juli1%10+0x30;) ?; n, k: P$ s+ M
juli1=juli1/10;
$ N: [, f: Z8 `; D8 K1 B9 R8 zDIS[4]='.';
/ n c& }! [+ a! V; LDIS[3]=juli1%10+0x30;
/ H3 t; A1 o) N% e' a! a/ \juli1=juli1/10;
/ T6 i% e7 l/ F$ S: k) lDIS[2]=juli1%10+0x30;1 o$ Z# A6 w* f& z4 j8 @) a
juli1=juli1/10;
' G0 e$ H* f9 j t4 |5 n0 JDIS[1]=juli1%10+0x30;
3 w& j+ |7 B+ Z b* SDIS[0]=juli1/10+0x30;9 l/ h. U7 m; f r) `; e" t
' R9 r0 e1 b/ G$ R& I7 I
}
8 Q+ u2 E2 j8 n# F7 R* ?' z0 K7 D& K0 V
void main(void)4 o# T$ s @2 s
{' f7 M$ |3 ?7 J" E
2 `6 k6 I: ~$ N6 ^" h r
Delay100Ms(); //启动等待,等LCM讲入工作状态 i5 I! n/ ?1 E$ c5 m* l: n- G
P10=1;
3 O& B3 N3 A$ _ TMOD=0x01; //计数器0工作在方式15 e: P( d$ q! i# A" x, O/ y
TH0=0;% V' w9 H/ n( ]+ h/ _5 t( p4 p( _* X
TL0=0; //计数值初始化
7 {: W; j k. t* H IT1=0; //低电平触发中断
- M' s3 t' Y& V6 Q9 w) ?" C EA=1; //开总中断3 d- d& q& L: }( c- k; c1 V; l6 T
//IP=0x04; //设置外部中断1为高优先级中断; {$ V, D" l( B! ?, a
flag=0;5 y0 R( M1 I6 \! a) K6 r; m; ^4 `
LCMInit(); //LCM初始化2 q5 ?, b* I' u1 b! H' G
: E' J2 b [+ q3 J( e- t+ C( Z# D
4 z z3 m9 `8 \" V4 I while(1)
4 M0 {+ n* `2 E {6 n: T" `5 S5 ]. P) b9 @
cs_t();
& B% b7 j1 q; U) C/ S9 C- q0 ~ Delay5Ms();
- Z+ [3 d* c4 E: O* G# ? ET0=1; //打开计数器0中断
' d$ L& s& F2 k0 s EX1=1; //打开外部中断16 m' r( ^: F- r
TR0=1;
6 c# D7 D8 D2 W! |! m while(!flag)
; X9 _/ W6 k% _% j! A {
( Y9 f4 f. L* [4 d7 @2 }8 h DisplayListChar(0, 0, cdle_net);+ m& a& f9 Q* J6 B# J
DisplayListChar(0, 1, email);0 F/ J* T& A3 t' u. m2 K: H
}% G8 t. T* h/ x& x) y! m7 J& Y
if(flag==1)
3 Q8 G# S0 d- ^7 E+ L# I% L {* z7 s6 T+ M& |
time=TH0;" ]2 ~3 K# i; d
time=(time<<8)|TL0;% p, Z3 [5 R4 n4 M
distant=time*1.72/100;* P6 K8 u3 ^' q5 t" b
zhuanhuan(distant);
$ P) r n7 x! I5 T$ ]/ @, [& b- ~& R if(DIS[0]=='0') DisplayOneChar(5,1,' ');
/ \ m( f/ `2 ~& w/ y else DisplayOneChar(5,1,DIS[0]);
6 ~! @. A" N' p: ]8 ^5 I if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' '); D f5 F/ A5 r& y7 o6 J& H
else DisplayOneChar(6,1,DIS[1]);; Y0 [& H. Y0 s" j
if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');: w2 f O1 `9 _1 R/ Q# m1 `
else DisplayOneChar(7,1,DIS[2]);
- p0 `+ v% Z& B. V( H. V DisplayOneChar(8,1,DIS[3]);
4 ]; B4 H& b- n1 `) M7 C DisplayOneChar(9,1,DIS[4]);
' L9 O" b4 ]& Q! s/ }( @ DisplayOneChar(10,1,DIS[5]);1 k! O1 d+ ?) E1 O* E( v& A
DisplayOneChar(11,1,DIS[6]);/ [% k- v+ O* e1 u- W
DisplayOneChar(12,1,'c');
6 S% ]' Y0 d: x. L# s DisplayOneChar(13,1,'m');- A0 G, H) d# \
flag=0;
$ a+ e7 ^, w& i6 k% z5 Z, _7 `; Y9 u }
4 K, N2 W' _0 |9 e- ]6 G2 Y else
1 w; W! I7 m8 h" O1 B {* S$ h+ F$ ^ M, I3 ^
DisplayListChar(5,1,"error! ");* j- a. G K0 n: z0 u+ M' y, l+ \. |
flag=0;
! G7 ]6 @9 Y! ^* [% }: J/ e; m }. h' a+ ~# ^3 {4 R- ~
TH0=0;; ^/ W' N' ]+ g* b% a
TL0=0;
. @* ?( x; Z& A ~* d- R* r8 F& x z Delay100Ms();' K& l [# ^! D; I, ^7 z3 ?2 f
}
1 \4 D4 v6 ]- |) B! d, I6 N% d}3 y6 X7 N- i5 A" w4 j5 y
. _) f0 R$ R! ^
: E# p: I- j; \1 F" }" m9 }9 O3 I9 I
3 \7 u: M4 }9 w4 g( \5 ~6 C: Mvoid cs_r(void) interrupt 2
' M! k* T3 q+ F0 F: X8 I{
" j- ]# D/ `3 q$ d$ N; zTR0=0;
8 f9 }6 v* l% X, ]" u. fEX1=0;/ b3 \& s6 o1 H' A/ U
ET0=0;
8 i# t; q. @2 K( i! @9 Bflag=1;
) c+ l' k, q; n, X8 g- S5 U}2 m4 u7 b3 {1 w8 M% T
* O* ?+ E* j7 ?4 @
3 M2 n- i# x2 V1 S
void overtime(void) interrupt 1
$ c$ l' `* u. b{
9 i: i0 J# a& P3 K5 l* q0 HEX1=0;! a1 x& ~5 O; V& W
TR0=0;! C U# F) Z! z
ET0=0;1 j- Z8 u# z" s4 D0 v3 K+ g( |
flag=2;
. V5 {1 ?0 H9 \7 r b}
1 N* \- J# B5 y6 z2 H* H* |- o$ T' r x6 }' q
# t) ` _ u& n7 s8 W//写数据
" [) g$ m5 b% }" uvoid WriteDataLCM(uchar WDLCM) 9 v9 ^- I' ~% \
{1 S ~( ?& k% w5 j! b
ReadStatusLCM(); //检测忙. _ E, A8 q" K8 `$ _( K) m: ~
LCM_Data=WDLCM;
. r8 `. W' ]9 {* d- g( C LCM_RS=1;
. n0 F' r9 `; N$ g LCM_RW=0;
7 f9 p8 G& D9 Q+ [- c0 c LCM_E=0; //若晶振速度太高可以在这后加小的延时. d1 y5 T% r: t, z# T
LCM_E=0; //延时
% D/ G' @7 C( Y LCM_E=1;
8 D3 L4 }- r+ A9 \}1 U& A6 F1 q# b$ Q" _1 i
/ q; [" S- G( Z* _
//写指令. u* {, Q& S" K# V( a, ?+ q
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测, R+ C9 _+ z8 R/ ?
{: ^' e, v8 F: l1 |9 d7 ]
if (BuysC) ReadStatusLCM(); //根据需要检测忙- {4 P7 C3 l- O4 l2 d1 _4 v
LCM_Data = WCLCM;4 `/ C: m8 F3 [! o/ W4 p
LCM_RS = 0;7 A D$ w, Z" Y* U
LCM_RW = 0;
: X- k" x9 ~6 i5 | Y0 w" ^ LCM_E = 0;
2 F: M. C% I5 [8 A8 D' \ LCM_E = 0;& Y% n- }; |& W: X1 i- Y
LCM_E = 1;
h) p/ K" S' [, {' I}' B5 p) L" ?2 f, v: Y+ @
. B- S1 |6 L$ X7 q3 Y
//读数据3 D& o" g) j/ k) j) _; T/ w
uchar ReadDataLCM(void)
' g4 S0 V8 {# O6 Q7 i& @3 p% i9 w{
+ c& a, I# U# ^, s2 C LCM_RS = 1; & a9 X- m8 k% U1 e6 L& ]. T
LCM_RW = 1;
3 Z8 B1 O* }+ u6 ~+ m' L$ f5 V LCM_E = 0;5 h0 T6 `8 J7 r0 w8 Z+ r% F
LCM_E = 0;
j V# ^4 C& r/ S( ]9 F# Y; c LCM_E = 1;: X8 }4 \& Q/ B. `. U( c
return(LCM_Data);
, S+ v H: D6 q% B}
# p6 D5 a) d8 C- j; U
3 S" ~$ B8 R. q$ C( z//读状态5 x; P' @" y6 x$ ]% [5 |/ X1 z
uchar ReadStatusLCM(void)( E0 m5 p; e6 L$ K9 {6 ]$ X
{7 s1 p! i% I; ^! m3 O
LCM_Data=0xFF;
3 C; P) D, d" P9 z/ p, P LCM_RS=0;
' t- o) `* u: }9 a+ c7 S LCM_RW=1;* B" f, R& U0 Z2 Z+ S+ s' c
LCM_E=0;- g9 n1 u0 y( c# q' y! m2 G P
LCM_E=0;
, e3 h! H0 r. w9 V% o3 Z& m LCM_E=1;7 c8 }6 x. z, o% B' ?2 ~
while(LCM_Data & Busy); //检测忙信号
+ x# |& P% g4 o/ B- s( ~ return(LCM_Data);
& @$ Q" r, |" L6 @" w. }}
, \( `4 p# F* A& e/ A
) ^( _9 w9 O$ A( e4 hvoid LCMInit(void) //LCM初始化% ^, }, Y5 M) A
{
# ~* M+ H5 l, j" v+ f LCM_Data=0;
# M4 W* p( A" a2 | WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号# A; s0 H U- `, u" r
Delay5Ms();
' y' Y4 x' Y1 r6 S; Z% K+ E2 _ WriteCommandLCM(0x38,0);# | ]7 H8 i9 m; A+ E `) b- ?' |
Delay5Ms();
0 ^( l- r" l8 g+ X7 U WriteCommandLCM(0x38,0);
- ?/ b1 ~* f7 `2 K o( N Delay5Ms(); " k4 C6 G. L2 G0 M8 `# C+ W) u1 q
3 v2 t( L) _1 H0 N, j4 x( W
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
6 I% t5 u5 l8 D WriteCommandLCM(0x08,1); //关闭显示 D4 ], e* n5 S5 |- F4 D+ v0 Q
WriteCommandLCM(0x01,1); //显示清屏8 l" {; u. o/ e8 ~: o- v5 L
WriteCommandLCM(0x06,1); // 显示光标移动设置5 a7 Q, t* C3 S- s/ n
WriteCommandLCM(0x0F,1); // 显示开及光标设置
3 [; O7 p) r: m* M5 \+ i}
5 u0 x0 S7 B* K1 E! e8 [; l
% C a3 `/ D% d. e//按指定位置显示一个字符
0 Y- f' G" R" V, ]7 Fvoid DisplayOneChar(uchar X, uchar Y, uchar DData)6 @" R, _" R W0 c# x
{
' F; p R4 E0 V/ t7 I Y &= 0x1;
9 S( |3 c B) d W9 D6 Q X &= 0xF; //限制X不能大于15,Y不能大于1
/ ]; i" D3 ~; D: j( s- _3 D T if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;% ?) Z* d; [. x5 o& K7 _" t: U/ [% x
X |= 0x80; //算出指令码- U. g; O# W3 M
WriteCommandLCM(X, 1); //发命令字
! Z& \2 K; z4 \; ~* H3 k WriteDataLCM(DData); //发数据
5 G2 g' T+ J& @; M}! V) Q5 b, d' F% |- u0 k
( X1 f' W ], C9 s% v//按指定位置显示一串字符
6 [' m- S; ~6 a9 F+ D* o0 ~void DisplayListChar(uchar X, uchar Y, uchar *DData). f% i/ V! j4 ?) _/ e
{+ k% q6 [5 H$ K, ^$ ?( g" l% p$ T
uchar ListLength;' ~5 l$ H" Y9 _, a, ?
: ^! C) D- B% ~! v' @
ListLength = 0;" y6 H0 X1 l# v3 ]' |
Y &= 0x1;
5 [4 c% F, @& z8 m7 w& F' {3 n5 f* o X &= 0xF; //限制X不能大于15,Y不能大于1
# k' ]: o+ u5 D! ]- V while (DData[ListLength]>0x20) //若到达字串尾则退出! J. ]% q9 Z, ^2 Q; a
{
1 v! | P4 s& D& y% j if (X <= 0xF) //X坐标应小于0xF/ L8 j P6 m0 ~* N2 W
{2 Z: `1 m6 |& s. q
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符" K& m/ F; D: x
ListLength++;
3 p3 ` \) {7 }" j/ Y X++;4 E, X3 ^& l5 [; B2 C% Y
}
' v% X9 ]9 R( Y5 p4 } }
* y/ p- X0 d* p' _4 ^/ L8 U}0 y1 U" M& `0 w2 _" @) \! [7 e
$ {" r+ q: ?6 s3 J1 b//5ms延时
3 ^8 R, K+ m# ^$ Lvoid Delay5Ms(void), M: M( X: ^1 V# J1 ?/ [9 n
{; Z' Q' M2 h0 M" [. w% z# e* Y& {" J; c
uint TempCyc = 200;
2 y6 L6 _; t+ h. O% M3 l* x0 Y while(TempCyc--);
$ L/ @2 h, F4 d# F. j0 T}! k& L5 _, R& `( y! `1 c R( D
8 t. s. y9 t* a. ]
//400ms延时
( s' Y6 F' `8 S- e8 y( Yvoid Delay100Ms(void)
' K( M' `, ~. N2 A2 B{
8 K5 S9 J7 F7 A5 g# h% m uchar TempCycA = 1;
4 O: _% {8 Y2 }( q uint TempCycB;, i1 ?/ u. J+ \* ^
while(TempCycA--)' O# V. E+ p' M, r( J# d
{
4 C. [4 }. }' E- g2 @ TempCycB=7269;
- X7 M7 `" U f+ m0 ?0 a7 G7 _- c while(TempCycB--);$ ^" q& w$ D; U# i
}
& o W& v- y4 _1 v. u* e} |
|