|
|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。
% e6 |& K% Z8 X# A! S硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。
8 c# ?! F6 }- |4 ]) `# E液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。
q, H" L9 T7 z6 q5 f超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。: t4 _: g' |) D8 w3 p, O
超声波的接收电路包含一块CD40106处理芯片。1 \% c; A5 Q" A! O0 [
技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。
' c& l j, j: T! ?1 K#include<reg51.h>% V( y& ]5 i M; y: b, n7 J% }
#include <intrins.h>
" n0 ?4 r: g- _4 H5 ?+ n* M8 p6 O#define Busy 0x80 //用于检测LCM状态字中的Busy标识
U: e+ V! ~0 e. N) ?#define LCM_Data P0 + w! b% c1 Y& C5 ]! K% E7 k$ G
#define uchar unsigned char8 }/ v8 e, i3 E' D
#define uint unsigned int% c5 N1 l4 L' k( C" T/ X
#define ulong unsigned long
' }# A, R) c! q" o) W2 {' \8 N$ [4 I5 b- C, O8 D9 y& H# e
. H/ _- x5 A7 ]; [& @
extern void cs_t(void);2 O' L4 ]' D1 b; ^3 g$ @- D* ]8 S
extern void delay(uint);
! B: @! \" V9 H5 q( z8 B: \
: T9 q( l4 E& |" F9 ^, F/ m1 T7 N9 e8 J' _1 t1 V9 U" Z
6 Q) g" s2 g/ a. Fvoid LCMInit(void);
" L0 {9 H4 w7 Xvoid DisplayOneChar(uchar X, uchar Y, uchar DData);; U. E) s( C& n* n) [+ X
void DisplayListChar(uchar X, uchar Y, uchar *DData);
n: C3 j+ G& ^+ c4 R7 Evoid Delay5Ms(void);7 }, i, C( @" G; x3 }2 X1 H
void Delay100Ms(void);
) i/ |2 S- z' U5 _0 }- I2 c" a( z1 C0 `8 V$ T3 j
void WriteDataLCM(uchar WDLCM);
# O1 P9 N. B$ ~ I# E. bvoid WriteCommandLCM(uchar WCLCM,BuysC);. B0 M8 y1 o9 s) e0 r5 [' Y
& l% H; O3 X" _& |: H3 i7 b
$ t' ^5 i- ]6 b8 d ldata float distant=0.0;
6 R; r3 J6 B# r. Q; Uuchar ReadDataLCM(void);
6 ]: P# i( @0 R7 s0 kuchar ReadStatusLCM(void);
; q# H8 y4 y( R* o; Euchar cdle_net[] = {"--Daoche_Leida--"};
- j( |6 ?% G& \, E( a/ x/ ]2 H6 muchar email[] = {"Juli:"};
1 H% b* ]: |2 [+ u: l/ U* buchar cls[]={" "};
0 w) f' z6 V7 t+ i% q2 Juchar DIS[7];
' L0 u7 `( d) Bdata ulong time;/ O1 ^ f! U6 l; j1 D
float distant;
% g+ n' F9 ^% Q( t! Psbit LCM_RS=P1^1; //定义LCD引脚2 F- N5 z9 `& P4 P, a
sbit LCM_RW=P1^2; % v5 l7 D1 @! P1 ?7 f f6 t2 P3 g
sbit LCM_E=P1^3; & ~- ?1 E, f- Q, T
sbit P10=P1^0;# q! k% ?8 g9 A: c/ G
4 ~2 x7 n" B3 | M+ j: f# [) u$ ^/ _; [
data uchar flag;
7 k1 e2 r7 i9 i9 r! S( f+ e7 g2 v/ g4 `6 \* |2 s
void zhuanhuan(float juli)
/ M. h/ N7 f- s# x; l8 e0 Y9 h7 j{) s. k- c K" q' T
unsigned long juli1;
2 `: F1 h8 B9 I9 K& O& sjuli1=juli*100;
* t! l+ q. b" [2 iDIS[6]=juli1%10+0x30;
8 z3 ]! H- D- C+ Vjuli1=juli1/10;
0 \, z, [/ _) V; p8 tDIS[5]=juli1%10+0x30;
8 @' [2 e! R! h( N* ~juli1=juli1/10;
* q9 a5 n9 f& J( |* k0 ]DIS[4]='.';
, |4 @+ ^( u% t( ?5 z9 RDIS[3]=juli1%10+0x30;
S D* n+ F% }) _( P( S/ Jjuli1=juli1/10;
- D+ h4 N# K& }% \- ]DIS[2]=juli1%10+0x30;
2 w: `1 d1 O8 O; cjuli1=juli1/10;6 t/ N. D# _ c5 ~" q4 `+ B
DIS[1]=juli1%10+0x30;' @7 j6 N( [2 N# ]
DIS[0]=juli1/10+0x30;
; r+ s) h7 V; ~8 _" M
, S9 u6 C7 b! `* B E- w}8 y. U7 _( g, g" L$ V
* Q0 m" m$ }; |void main(void)
/ l$ T }2 e+ w. L3 Q; X# I{% X8 a" a, t2 D( y' J- l
2 M! b6 m( W3 E
Delay100Ms(); //启动等待,等LCM讲入工作状态
4 ?' c% U2 U2 E6 P7 j P10=1; - T+ Y- {( t7 _3 U$ a& V+ M" }/ K' D9 g( _
TMOD=0x01; //计数器0工作在方式1
" c- _* C7 j' P% L TH0=0;
R% [6 n" V; @/ ~ TL0=0; //计数值初始化
' {1 [) D) I- e IT1=0; //低电平触发中断
7 x- C, o$ Z1 m7 n& Q7 m' C EA=1; //开总中断7 S$ v; I' m, e# d! O0 ]2 E- h' N
//IP=0x04; //设置外部中断1为高优先级中断
) ?3 k y. u0 p; K( q& Q flag=0;
" N& _: H4 M1 _+ c LCMInit(); //LCM初始化
7 ]2 ?& O" ]# o, q* Q0 \0 J
7 `" s0 }2 o4 D& u! P3 y3 ~ / J+ U- b$ `: J- d' ^1 v
while(1)* Q( v' f0 W& r0 a! g: I
{
" q6 |* A- S# r. x. p cs_t();4 [+ \ c( W2 N% ~6 L* k
Delay5Ms(); # ]1 W1 n& J) {9 h z( e8 _7 D
ET0=1; //打开计数器0中断
( u p& L% @4 @9 k0 Y, h EX1=1; //打开外部中断1, L+ h, ^9 ^3 T. O' S
TR0=1;* D5 `! K% h) V8 U# h I4 X
while(!flag) 5 g$ ?, A ~# k
{
3 v: i# q" F5 _ J9 \: j8 T7 z6 U2 w DisplayListChar(0, 0, cdle_net);
4 i; _9 x% p7 z, B" S, I DisplayListChar(0, 1, email);
! f6 Z! @. f+ k+ m: T: B! [/ s }# l4 k9 A6 B, u- J. T p
if(flag==1)
' q# S5 c- q; n) G7 E; w7 E- m. H {
4 Q$ L% |, [! I time=TH0;& U' Y3 O9 O6 l! v# k
time=(time<<8)|TL0;
* \) J( }3 V- T8 I3 _7 |% H+ l distant=time*1.72/100;
' |6 j& |1 R9 J1 n, M$ w* P zhuanhuan(distant);
( }" h1 q$ H" _ if(DIS[0]=='0') DisplayOneChar(5,1,' ');
+ j; G9 u9 N2 g) ^ else DisplayOneChar(5,1,DIS[0]);
7 ^" G6 S3 X8 n" e9 F1 z if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');
$ N+ g: Q, b3 H' C/ _* C8 | else DisplayOneChar(6,1,DIS[1]);, Q7 J8 g7 [ N" D
if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');# c, {% L1 J x2 x/ i
else DisplayOneChar(7,1,DIS[2]);8 P- P: C. Z2 s4 G
DisplayOneChar(8,1,DIS[3]);/ T' u1 `. r1 U! ^/ M. s
DisplayOneChar(9,1,DIS[4]);2 q* p6 @( S# C- U
DisplayOneChar(10,1,DIS[5]);
, n: g6 Y# W1 O' G6 U7 d% k DisplayOneChar(11,1,DIS[6]);
4 U9 U+ W- `/ k9 {4 R- F, o DisplayOneChar(12,1,'c');
- H x8 |, \ S DisplayOneChar(13,1,'m');4 N7 b7 N0 q" x# r+ `* ]
flag=0;+ x {) x s# h4 o b
}: M' m/ O* P* l/ {# ^( i5 O
else- Z, u5 t& g5 }( u8 g
{7 ]+ f# ?" f* h: H" S
DisplayListChar(5,1,"error! ");
5 u$ @$ U7 L5 ]5 [, ` flag=0;
* i+ t# Y* i& v5 w3 M @* R7 ~ O1 { }
$ ?" m- ?! N. W: ^4 I- t TH0=0;
* o4 A9 n7 O2 V TL0=0;; ~2 C5 g* T, o
Delay100Ms();
! [/ \' g, U) d0 j' X }
& c6 ~3 s7 m9 C" s+ e& f- c# R}
* Q& m; P, j" W# B& ~$ T5 ?/ e" l4 O/ p+ V. Q1 k
) T, Z2 m$ R4 P8 l4 ^. U" O
! X6 e8 T: |. n; W5 ]) X
void cs_r(void) interrupt 2
s/ D: L% }3 O9 B3 ^) ^6 C9 q{
0 X" B# F4 R/ OTR0=0;8 O) j- d. b0 [4 a c) t6 J' P; h
EX1=0;# B0 Z/ \+ M7 ~$ x7 h: K; y
ET0=0;9 t0 e& D2 z H: H. C, G# \+ Y2 q; k' C
flag=1;8 {( R% }; O6 K/ M
}) D3 B: w' v$ l+ ? N
* y) b/ V. z2 Y, Z6 u& x$ v9 x) R* e6 F5 c* q7 ~( H1 j ]
void overtime(void) interrupt 1
, z7 z& ^, U* w{
" L& L: L) s1 z8 e) T! aEX1=0;4 }6 O0 w+ F1 v4 z* N
TR0=0;
* o6 u7 ]* r8 o, [0 u( l, HET0=0;0 U; e1 g! _% u _$ v2 _
flag=2;/ q/ ~/ ?3 P! j( M5 G
}
* I) @( B4 Q7 i4 ?" F
1 c7 V0 w2 ~0 {; B% n) W4 V4 `
//写数据
; x# m! u& x6 u: n8 }. Fvoid WriteDataLCM(uchar WDLCM)
8 [( H2 n S9 `6 X4 d' k: |{
4 t4 y! A' T; H4 T ReadStatusLCM(); //检测忙$ | c8 f" [( M2 Z6 D
LCM_Data=WDLCM;
) A$ B% F+ \7 O LCM_RS=1;
% c: p! Q/ v6 N LCM_RW=0;+ M3 t$ c* f" G- p
LCM_E=0; //若晶振速度太高可以在这后加小的延时2 W) M! J5 V3 E
LCM_E=0; //延时6 Y; E: w# s. @
LCM_E=1;! N5 u: h& h6 Z* j4 O4 A5 u
}
& `) T c8 Y/ [* Q0 c7 i2 q. o1 p' x' ~$ l6 E
//写指令$ ] r& A' n0 q, k3 T8 a
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测
3 P6 C+ I6 b) {" ?# h0 `{% o5 X; G+ u: K+ s U' H# |
if (BuysC) ReadStatusLCM(); //根据需要检测忙8 o1 G3 S8 g/ x8 V. D1 F; J
LCM_Data = WCLCM;
# D, E0 @- J% o LCM_RS = 0;5 X; r0 o- {1 y: i- B. U; [. t
LCM_RW = 0;
7 M/ [: n, N+ I0 ]/ Y LCM_E = 0;
! b5 ?5 k. S& i8 \5 s+ U' D LCM_E = 0;
* Q9 o8 [: u/ q% G# V9 m LCM_E = 1; ; m- x: k- n! N- s, ]0 F, F, Q) A
}* ~! T( e3 M9 M1 G; |$ F% \' |0 l
7 b/ {; a6 K% ~, E; ^9 t% s9 ~
//读数据1 L# c3 W: X" P9 M4 J
uchar ReadDataLCM(void)
. e% @+ u4 Y* c4 B' L2 K6 c{
/ ~- b: |1 Z D n% c LCM_RS = 1; 6 j' d* N. u, d: y% [6 l
LCM_RW = 1;
; X7 Q# r+ d/ f, W8 W1 T; @ LCM_E = 0;& ~ a' ~: a; c; }4 N% w! c
LCM_E = 0;
; }: Q1 m! M6 {5 @0 _ LCM_E = 1;" ]2 h5 L1 g/ T* D0 a: ]) L
return(LCM_Data);! _) G% U2 M9 Z2 }
}* X8 o6 g, _: D+ z5 V9 V/ _1 A
& v. e! w* n1 g0 L" l//读状态
; N5 d- }9 C L* @8 Wuchar ReadStatusLCM(void)- y' ?& ~. m* h" r
{% Z) H, R/ |! D: b$ l- M
LCM_Data=0xFF; . a x: p3 y' |( Y
LCM_RS=0;
# P3 c! _, @1 T8 T5 K; b' { LCM_RW=1;5 v! J- ~! V1 p& ]" L
LCM_E=0;" X o, U4 L# s; T, R: z* u
LCM_E=0;
( H/ _* c( O4 t1 \' d. ~1 l LCM_E=1;. B( R8 p* _# Z# g% t
while(LCM_Data & Busy); //检测忙信号
2 b! U" s! w( e# j s return(LCM_Data);+ }2 @( {7 \% T9 L: L
}
, u9 b, M B- Q1 @) j( m0 [$ x; m5 ~8 ]& K. V" d
void LCMInit(void) //LCM初始化
* i$ l2 x: M) z3 g" z2 J' Q{
, [; e% m; `( K! | LCM_Data=0; o( y$ r+ Q& D, l* X5 P% _( Y7 `
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
8 p1 l3 Q& D$ M: W3 W Q& A; b2 D Delay5Ms(); 0 B( A( A6 Z( X$ c: j$ ?6 _% x
WriteCommandLCM(0x38,0);
( g8 x$ T% o/ k8 p! V7 d Delay5Ms(); & ]0 v D! ~2 N7 g
WriteCommandLCM(0x38,0);
1 [% }5 O- @6 U Delay5Ms();
3 Y w, o. i+ Z6 [1 p/ i6 O
* r4 i1 a9 q: z: m WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
* Q/ {" q4 E, F- B: b WriteCommandLCM(0x08,1); //关闭显示
" `8 |# T8 w) a" s4 ^. }2 d WriteCommandLCM(0x01,1); //显示清屏/ b, b, A: f) d1 o/ o
WriteCommandLCM(0x06,1); // 显示光标移动设置
9 \4 V& q$ b7 T X, X+ [ WriteCommandLCM(0x0F,1); // 显示开及光标设置+ \. X8 }$ n/ E G! G4 y5 c0 l# {
}% h0 M$ G" u8 v1 ^8 B- a
& [6 ~+ C6 Q& w( H//按指定位置显示一个字符
# U! v7 R R3 a$ V( {void DisplayOneChar(uchar X, uchar Y, uchar DData)3 P& ^7 `2 q% R1 ^7 Y
{
5 d6 I4 g, R. } _ Y &= 0x1;! y2 {6 d8 g5 D2 u
X &= 0xF; //限制X不能大于15,Y不能大于1
, a2 \$ A( `7 L# @* i" I if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;% p0 `, Y6 [: f& T& u; T n
X |= 0x80; //算出指令码& [5 n7 z0 n# g1 \/ L
WriteCommandLCM(X, 1); //发命令字! K# N4 v' S0 |, t0 J. n
WriteDataLCM(DData); //发数据
% h+ q) |2 ^2 ?9 m} a: H7 H) R2 S/ y6 M
. c0 U; {1 o, U* s//按指定位置显示一串字符7 C1 ]5 \. j! x& c7 }7 h
void DisplayListChar(uchar X, uchar Y, uchar *DData)6 M/ B% c4 f X. t6 \( Z$ X' T
{ D H% _3 Y! J9 \3 i
uchar ListLength;
) o* G$ s1 l. r8 I; p( K6 L% K. r9 @2 u: z7 Y/ F
ListLength = 0;# @# _7 d- _# y
Y &= 0x1;
9 S; F5 r8 e4 I X &= 0xF; //限制X不能大于15,Y不能大于1) X& ^% M2 h& _8 t
while (DData[ListLength]>0x20) //若到达字串尾则退出# r, f o# I; S5 }) d
{" X! ~( i% {/ G# }2 w5 t
if (X <= 0xF) //X坐标应小于0xF
) h; m2 t( [3 n$ v0 B6 O {# g. G' p ?+ L+ C8 h
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
2 m; O# I/ t- t- p ListLength++;8 L/ Y; E# y5 O8 g% D
X++;
S' [( I; K; J f( Q6 d }% A7 \ }
% l& A1 z& N* `9 \7 ]2 R }0 j" G8 [) c- D2 u/ ~: Y5 |/ M
}
6 w, o+ I0 T" \. h. q, A' q# g9 }' a
//5ms延时
0 b) ]3 e3 W1 d# K3 P/ x% @% ^$ I+ I3 wvoid Delay5Ms(void)
- d) C% ^; {, g1 C& y n{
5 n; w+ r8 T/ d" p9 d# [ uint TempCyc = 200;3 K. F# Z) P. V8 c
while(TempCyc--);9 _% K( ^. ]3 P
}
' V5 _4 F3 j) G* u) i5 {# a+ s2 K5 S! k$ Z. ~. U" n" }
//400ms延时# |: i# e' H- w. z$ r
void Delay100Ms(void)
R) L2 r4 J! j1 q$ `, x! o* y{
, m( ~8 D P7 [! l/ I( y& G9 f( ]% \9 i uchar TempCycA = 1;
7 `7 R3 s H0 y, k e$ a uint TempCycB;
/ {- m D6 H/ j5 s* \9 ~ while(TempCycA--)
% ]* N0 i" u' d @ {6 Q1 {! {& Q! Z8 w( t# `& x# m
TempCycB=7269;
( J3 K! D1 c; s& V2 C- |3 u2 e, L0 i E while(TempCycB--);
# k! Z! Q9 A7 q& y3 q8 k }' F9 c2 R% b2 W# Z" h
} |
|