|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。+ r- ]! b, K, y/ g
硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。: A* \0 w& q) D8 c3 r2 L6 }4 y4 i
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。! I7 P; d4 G: p
超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。
. `( }% p5 ?/ i z) Q超声波的接收电路包含一块CD40106处理芯片。3 ^; o1 y' w' a: T7 @8 a! k- y
技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。
/ e* Y+ y( ~0 c6 T, w/ G#include<reg51.h>3 u5 H" `" E) C2 J
#include <intrins.h>
! B# @9 W8 L+ q, Z+ V' H#define Busy 0x80 //用于检测LCM状态字中的Busy标识" B$ t0 N' ?: g, B. d# n- E
#define LCM_Data P0
2 M E- p/ T" r* x, X#define uchar unsigned char
/ y y( f% [4 B& W0 c#define uint unsigned int
. {- _; E n- @$ K( u#define ulong unsigned long
$ Y% f U; t1 P% y2 A0 i! W2 t" A( [/ K6 }8 I. R
& Q% S" s: I+ Q
extern void cs_t(void);
* s4 O1 {, ~; S5 M8 [" e o- N, N9 cextern void delay(uint);
; R+ w1 U+ [3 \3 z" ^7 B
; o1 c" u( v: o5 `
* u. F3 Z) [% g, V* G1 F% H" y% W8 I
void LCMInit(void);
" ] p* G# j9 B* }5 [void DisplayOneChar(uchar X, uchar Y, uchar DData);- |4 o# b- m# c; ^$ |
void DisplayListChar(uchar X, uchar Y, uchar *DData);
" d5 f& B# t# M) Q6 W9 F: `void Delay5Ms(void);) l. N$ O' r) k2 y+ L
void Delay100Ms(void);
* E' W! F$ w; i1 n" A6 b/ U: E) s9 M
% ~! V" |$ ^8 j0 ^void WriteDataLCM(uchar WDLCM);$ O7 F) Z P, U/ G( h6 O
void WriteCommandLCM(uchar WCLCM,BuysC);
) \- U' r# U" w' n e9 v, z' V/ K" ~+ [, t! h: N
! H/ ^. l% ]8 I) b) O+ i+ `& tdata float distant=0.0;8 Q# u! p- H# t' \( O& G
uchar ReadDataLCM(void);
% {# G' m6 H5 M& K2 Nuchar ReadStatusLCM(void);
) n% D) s$ U4 nuchar cdle_net[] = {"--Daoche_Leida--"};
% L& K' m* A+ _; k0 `uchar email[] = {"Juli:"};% p. a o# V/ I5 Y* D: u* |5 x; Z/ M
uchar cls[]={" "};2 C* f: h/ c F% v G
uchar DIS[7];
8 C Q! ?' B; I$ v! u2 P" xdata ulong time;% a8 v7 q4 H! p) x6 U
float distant;
$ j6 m$ B5 ?( @: S; Tsbit LCM_RS=P1^1; //定义LCD引脚3 r& {* M" i' q
sbit LCM_RW=P1^2; 8 j& X! P5 w! N# Q% }
sbit LCM_E=P1^3;
6 ?) u; R5 R1 _- M2 Y, Csbit P10=P1^0;
4 G, R$ K# e" i3 r! m% q* T: A& E1 `4 `7 V. i0 [1 N: p
2 s* r+ G" F! v; d4 v0 W, idata uchar flag;
t* M$ J$ [0 L5 l4 Z9 ^3 o6 ~/ E* a# q# Y9 U
void zhuanhuan(float juli)" R+ S1 }- x7 j6 j5 ? |2 V/ U
{: |% i% j; m7 L3 _/ T
unsigned long juli1;0 K% U* S; X/ j% u0 ]0 V
juli1=juli*100;
0 d; M2 u& B/ P" H, wDIS[6]=juli1%10+0x30;
5 ~$ R4 V) H- d# ]juli1=juli1/10;5 P3 m% ^9 u; d# t% y" g
DIS[5]=juli1%10+0x30;! r& g4 n5 y5 d" c
juli1=juli1/10;
& W7 h5 I0 E2 \" b# PDIS[4]='.';
6 G. C, @; {8 N+ A( `9 zDIS[3]=juli1%10+0x30;
* Y8 U0 h/ h3 T/ Djuli1=juli1/10;
2 y, l5 i5 k* w6 j: F/ P8 B% gDIS[2]=juli1%10+0x30;4 U1 f0 k0 y; a
juli1=juli1/10;
4 F5 u) {$ ?( h& uDIS[1]=juli1%10+0x30;
- M; {: ]' y3 V( X6 KDIS[0]=juli1/10+0x30;
$ D! n4 _) T) ?# {' J" g9 r- `6 X2 \# Q4 _
}$ z# U, W+ q. R
0 H/ o+ S) E8 Z+ c$ Vvoid main(void)
6 |/ l: K8 }+ L7 ^$ D{' j$ Z+ w3 c2 Q, c% ^
' ^ [2 S7 _% n. e5 ]: [ Delay100Ms(); //启动等待,等LCM讲入工作状态
5 u$ W8 l0 v& F( J5 F+ | P10=1;
3 T1 |4 ~8 M; @ TMOD=0x01; //计数器0工作在方式1
0 s- M- O5 V+ N, G6 a* _, H TH0=0;
6 T, D2 O2 i" K- e TL0=0; //计数值初始化& d* F3 @' R; Z5 A, t
IT1=0; //低电平触发中断! j6 n1 z; w) |5 B. v' t4 G
EA=1; //开总中断# w8 |7 v/ }* C
//IP=0x04; //设置外部中断1为高优先级中断* n% ]; S) B* ~4 K1 K: E7 a! t' {
flag=0;
* ?" @. ~5 j; L+ G$ E/ i LCMInit(); //LCM初始化6 ^4 q/ d- c( @7 \9 t
. Z0 X% Z% M0 w6 F9 r
; ?5 ^& O3 W: u, B1 d, K+ G- h. m. t
while(1)+ n( ]& @. G6 Q2 ?; B
{$ w& ]4 _" T# }. G' x
cs_t();) h) t* C" M" _/ K0 I
Delay5Ms();
' ]; B& r5 a0 K$ Y* K ET0=1; //打开计数器0中断% ^9 r3 o* s+ H6 H9 R5 C
EX1=1; //打开外部中断1, A6 S6 n7 l [# e4 [. ]* j) {
TR0=1;+ b0 n6 b8 q; m7 m4 C% G
while(!flag) : b" E" m0 }. d6 V
{# f* L6 Z! V0 M
DisplayListChar(0, 0, cdle_net);
- F) G' q# y0 k$ b DisplayListChar(0, 1, email);
, D# y+ g# X: Q" _ }
2 q }0 n3 ^" ^& L# a8 w8 s* D if(flag==1)
: L2 T5 |7 ~# [' {- P e" B {
- M5 y3 i6 D2 p. v time=TH0;& x' l' p6 P. w. u
time=(time<<8)|TL0;- v- {, `8 ~' x
distant=time*1.72/100;/ {) g( `/ Q# V8 V% n4 t
zhuanhuan(distant);
, b& q% d7 J5 f5 Z if(DIS[0]=='0') DisplayOneChar(5,1,' ');7 B, A5 h* Y& X) m, e4 C) t, f
else DisplayOneChar(5,1,DIS[0]);7 ]3 s# y0 ?0 t
if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');5 O/ q# d/ z! H! ?( ?' i( A
else DisplayOneChar(6,1,DIS[1]);
`! F7 X/ i$ g8 f3 L& ?$ d if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');
1 [! f+ L* {. n else DisplayOneChar(7,1,DIS[2]);
, x3 ~+ D8 K& a' h' ^, a DisplayOneChar(8,1,DIS[3]);
* R9 | X; c* ^; w) g) X, x9 {' A DisplayOneChar(9,1,DIS[4]);4 G) j, Z# ?$ t7 G) P% ]: A
DisplayOneChar(10,1,DIS[5]);2 M7 O% V. A! q- J+ q
DisplayOneChar(11,1,DIS[6]);+ r$ S4 n/ |! C) J# @6 `4 R
DisplayOneChar(12,1,'c');
7 i* a8 W: ^+ p9 E, U1 f* u* K DisplayOneChar(13,1,'m');7 Y6 c/ n' I& t1 X- Y
flag=0;
$ }7 h' E3 s) i& d- f+ | v2 @ }4 S; g, M1 e2 D1 ^' L6 F
else" S) M5 F2 y* c* ~9 f, J. t, c
{, Q, P% T( F% M6 A6 e. C
DisplayListChar(5,1,"error! ");& _9 ]; I$ f" t8 ?
flag=0;8 H1 ^" V+ k3 {4 K1 N6 O
}
0 q+ S( R$ J1 T* N1 [3 Q, I TH0=0;
9 _& b3 v6 O4 ~+ r4 g5 [4 }8 ` TL0=0;
3 _$ w' F1 X4 [9 m8 K" W Delay100Ms();
6 ?% D7 m1 y4 p, u }% l0 y+ N# e- [9 e
}
( a. v% a. h, i3 P8 `" N$ P# t7 U. v
. ~4 m" R2 [! M
3 Z: _8 D5 T4 B9 f& w5 B
void cs_r(void) interrupt 29 z/ x* Q4 ~$ d- e, }1 U% D
{
+ @ F8 r, _# ?% z) uTR0=0;) f4 Y, ?. L' X$ w% E3 e: I' p" Y
EX1=0;# @4 P. w; r$ N+ G' A0 d2 u2 A
ET0=0;! i7 q" b! M# w
flag=1;3 w0 @) @" w) O
}* k- N! H* h; [
. [( \" w& x/ X0 _$ T$ Y V/ S) N. X3 Y0 m" v
void overtime(void) interrupt 1/ a' {' m( `) t. F& y" _
{% q: G) S4 N/ r( w# u3 M- ^! a0 A
EX1=0;) [6 g7 ]0 Y& c Y( J
TR0=0;$ I, E U$ ^7 R/ K
ET0=0;
. l0 X, C9 l6 l3 J' Kflag=2;- Z2 M3 b* v0 B4 u. A
}
3 A1 T- Z# {, C& O+ E
2 T" `3 z6 ]& o
1 M- B# `. ?* m6 w2 \. h& R6 n//写数据& p2 K* g ~; g; i
void WriteDataLCM(uchar WDLCM)
$ R, N9 @6 ~9 m! k{6 d: a7 X0 N4 D& s8 e* ^- m+ R
ReadStatusLCM(); //检测忙/ }5 U/ q8 P6 ^9 l" ~1 ^
LCM_Data=WDLCM;, R+ ]& D1 f% \% _
LCM_RS=1;
9 B: U* u4 C( k+ p LCM_RW=0;3 B4 }0 S" K9 z
LCM_E=0; //若晶振速度太高可以在这后加小的延时+ W8 N" u1 z0 Y5 k- h$ B6 e
LCM_E=0; //延时+ N+ L. b$ Z& t9 @- a+ B1 R6 A
LCM_E=1;6 b* e- V; ^- d0 }( s V" z: B
}
0 I) P1 `. P6 M2 [, {& F4 [. H
% O; c8 f# K" d; @: L5 E! g//写指令
6 T+ U; @# h3 e9 j/ w5 pvoid WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测) D0 ?. H' {0 C/ A- Y' P
{
4 V' m& m5 W& ]3 X if (BuysC) ReadStatusLCM(); //根据需要检测忙
4 a) f- L7 ?) e+ I2 H4 S! ~ LCM_Data = WCLCM;7 W8 `* V: v& q: r; s
LCM_RS = 0;
- ?9 V3 f4 I5 J LCM_RW = 0; q. z' Z6 }' m* q1 y, e
LCM_E = 0;* a& T" n5 `/ o {/ u& }% ~
LCM_E = 0;: j' f, Q# P9 w: Z4 A' \' j# {2 Y
LCM_E = 1;
6 `* M0 ~- t8 C5 T2 z5 ^$ {}6 t# U# l, v$ |$ w# E3 b
" K. B9 o: z0 x- @1 l
//读数据
' ~+ o0 V ~9 { M+ A! q; }- `8 duchar ReadDataLCM(void)
6 W& y# E) B. L9 H1 F3 y: w" g. C) b{
- ~% v7 [8 K+ }0 F7 `' u LCM_RS = 1; 5 U7 E& N0 A2 s% k: ~8 ^
LCM_RW = 1;! e) L/ e. w" W+ I5 \, ~( u
LCM_E = 0;& p$ A8 ^+ Z3 `% a
LCM_E = 0;
5 A$ W; |' O" a) m# I$ z. p5 p LCM_E = 1;, q* T8 S8 h) y& l
return(LCM_Data);
/ F4 k L1 v5 Q}% J5 `0 Q! s2 I& l* ~6 z
/ o, R( t/ ~7 ^1 N* G
//读状态
$ y; r T, c2 Luchar ReadStatusLCM(void), Q: j3 X6 N: H: c5 o8 ?: X; q, L
{
! z" p2 X9 l( d4 b2 s* {) n LCM_Data=0xFF; 9 r2 Y: v( l! K8 w
LCM_RS=0;* S. W- q$ y% h6 \
LCM_RW=1;; r- r4 w. j' b( u: k
LCM_E=0;9 b9 v4 F' _+ b: d4 H. b6 R
LCM_E=0;5 h; F1 t! E7 Q w
LCM_E=1;
) N; t+ G5 H5 H$ B/ P$ }1 m1 Z) g while(LCM_Data & Busy); //检测忙信号7 C& a7 p: O+ b; j8 U6 E% y
return(LCM_Data);' Q, U( A8 F. s3 l! l
}
1 D" c. p' C& U. z; [" U% o% ?! e# u: I) i* _1 K+ X
void LCMInit(void) //LCM初始化
1 q1 A6 k+ U; ]{( ^5 }4 t6 ?' b* v4 ^2 L5 v
LCM_Data=0;& e" o2 U/ e* Q" t1 B
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号/ q/ I X8 |( a9 X) K& a
Delay5Ms();
1 O z: M7 d# X1 o WriteCommandLCM(0x38,0); N+ V; `8 }! }. f
Delay5Ms();
( t* m) r$ J7 m7 y! H( o# |* L( o WriteCommandLCM(0x38,0);
% M9 F @$ q: W* ?, E( ]% c: ?5 ] Delay5Ms();
- N# ~0 U0 |9 _% q' k2 R- h( X! B
' n; \/ v+ x( n1 ^/ X1 `7 g WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
# a/ e+ d) T' z0 Y1 U3 k+ c WriteCommandLCM(0x08,1); //关闭显示
. N, y4 g/ \! w4 r' ~ WriteCommandLCM(0x01,1); //显示清屏1 ?1 u3 i. `! j2 }; f/ V$ ?
WriteCommandLCM(0x06,1); // 显示光标移动设置8 X; [: T* W$ W
WriteCommandLCM(0x0F,1); // 显示开及光标设置
0 _% n4 n4 t: E2 W& b}
7 C# `: v! j D; ^* j5 _6 L
4 V; M L( D1 P- }; A5 n//按指定位置显示一个字符
5 R& K5 S4 a1 S z6 Q+ s( Svoid DisplayOneChar(uchar X, uchar Y, uchar DData)
1 `/ k, D! G" B4 Q. @{
* s9 C+ d4 r/ E$ j2 B$ _ Y &= 0x1;
7 A, {; @. R+ g! g0 q! i X &= 0xF; //限制X不能大于15,Y不能大于19 t4 p5 \4 c% G% V& D# [; T- l
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
& C' U+ B" ^. Z: x# k" r X |= 0x80; //算出指令码: R/ U+ [4 D M1 \
WriteCommandLCM(X, 1); //发命令字
9 d5 r# r! O7 r9 o0 ]5 i WriteDataLCM(DData); //发数据
# r7 ~6 B) R+ A}9 s0 I. e0 W$ D8 T
; H, r% |- p1 l4 P" C) N//按指定位置显示一串字符
' Q! C1 D) p( l5 @6 gvoid DisplayListChar(uchar X, uchar Y, uchar *DData)
1 w& ]' B/ H" d& s: ^{
+ _/ B5 V7 o2 ^! n7 @( C' V; v( A uchar ListLength;
/ }' ]' C4 @4 q$ u. |. f0 u* L1 B5 w7 s6 C8 ?* O" ?3 k3 s2 [
ListLength = 0;
7 t- i3 u, W/ X: e% ? Y &= 0x1;% u. o3 D4 S7 B, q) U! J
X &= 0xF; //限制X不能大于15,Y不能大于1
9 {5 I9 x" M0 J& S. Q9 a while (DData[ListLength]>0x20) //若到达字串尾则退出" `0 t, L- M K8 D
{
8 ` S) V& V$ i) V; s' t1 G if (X <= 0xF) //X坐标应小于0xF" Y6 Q" j" X- _8 x
{0 S5 D; J+ ^' z p5 N
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符/ H9 N- z6 j' M. Y9 R1 K
ListLength++;6 E; I: V+ h- E7 c s
X++;0 j/ l. Z! A% Z
}
4 O" o% v" V- q2 n; X- I" D }4 h$ x" m# s2 N' M7 l+ @
}
- ?0 R/ H& _0 ?1 P1 C: i: k
/ ]/ z& `8 }/ R9 A//5ms延时5 D) ]6 K. T3 t1 A! k7 W
void Delay5Ms(void)
% o& b- t9 Y T. U4 _8 I{9 R/ F9 `1 {1 I. X! u( e4 C0 ~
uint TempCyc = 200;
" G3 L& ]) z; R! q while(TempCyc--);% i, r5 P/ C9 p \) u. f0 ^
}
, a! E: \( Z6 a# K( Y; L9 M: g0 ?, S- z3 T" I# m
//400ms延时
( I, T) o/ B3 gvoid Delay100Ms(void)! x1 [1 \4 j" [; S! ~
{2 d& M) X" b9 s+ Q) p: M
uchar TempCycA = 1;
# P3 `* r8 K+ w/ l uint TempCycB;) S, X9 e. m- h' W
while(TempCycA--)
! w1 L8 x/ I' O {
. o% e0 C4 _+ J TempCycB=7269;
7 m6 n' @0 j1 C5 Y1 ~ while(TempCycB--);
. r' p& A" \7 s6 N$ X' J }
K5 c, ]% i. D3 g} |
|