|
|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。
5 b* v% }; x- m) o9 f1 H) p+ c% O硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。1 r0 ^6 O5 f0 N; _ ^& h
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。
6 y; B7 L: O7 ~超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。
3 \# c) ~6 g7 }% K超声波的接收电路包含一块CD40106处理芯片。
* y9 q2 V8 {( t0 }; ~, u( t1 S) e技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。2 ]# J: Q! c6 R, S* Z# L5 D! n
#include<reg51.h>
" @+ W( h: K/ j. B2 j/ b, U+ u5 \#include <intrins.h>+ r( i0 K5 e$ N9 L
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
3 T; \+ l) d/ H# T#define LCM_Data P0
; W: Z) ?8 q5 }& m! l#define uchar unsigned char* V1 B! `, I9 @" V( v2 m: h
#define uint unsigned int
$ k9 R& n( B% W* g; q1 V#define ulong unsigned long
; W' I6 w6 c1 c: I/ y
4 C' V. q, v) ?, [" t
! A" d% B: U+ A+ Xextern void cs_t(void);* m. \# G; P! F) X* C
extern void delay(uint);2 T* t" Z2 S4 {* J, q& j
& D! _8 r$ s" ]
: W! {- A0 k8 [& j3 _3 v0 N) z% G# \9 B ~
void LCMInit(void);7 Y1 d5 S4 h( Y& h, Y
void DisplayOneChar(uchar X, uchar Y, uchar DData);6 ~: b9 I* D/ R+ G9 n0 x7 }
void DisplayListChar(uchar X, uchar Y, uchar *DData);
2 @% |4 ~* s/ @$ @& pvoid Delay5Ms(void);
T* }0 l* `# X5 {$ nvoid Delay100Ms(void);
9 L# L) E* ]3 F* m7 Z" ?3 `! W! ~7 q, `0 Z ~
void WriteDataLCM(uchar WDLCM);6 ~: I, J5 T; h& p
void WriteCommandLCM(uchar WCLCM,BuysC);7 W5 d- ]# U" z3 f% w; b3 ^! y
. a7 ~ P& y: i. F0 V/ @$ s: |! O' n9 l* s' ?& r4 k
data float distant=0.0;% \4 N$ p- b2 e
uchar ReadDataLCM(void);- Y1 j7 D7 G- l, f9 Y( e$ ~
uchar ReadStatusLCM(void);
, e1 J2 S0 u' e& i$ _8 z4 p! tuchar cdle_net[] = {"--Daoche_Leida--"};
5 ?/ y. _7 u. Z B# Fuchar email[] = {"Juli:"};/ k9 r1 A& _$ \1 B
uchar cls[]={" "};" _: ~) ?0 K) y& K8 }% [% V0 ]
uchar DIS[7];" G. n; ^9 O( S! P7 [' D- Z" I b
data ulong time;7 Y1 k" h* K4 {4 I
float distant;
& i9 p3 y0 x9 O; f. U; csbit LCM_RS=P1^1; //定义LCD引脚/ F! v5 |" }/ x' U" p
sbit LCM_RW=P1^2;
8 l |% y& s/ `/ xsbit LCM_E=P1^3;
. ?6 s/ L {$ e6 y6 [9 {1 f$ p" r7 Bsbit P10=P1^0;# M" k! M! x, p6 I" f) B
3 T; l' q' p5 V+ ^+ j
$ l3 Z$ H2 Z, I* ]; o6 odata uchar flag;
2 s# b) S' P0 |& L6 @8 f% X! U8 p: T" _+ Z9 |) s
void zhuanhuan(float juli)* a, D( B3 w( K. Q' `
{
% {+ h% K1 l+ Q5 bunsigned long juli1;
! ^6 V) n- K: `& U# gjuli1=juli*100;3 |7 ~( e" w5 K
DIS[6]=juli1%10+0x30;4 T" p6 ]* E6 t8 m! u7 }- y
juli1=juli1/10;0 R, N. I# C9 ^5 E1 t
DIS[5]=juli1%10+0x30;
: k: g* ?0 Q! T: G" s) Vjuli1=juli1/10;0 q F" ^7 N" q* t- v1 y
DIS[4]='.';
+ b" g: R& o M5 h3 p" BDIS[3]=juli1%10+0x30;2 i0 {- ` j2 j6 a1 [; u; P$ c9 I
juli1=juli1/10;
# ]$ a2 V6 t) ^! MDIS[2]=juli1%10+0x30;8 ~- N9 ]& {' h
juli1=juli1/10;3 \0 ]' h$ }$ \/ o4 c7 x
DIS[1]=juli1%10+0x30;
9 d) _+ c/ N3 ?0 q2 y+ xDIS[0]=juli1/10+0x30;
# N5 Q& H, W' Q4 D1 @
4 n" z. i6 m3 q7 Y- Z1 q k}
4 D. D' w" S7 z- I/ i: {' b6 h. K
void main(void). n3 ^( F' P R- m2 E- ?* l
{
; \. y' ^) s2 }$ d: l
" B5 Q: N" f/ t* [% s2 ~6 p- P. s Delay100Ms(); //启动等待,等LCM讲入工作状态- K7 A- ~3 A) P8 w4 B7 M
P10=1; 4 J( }! G% }- S; Y0 O+ i( e; N1 j
TMOD=0x01; //计数器0工作在方式1
/ P% v3 e' f% }5 Q5 }6 v# c TH0=0;# s) L- }3 d3 s
TL0=0; //计数值初始化! U6 U# P6 {1 _: H
IT1=0; //低电平触发中断
8 y3 E% m5 e8 D! f+ l/ t8 R EA=1; //开总中断
( c' V' T1 g" z% m# ?! H //IP=0x04; //设置外部中断1为高优先级中断
5 r' U" w+ W. Q3 N flag=0;
7 b8 @5 r8 @5 u; D LCMInit(); //LCM初始化 E4 H4 u* ^7 [& u9 {& ^
6 p) _ D1 I6 u( m# r2 @! M" W ; S" `# ~: Z1 p7 ^
while(1)
' R2 E' {0 ?/ T {
5 T( h! V/ f2 Z: h: W* {3 W3 M2 o cs_t();% M$ [$ `: r4 s* F- L& C
Delay5Ms();
, s) @ \* k% e4 J1 r4 s/ ]7 R ET0=1; //打开计数器0中断- b9 B4 S0 S: m9 y" N
EX1=1; //打开外部中断1
, R1 m2 t- Q6 m8 b2 j: r TR0=1;0 O3 u8 b9 o, M# B8 Q7 U7 f
while(!flag)
8 ]' M* J: u/ V$ v; c9 O$ { {
- F0 y) _: j) `1 w5 p4 M5 E DisplayListChar(0, 0, cdle_net);
: Z* U% ^* z; z4 Y! ~& E" v6 T DisplayListChar(0, 1, email);, ~' W+ N T/ u' n2 V
}3 M' p9 D% E( E- c, Y* C3 G2 R
if(flag==1)
5 ]/ k% \- s: t, J {% R; L& T3 m @8 m9 G
time=TH0;
: U0 B! g+ U9 U8 e/ ]! N time=(time<<8)|TL0;2 M R# r! ~* p
distant=time*1.72/100;
, M8 V+ s& K9 k V' Q; W( Z1 R zhuanhuan(distant);4 [6 G E# p: I: T
if(DIS[0]=='0') DisplayOneChar(5,1,' ');
0 t( a: N7 U* C" W! H9 O else DisplayOneChar(5,1,DIS[0]);; Q% H: w% y( [4 L# |0 Z7 ^
if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');" n) ?# B& n4 H- ^& w
else DisplayOneChar(6,1,DIS[1]);4 P4 ^+ h# y! D
if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');
k4 e* V6 `" Q1 L9 t! O else DisplayOneChar(7,1,DIS[2]);
6 h/ d0 v$ D3 Q7 }4 s8 W DisplayOneChar(8,1,DIS[3]);# ?( K1 K2 f. ?4 ?0 u/ o
DisplayOneChar(9,1,DIS[4]);
- W& r- l/ \1 f2 B* U* Q DisplayOneChar(10,1,DIS[5]);
+ q7 W* n* l: T DisplayOneChar(11,1,DIS[6]);
) c# [; C: W! ?) S5 s7 ?* N. M DisplayOneChar(12,1,'c');$ \1 @5 O! O* l8 C2 j
DisplayOneChar(13,1,'m');7 Y% i! ]8 o5 q# ?' {9 b) m! w( F$ n
flag=0;
& {( x+ _1 s C: C6 C0 D, F }; q$ \1 H* I' t% n5 m% I, X' w, ]
else
m& C$ W5 ?: v, W* o {
& Z& Z) R# z7 Q8 G) Z DisplayListChar(5,1,"error! ");
9 j; ~ G" }+ n8 w, G8 `- C flag=0;0 N6 _) c+ P/ T4 {, z, Q7 ~
}
4 s1 S) T u1 } TH0=0;% o) U4 C( F" I) K) C& j
TL0=0;
9 ^8 ?0 I0 Z, E3 B0 w) F' q! M5 t Delay100Ms();
, K8 z$ h2 u7 G5 n }; C/ w+ p* n6 v& t7 u3 f
}9 @( P5 v5 w5 u9 n+ e8 X& p( u
/ |' W \4 f( D3 L1 e
! ^$ h) Z& ?) [! A6 |
' q/ L& w: M$ i2 A" P
void cs_r(void) interrupt 2 b9 k6 @" F$ H( J
{( ~) Y* K: V2 r4 \
TR0=0;
5 J0 @" i' g% Q8 p& \" UEX1=0;" V- t8 ?) I( P u) e
ET0=0;5 T: s: B5 a( C5 @
flag=1;
q% r4 x4 j" u1 X" w) r' [7 P}
, s9 V0 R, G" x- [0 s5 }2 p) \) f* [6 U
' {" x, F8 ~+ n
void overtime(void) interrupt 1
! o' W2 o$ _4 r& s; j" {{* H. ? R. v4 `$ H! X; R( ?/ f; _
EX1=0;
, S6 [9 M! u. Q; V8 s4 qTR0=0;8 n4 V1 t3 H0 k7 r! Y9 H, C& C
ET0=0;
' O- V2 m* J2 l9 M) k' mflag=2;: k" ^; f/ p* b. ~. @+ F S
}
# ]0 V3 Q( T: r9 ^1 `, q$ K! I. p: t0 b
% U/ w4 r2 `9 K& }' J: q/ A! w
//写数据
N7 B) Q% J" Z+ D$ X. {void WriteDataLCM(uchar WDLCM)
% w( v- ]5 k- H, X+ {{
! ?# K# H- K+ L' N ReadStatusLCM(); //检测忙
: p+ G8 W3 g& Q6 h* a" L LCM_Data=WDLCM;" A7 i# h2 `4 d. i: A/ h8 }5 i
LCM_RS=1;
/ [% T/ Z# d3 K6 y9 j LCM_RW=0;
6 b4 S/ X, G1 g: \ LCM_E=0; //若晶振速度太高可以在这后加小的延时
& B% f' {: p) ]# z+ B1 U LCM_E=0; //延时7 R: \ X% a% f3 {
LCM_E=1;
' R, W% ` o/ W" A/ G}
. x, U( o, a9 ^$ e( X+ D3 g) \* a N! g7 O' @
//写指令
; [! g3 Y% {! Y" _% c4 Ovoid WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测6 b+ @3 ]$ K* F7 V8 a
{
) c7 X# k6 M3 p% [( S) s if (BuysC) ReadStatusLCM(); //根据需要检测忙
0 k) O8 w8 v) P, L. { m LCM_Data = WCLCM;( m( k( @* j% b: Q% u1 ?& c9 U
LCM_RS = 0;5 }) n" k5 \: k) S
LCM_RW = 0; + ^8 k0 `" \5 Z) V1 t/ ~4 e. L$ ~0 w, Z
LCM_E = 0;
/ b& i# }" M1 K0 e; @3 `% v LCM_E = 0;
) e: [) E4 [/ {7 ?( n& y8 C LCM_E = 1; , r( }5 h8 M1 j
}
7 w7 K1 f6 B5 U' d5 R9 R9 c0 _9 w! e6 b$ x8 s
//读数据
) W2 z# U$ p; p$ [uchar ReadDataLCM(void)
) i0 p! z7 @3 W{1 J" B. n6 v) o6 L; E" e
LCM_RS = 1;
* V; V! [& y4 S( I LCM_RW = 1;. @9 t8 \/ p& i+ _! ]
LCM_E = 0;
* ?, h% Q' C7 D, B LCM_E = 0;
" V6 s/ Q3 L1 L; e- l3 d1 \ LCM_E = 1;4 l( c t" M! P3 }4 m
return(LCM_Data);0 B6 Z- r9 y8 N0 y% n
}; J9 v" m, o4 p' E
/ P) M2 O: K { M( a//读状态0 w' p E# r( s
uchar ReadStatusLCM(void), R7 T+ u: A/ C8 ^# N/ w% V
{
/ p) B! r: Q: `; `5 T& ?6 L" w" ^/ ` LCM_Data=0xFF;
0 n0 j9 m3 M% Z, B' S N+ G/ a LCM_RS=0;
; m3 u- J0 n* R LCM_RW=1;
3 D, F9 b9 k. n3 [4 o; q9 `- ^# M LCM_E=0;
3 w: P$ W$ x! a; U" t2 T' b1 L LCM_E=0;
8 j8 V; _ I; `* k LCM_E=1;; e/ O! ?' T) d! c
while(LCM_Data & Busy); //检测忙信号( d, }3 b( k, y( l3 p+ T1 m! J
return(LCM_Data);
1 a% v: x9 U: p4 t& y}2 |/ c7 ]3 q3 o7 U; J
/ f- x9 j& @* m; L9 h
void LCMInit(void) //LCM初始化
8 I& s& z4 {. l. J1 ]6 A- g& P2 D{
3 R# d0 d4 g0 w. {/ e LCM_Data=0;# Z O1 P' d8 Z/ x0 a7 n G% u
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号! d0 e9 p- G( k+ Y3 T" w3 {. y
Delay5Ms();
8 ]2 P) g% x% z# E" D: a WriteCommandLCM(0x38,0);6 i2 D- F) @3 R, i! Q
Delay5Ms(); 5 Z: ^' {9 @1 }0 ^
WriteCommandLCM(0x38,0);
. F; Y1 f$ G: `! [( F, F Delay5Ms();
' D5 l6 I; \. z& Z" L+ a# f0 Z3 B7 C. \, O$ R- {
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号# X+ }( ?1 N$ C4 N' R* g/ N/ N
WriteCommandLCM(0x08,1); //关闭显示
" A6 m9 A. _& l5 O6 m4 n# s WriteCommandLCM(0x01,1); //显示清屏
0 ]) o! v( y4 h9 L; _ WriteCommandLCM(0x06,1); // 显示光标移动设置- ~- C$ i: T+ E+ y) ~/ n n& g
WriteCommandLCM(0x0F,1); // 显示开及光标设置
( U% E+ h; W% J- P: m5 f* l}
$ @- k7 W# f& n) M: ^8 H" y
5 x. ~7 a* r) I8 K4 b. q//按指定位置显示一个字符; z/ M& a; v& S& k3 [( F$ ?
void DisplayOneChar(uchar X, uchar Y, uchar DData)
1 s& S/ S# c8 D9 S- [2 w{
9 C# w' w" }3 z& H8 r- { Y &= 0x1;$ p! j4 F8 H" |+ y0 T
X &= 0xF; //限制X不能大于15,Y不能大于1* Y3 O" z! t/ a) w! C- g: u
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;" K9 x- O) B7 n b* @6 \: I7 Z; k" {
X |= 0x80; //算出指令码, ^6 Y* L6 F+ T$ {
WriteCommandLCM(X, 1); //发命令字
% [+ x& y* ]6 r8 C, N! C WriteDataLCM(DData); //发数据
; T# E' P1 u! p2 ^ e# Q$ H; w}/ f$ h. W, E3 l; }
( F3 q! P }5 u! r/ J//按指定位置显示一串字符
3 c% K5 |$ N7 I* j; z1 F& Wvoid DisplayListChar(uchar X, uchar Y, uchar *DData)
+ w) t8 y3 j$ b G! j* z{, v: K+ E1 G3 i
uchar ListLength;
5 c! H3 i( h7 @3 u1 h/ x
- g& {8 [* O& M0 n" a( Y ListLength = 0;
7 Y. A+ v! U/ _0 I- g2 K. t) | Y &= 0x1;
! S+ s4 L8 q9 b2 M; p X &= 0xF; //限制X不能大于15,Y不能大于1. { ^" L" V% T9 V0 g8 g
while (DData[ListLength]>0x20) //若到达字串尾则退出5 s5 t- C5 h: [$ V
{
4 Z8 c+ ~, x7 t- A a6 T6 p if (X <= 0xF) //X坐标应小于0xF
5 X( T# s. B/ C' p, } {
7 Z7 Z! V i$ F9 O DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符+ x5 c/ `- _* k9 A" [" t6 |7 Y: e
ListLength++;
/ n3 C$ e5 t* W5 x0 Q0 Z X++;
! \# K! a- f. r/ h! Q& a- v }
% c& w& k+ c; S- o }8 [5 q) ^& W1 d, [8 U( U
}: p1 |$ M- t, R: ?% Q
+ k* ]9 R& t/ \; ~5 z3 J) y! X) G2 y//5ms延时
7 T3 T1 v" f3 Y8 `2 o _1 |void Delay5Ms(void)/ X& B# L; j) x1 j3 B$ a c
{4 v' h5 j9 G) h" ~
uint TempCyc = 200;: T3 w1 X8 q1 d! c
while(TempCyc--);) J. W: m6 f& ^! r+ G" X
}. k( V) J( I1 i4 i8 a: G6 V
9 |) ?3 D- K# Z/ @! {# g$ _# |
//400ms延时! u* |6 s: l6 D( I# {/ R
void Delay100Ms(void)
4 s2 X' S* D0 B o+ a& s{
. ?2 j7 J* y; B0 v uchar TempCycA = 1;7 v* w; e* K! y+ T
uint TempCycB;
- F: q F; v; f# v% [ while(TempCycA--)
" k% t f7 A9 i% x( {: A {
5 @2 [# I$ R9 H# | TempCycB=7269;
{8 f5 o0 l: ~/ g% i @3 K while(TempCycB--);
+ N! q4 t- k3 u; ^# x/ u }- i `. B# P l, b; m
} |
|