|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。/ A4 `& @% \1 M( t2 }
硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。
4 e0 m' x; X- m/ @ M M液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。
- l& K% g9 H' c. x超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。. P7 ^+ m5 C1 t; y7 v' i! A" ^0 r
超声波的接收电路包含一块CD40106处理芯片。! A7 M( j% |( c2 l1 O$ Q$ c. H
技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。. d, d/ G' W9 D$ d/ g6 q' x
#include<reg51.h>
* C; P* K* e1 r" \#include <intrins.h>
! ]& N' B& j' U9 s$ F$ H#define Busy 0x80 //用于检测LCM状态字中的Busy标识
3 V* }1 O8 b- o8 x0 h# e#define LCM_Data P0 ! e+ `3 g! f* o4 D! l$ m
#define uchar unsigned char
) w s& Z X$ |" J: E; t#define uint unsigned int# q. f9 q: [- I0 S/ n) X+ g
#define ulong unsigned long
' d0 X5 Y9 @* t( @! P
! U: N! J; Y3 t3 o6 u' d" P! s4 ~* ~0 l% r5 P6 f, V+ N" t7 d
extern void cs_t(void);
' C5 _0 F: L p4 x( C5 F |2 B" textern void delay(uint);
6 ?% U" I# I$ W+ J" u
5 k. U3 }4 r. k1 G4 b3 r
8 z8 b* i1 @/ S4 F6 a$ I; B {
$ \" S& T) X* d& p4 i+ Ovoid LCMInit(void);" [+ q+ @9 s0 w4 R2 ^& \4 X
void DisplayOneChar(uchar X, uchar Y, uchar DData);
4 }' L: w0 G( I5 q+ t/ B) g! ~void DisplayListChar(uchar X, uchar Y, uchar *DData);
% [7 k+ ]) X O" Y4 ?void Delay5Ms(void);
8 b% h6 q+ U W3 z6 o) Nvoid Delay100Ms(void);
! e# r7 j9 @# ?" F$ a) ~9 j' B3 i+ o4 d/ f& D( Z1 |' a( R0 e# s1 a
void WriteDataLCM(uchar WDLCM);
i& {* P+ i$ u1 ]void WriteCommandLCM(uchar WCLCM,BuysC);+ ~6 B0 B6 t2 t/ V% Q X5 t
5 e6 x8 A: N/ l9 W7 |
9 E0 a0 x3 Y* j2 F( L& }- X2 jdata float distant=0.0;. @8 D9 ]8 s* Y0 t$ ]
uchar ReadDataLCM(void);
V& R* {9 D' U7 F, g! puchar ReadStatusLCM(void);# |6 ~& r; F) z$ W
uchar cdle_net[] = {"--Daoche_Leida--"};' v2 C0 b' A' L9 t# l1 G0 |
uchar email[] = {"Juli:"};1 V% \- l( Z0 f/ G- S
uchar cls[]={" "};8 A9 m/ `) ? Q" t( P
uchar DIS[7];$ c2 ~: E9 B; M8 H2 n* Z! T& b4 d
data ulong time;
' G; u9 Q. a& y2 C+ ofloat distant;
# @. U5 n- M" n* x+ J2 wsbit LCM_RS=P1^1; //定义LCD引脚
7 x3 T. _, J. D# G" Lsbit LCM_RW=P1^2;
6 h' A* N+ i7 R& W5 P( U5 usbit LCM_E=P1^3;
; {9 n$ G3 I2 M3 g) Vsbit P10=P1^0;- _. c' U @# R# W# [1 T. J9 L- e: A
- c! ~$ Y- y3 S: d0 k9 h5 u1 P U, a, _- o3 V& t3 K
data uchar flag;
' ?* ?, o- o/ P. f5 `
9 `' e4 a3 I# Cvoid zhuanhuan(float juli)
1 A3 D4 ?, ~7 u6 d% S{7 ]) c5 R- L- k" ?7 Z+ [0 h
unsigned long juli1;
/ h; e! M$ A# J. C- K; mjuli1=juli*100;5 O- i* Z2 x7 N' r6 i3 T4 X( K
DIS[6]=juli1%10+0x30;
0 c1 m. u1 [; f9 M) p+ qjuli1=juli1/10;
8 _- }9 Q2 Q8 [DIS[5]=juli1%10+0x30;
7 o* R' D- s; C$ J! gjuli1=juli1/10;0 Q) `; `! ^: D
DIS[4]='.';
" ]* W s6 r# q& w% `DIS[3]=juli1%10+0x30;. k% }/ G& W+ S7 _7 q' {* k; y
juli1=juli1/10;
! m! w- j' J, KDIS[2]=juli1%10+0x30;- K) N( A* J2 K* y, z
juli1=juli1/10; N% ]0 c" a8 b# P+ R _
DIS[1]=juli1%10+0x30;! m; A! @& _. w& H' I
DIS[0]=juli1/10+0x30;7 |! _5 L L& B j' v
{0 v5 d1 f- M2 ~}
2 t0 [/ x% B$ R" A$ @" a4 I, A8 y' q( Q
void main(void)
7 u' p/ s; S/ p/ _0 B6 y/ H8 H' T{
b, |- g% |/ e% d& B# F# r2 W
l; w7 f- R8 p* g& K Delay100Ms(); //启动等待,等LCM讲入工作状态/ h& R- E% j, n1 P% n8 q
P10=1;
+ K! Z5 u' ?8 K$ E2 g+ { TMOD=0x01; //计数器0工作在方式1
0 ]- z0 n$ _* M. r8 T TH0=0;
" H! n& J' B( a TL0=0; //计数值初始化
3 U0 i" I6 Q" g- i! c IT1=0; //低电平触发中断
8 T8 Z7 f: X' f+ m: E+ d' \ EA=1; //开总中断
: j- M" m8 { V- t. s; h' F. ? //IP=0x04; //设置外部中断1为高优先级中断
% A5 i3 z# n/ o8 V4 P flag=0;
6 K3 f+ \8 j1 W9 \, y7 W LCMInit(); //LCM初始化% X. p' X' h$ g3 o: h
# K2 s/ ^& j4 {" p: @
" h3 q, J/ F: F6 r" m while(1)
3 g, }/ |1 D1 [& q0 Z1 C {- y* C3 n) Q* B; J! k# C
cs_t();
. J1 g3 p! p% F* q" u/ n0 V2 f Delay5Ms();
) J3 L9 r# h3 D3 Z# W3 Q$ J2 u% o ET0=1; //打开计数器0中断
3 G M; g3 X% z/ N EX1=1; //打开外部中断1
3 u, \; S' h0 o* K4 _& K( f! R* w TR0=1;* M# f! i7 h Z7 f
while(!flag) % L: a- b3 L% O7 r$ H. D
{" R6 [) R F* }) r2 ~/ R: I0 k
DisplayListChar(0, 0, cdle_net);
' L. ]" W# o0 J1 c DisplayListChar(0, 1, email);$ P0 e5 t6 J% H3 X
}: s4 z: b2 W5 \/ W' _* m+ D$ u
if(flag==1)0 @* |- m8 z- i* M. ]5 o8 y; F- R6 I
{: R+ U! ^% C: W. ~* h9 m
time=TH0;
2 G4 |, S' V3 e/ _9 N F. C time=(time<<8)|TL0;
" J: H5 R1 h+ K9 k3 p0 [. e distant=time*1.72/100;
; n8 V& f2 u! D' g) h' ?, Q zhuanhuan(distant);
2 T- ~' c- W% k3 m: W$ q0 d if(DIS[0]=='0') DisplayOneChar(5,1,' ');, \& A$ h7 S, t, F3 w6 F6 A9 o' A
else DisplayOneChar(5,1,DIS[0]);
" n2 K! P: R2 e$ X, N+ | if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');
0 _8 J, n+ _* j m9 T else DisplayOneChar(6,1,DIS[1]);8 D! T$ ^3 k6 {; z
if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');
3 k$ A$ ?8 h7 z6 V" ^ else DisplayOneChar(7,1,DIS[2]);
4 }$ e. c- w( L {' s9 s/ B DisplayOneChar(8,1,DIS[3]);
+ Y( V! H3 u& a# F5 j DisplayOneChar(9,1,DIS[4]);4 a' l: g: d7 }+ b) B" S
DisplayOneChar(10,1,DIS[5]);
& K( W1 |( Z* @) d2 _8 Z% P DisplayOneChar(11,1,DIS[6]);
- E9 h3 R" W J. ?3 y DisplayOneChar(12,1,'c');
% k* J6 Z; z+ n6 R+ N& C# ^ DisplayOneChar(13,1,'m');* W% A- r3 Z' Y
flag=0;
6 S7 v- m, O5 I- l1 r( m }! m: I1 k* m' @* J( l6 G
else8 ]- q& ]% ~8 r" m5 J% Y! l
{4 E8 B+ z. z3 [5 d7 ^
DisplayListChar(5,1,"error! ");
# D4 J6 U& X- {2 W/ J r flag=0;4 F& j& D4 B% ~( n, q
}# d6 x" ]3 _" @1 G' Q
TH0=0;
! f7 Q# w$ c! g" g+ \ TL0=0;0 }3 M/ m" h2 z# Q
Delay100Ms();
; |4 ^# S2 \4 }0 n4 v6 b$ a) V }
y E# G* e/ L- M( x2 |5 Z3 l% O}
7 _) d+ P& b% ^+ | ^7 S( |0 V. B5 h4 ]8 O1 S, W
$ {. ~# z4 v7 Z5 I$ V* c# h2 X) p1 \& _6 h
void cs_r(void) interrupt 2
1 G9 o' E) X8 p' P1 d8 c# {' Y{
' c8 y2 n+ _ v9 Q4 O6 Z7 O4 bTR0=0;
! ^# G- G |* _$ h7 p. C; sEX1=0;. f& C7 @& a! q
ET0=0;
. t' [; @9 e1 T) Qflag=1;8 @- g, Y% f0 ~2 m6 G
}
k% I2 \3 R( F
0 Q3 B! x; B& D/ h5 n7 J$ v0 q) N' U1 ]& t1 c- r9 k
void overtime(void) interrupt 1! D. G% w8 B6 K1 Z
{, r' T. Y% b, y% Q9 r/ J
EX1=0;
! j* S4 m' m- P5 }1 a+ fTR0=0;# g+ @1 A& k: `; F4 j( \
ET0=0;
: S5 d- Z# K( g2 ^flag=2;
, Y- m ^, [! a( Y2 r4 `: O- d+ O}+ _ |! \/ m' Q G
, A& L1 P7 K; S7 q5 V! o9 t. i# F3 Q$ I/ B
//写数据
6 ^; b/ w5 }2 C. Tvoid WriteDataLCM(uchar WDLCM) ! k- F" c1 u7 K( r5 y
{4 `+ \2 c& B, p: _( e) y. T' i
ReadStatusLCM(); //检测忙/ _" |: ^1 p7 P+ k1 L' J) z
LCM_Data=WDLCM;9 b# _* \" q8 e5 e4 I! ^
LCM_RS=1;3 P- U. l9 T2 o9 [ k: i. ^
LCM_RW=0;, V7 Q( o/ J2 r) U! [+ R* S: y
LCM_E=0; //若晶振速度太高可以在这后加小的延时
7 _+ n! F3 L; L% z) z8 H4 B( s LCM_E=0; //延时
& R5 y% v/ `9 Q5 g* a. E0 y- d+ H7 t LCM_E=1;5 @9 {' _9 u; p; m9 k7 W+ g
}; z" U3 S% U8 N: z6 y6 O5 S
9 i& v+ d( N; x" v1 H) i- _/ {//写指令
/ x! ]' k- O1 ?: Pvoid WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测6 u& u8 X8 r9 _( q+ E& r
{, l% ~% [% a5 e6 h# i
if (BuysC) ReadStatusLCM(); //根据需要检测忙7 Q* M8 W# h% R5 ]9 S" s, K& b& J. H
LCM_Data = WCLCM;4 H- U2 `5 u/ [$ A2 S+ X% _7 @) @
LCM_RS = 0;4 y& a! r; |% e2 m
LCM_RW = 0;
- k& F( \2 _! ~: K7 y9 |3 p LCM_E = 0;1 e c6 T9 b0 ?+ q l3 P
LCM_E = 0;) \$ d; A, h _
LCM_E = 1; / H! j0 _. k6 b1 h* d8 N. G( x# p" E
}0 C0 V( {7 p' a% b! l5 j0 m4 u. r
4 @* f, C) E. j0 [
//读数据
/ d, a) H) E7 [7 s* X7 ]0 r# G9 `uchar ReadDataLCM(void)
1 U4 \/ @6 I9 @$ @/ A& d# ?3 |{
+ A6 j( z$ w- G LCM_RS = 1;
& [# K% H) O* P% I& R+ r LCM_RW = 1;: l F5 y5 E# R
LCM_E = 0;
7 A, U& \, Y( R+ \0 A( v LCM_E = 0;
' y, A. ]+ ?2 l# Z, w LCM_E = 1;
' |& o% L k; ~ return(LCM_Data);% {2 @3 E# W u+ B
}% @% G$ y/ W, D4 M' ~* E
, k: `8 K3 V1 g6 R6 m+ E7 Q) [2 p//读状态% {. J( u0 B" {
uchar ReadStatusLCM(void)
" z0 c% V/ p( o9 P9 r. b. G: h, _{0 @3 V, F0 q; G, f7 c; V- A6 v
LCM_Data=0xFF; 2 R# L0 j. k' R
LCM_RS=0;
3 ?% O* j* E; t9 Z: L6 ^ LCM_RW=1;' K6 t! ~6 E* Y+ ?2 L" U3 V
LCM_E=0;* U$ T! g" ^$ R9 D$ o, n5 G$ f0 j# F
LCM_E=0;- R* l+ s0 q; T# @; U
LCM_E=1;
+ ]% \0 J s% \0 R while(LCM_Data & Busy); //检测忙信号8 ?7 ~! _2 ~4 r2 L% ~4 E
return(LCM_Data);
3 T) R7 Y# c" L T* ^" k# o}/ ?* E$ W; ~% V: e# c* G
1 M6 m) h/ [& g' Y
void LCMInit(void) //LCM初始化
2 b( k. f+ i$ I! m7 W c( ^" i, q2 H{
+ s/ \2 ?0 ]! k& J LCM_Data=0;0 }7 G) ]8 O7 G& p3 i' ^5 ^& j
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号! O5 z7 |- {8 a/ a2 M
Delay5Ms();
. z* Y! ~6 ]! e, c6 @ g WriteCommandLCM(0x38,0);9 h0 A/ C5 P1 R, ~% C( u
Delay5Ms();
0 X( I% `, R: }( n8 c WriteCommandLCM(0x38,0);
4 u) ]7 A6 I% ?1 @ I" f1 K Delay5Ms();
5 i5 e& m8 Z5 i4 {0 o2 {
2 _% R1 `! Z' G) `1 E WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
! X7 _3 ]- M$ s3 N9 E) I5 v WriteCommandLCM(0x08,1); //关闭显示
. B1 V' @! ~" \! {" E- y WriteCommandLCM(0x01,1); //显示清屏. i8 J1 a }* i ^# G9 V
WriteCommandLCM(0x06,1); // 显示光标移动设置
4 D" T; n* j/ Q- `( O WriteCommandLCM(0x0F,1); // 显示开及光标设置# I' T) x; V7 e( g
}
7 @9 i! J" G5 J# h% j* K
' P: M2 `$ A, m5 @/ }//按指定位置显示一个字符
& J5 K$ m8 G4 O: C8 hvoid DisplayOneChar(uchar X, uchar Y, uchar DData)
7 _' G( W) H8 r/ t0 J% O1 T# [{
$ X! |; I7 d9 L% ? Y &= 0x1;& P6 U8 n2 `1 }& k: s( U0 n
X &= 0xF; //限制X不能大于15,Y不能大于1. s* m$ a4 T" j1 b ~
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;- F8 y& H$ z# i) o! ]0 j
X |= 0x80; //算出指令码# a3 r% s% M, A) F5 Y: j
WriteCommandLCM(X, 1); //发命令字
. g# }$ r3 z9 h9 e1 q) R6 | M6 e WriteDataLCM(DData); //发数据! J' X6 ]8 @' {1 {) e5 f
}
( o( `& H) K2 N: W. h) t/ y+ f4 S/ e/ B! o Y7 v5 v& l
//按指定位置显示一串字符7 P# n1 _- c9 S0 C' g2 ^
void DisplayListChar(uchar X, uchar Y, uchar *DData)* ^; M( `/ |; H3 F7 u$ K) G
{* [% t4 d# e" _$ ~, @- t
uchar ListLength;
+ [& v! k9 A3 u5 h+ M' b$ p' {# L8 d+ W/ w: B' _
ListLength = 0;
1 B8 }& x% r& T3 v Y &= 0x1;
+ a3 t3 {7 P% \/ r8 x X &= 0xF; //限制X不能大于15,Y不能大于1" o! F# d1 k; R- |' g2 q
while (DData[ListLength]>0x20) //若到达字串尾则退出7 ^( C" `5 G1 U' ?, z' S4 {6 U
{9 d! k8 c2 B6 [6 Y' P
if (X <= 0xF) //X坐标应小于0xF$ p4 {, O0 I: ? W3 |6 ^" B( [
{ \: ]+ o8 I1 u
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
* v0 J* ^0 \0 X& y; c+ s. m ListLength++;
% [) c' C9 N, T: I8 M X++;
( r1 X9 M9 X. b$ t& [( ]9 b }
* C. \: E8 e# `. u1 M; C }
) U& y b9 |4 L" O}% Q. I9 f& R# @
% ` N/ u+ I$ _: _5 c* b//5ms延时; y! V- `5 R5 W7 b1 j
void Delay5Ms(void)
. ^5 F. ~+ P7 g6 J6 _{
% A- j: V5 B$ N: ^4 e uint TempCyc = 200;* W- R4 B i0 ^5 [
while(TempCyc--);2 T( ]& x6 t# @
}$ P& G- h5 I3 a" o6 G
o, F! C6 j3 w//400ms延时# A' O4 B, `8 W: v
void Delay100Ms(void)# H% Q6 v* z6 n+ W
{( f* G- {4 e8 u% h
uchar TempCycA = 1;
]0 _) d$ i) q2 ?! ^% d uint TempCycB;
V9 u4 }3 r9 z6 c( C: b while(TempCycA--)
+ b4 o2 D7 g( ?* \2 v4 g1 X7 h {8 q0 W5 n9 d$ I2 W% q
TempCycB=7269;9 [- x- V: X" \9 C4 ?5 \' L
while(TempCycB--);* E; E( K9 j' Z' b+ Z
}
p" g- ?; r/ d- f) \' k4 E4 S0 W} |
|