|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。; E) v* Q3 p2 V, W0 d
硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。
" p# Y- m( b1 {) X) t8 X% o2 B& U液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。
4 [3 q. c0 M: T) q) H& u超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。- G" Q4 n$ F& ]$ A' b
超声波的接收电路包含一块CD40106处理芯片。' b; B* A# F2 l
技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。
* W" [: U* o2 l6 S#include<reg51.h>7 X9 c; `/ K" W& r- u
#include <intrins.h>/ n! g& \2 W, {; B! C
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
4 j% O" |" C; p1 S' E6 w#define LCM_Data P0 % b5 P# f7 X( W& M9 y0 H$ N9 |
#define uchar unsigned char# v* Y* P; N- c* {9 H* _
#define uint unsigned int3 ?1 K4 |! e" H0 c) o, C, o
#define ulong unsigned long9 p3 Q8 f- T' h+ U+ p9 u4 ~
' `! n: Z2 x+ }( G. ^$ e
9 H; I& q2 \/ ?3 [- V1 k0 textern void cs_t(void);; e+ \% q' m% U. ^* G. [1 d# t; m
extern void delay(uint);( c( e* v: ^9 C& i6 J& {
3 ]. l/ J/ T4 \+ g
; [* e8 E& ?! N8 E$ e# ?: }- c4 f/ j2 }2 ]$ Y1 J) V
void LCMInit(void);% {' _6 j) e8 x8 U6 i. z0 H
void DisplayOneChar(uchar X, uchar Y, uchar DData); `2 e h( L1 i$ _; [4 `6 v
void DisplayListChar(uchar X, uchar Y, uchar *DData);; M; V, p$ C) K
void Delay5Ms(void);8 s% f/ P @$ }. w
void Delay100Ms(void);, q5 O$ K [6 r T% r3 p
- C% P8 B+ w" z# C; |; @void WriteDataLCM(uchar WDLCM);
3 l1 b. Z. a- d1 Q$ Ivoid WriteCommandLCM(uchar WCLCM,BuysC);( }+ z/ ]+ p' ^0 m, h8 P/ M3 S' M
% O* _& o9 r% Z& H
! l C+ ~; V! A/ H8 [( _data float distant=0.0;$ ?- @7 q# ` Y/ x2 H- n
uchar ReadDataLCM(void);5 Z ^/ H1 w8 ]# _: ^# i
uchar ReadStatusLCM(void);
7 Y4 i7 S! E* v/ X- B0 M4 |& w: suchar cdle_net[] = {"--Daoche_Leida--"};
! J8 M; U+ J6 d$ R( p* F# euchar email[] = {"Juli:"};
6 a2 W( ~1 k; J9 N+ Quchar cls[]={" "};+ j2 W4 R G& N/ y+ G; j* ~
uchar DIS[7];4 c- ]% A1 ]3 P
data ulong time;
) {) a6 R/ `$ z3 k* Gfloat distant;8 L0 K$ ?3 O4 q
sbit LCM_RS=P1^1; //定义LCD引脚& f. T+ i% x; }* t
sbit LCM_RW=P1^2; $ J. }/ \" D! z. H+ m
sbit LCM_E=P1^3; ' \, `/ _9 q5 J, x; Y* W+ v
sbit P10=P1^0;3 l# W6 M% s: z! H( ]+ t; z
( F9 D( y% B. [# S" T
& A7 _$ Z5 I9 @2 Z7 P7 n2 Kdata uchar flag;
[* f2 Q z, I) }
+ N$ ~1 q" [ Cvoid zhuanhuan(float juli)2 G7 O1 Z) p9 P% B; m& ~1 d
{4 C, o; h4 B2 K2 G/ e. y" ^
unsigned long juli1;" { Z- r x6 i0 x0 C* c
juli1=juli*100;
& }1 P! r% @" u8 t% G* QDIS[6]=juli1%10+0x30;
t2 B( r7 f) Y! mjuli1=juli1/10;
- H) ], a2 P. JDIS[5]=juli1%10+0x30;* Y" G0 f4 |% z' {: L
juli1=juli1/10;( ?) X1 n1 a8 W
DIS[4]='.';
8 @) i2 Q. M0 ^2 o6 S' y4 |+ @DIS[3]=juli1%10+0x30;3 P8 D7 Z- n+ r1 E
juli1=juli1/10;. [' r4 b Q) l3 b" w3 k8 j2 K4 ^
DIS[2]=juli1%10+0x30;
* F5 ?4 s8 B1 u4 ljuli1=juli1/10;; e5 m& U7 H/ k- |) f
DIS[1]=juli1%10+0x30;
/ Y5 k) K+ k. @4 k$ W' \8 i* hDIS[0]=juli1/10+0x30;/ a& I6 k8 V3 j8 |( w
/ ` s+ h# l) m5 C! t: U}
. X" D, I# Z% g! F6 {5 Z* v8 a# w: s) W. N1 p1 U
void main(void)& c( w' I# V j! v* Z7 v- T$ O2 [5 _* G
{
" g( p+ w; E' {; e* ^- P
" S b. ~8 l4 r3 P8 w9 s- } Delay100Ms(); //启动等待,等LCM讲入工作状态5 \* t2 B) R2 O5 |: j/ r
P10=1; 3 @ r K5 \9 I" [/ R) W2 j" M
TMOD=0x01; //计数器0工作在方式1
: d2 P. v+ b1 S( C+ A# l- p5 p1 y TH0=0;
, h1 C& P) i* S( N TL0=0; //计数值初始化
5 Z: t5 Q. O8 N3 f IT1=0; //低电平触发中断
- p& O# |! }) a+ A$ i r# z EA=1; //开总中断
G! h D; r5 J: P5 _9 `* F //IP=0x04; //设置外部中断1为高优先级中断
D/ t+ K0 i- {$ K# e flag=0;$ E' t. g. C# H2 A' ]5 t* R; q
LCMInit(); //LCM初始化4 x4 S. J6 Z1 X2 Y
* p/ T3 m9 D# Q( e4 w1 O
) {; p3 M$ `% {/ {: ?( | while(1)
, x ?8 x) f8 t- v# c, ? {' w7 w! y& x# i/ k0 ?) C1 {
cs_t();1 v. a) a, C: d" g4 Q* e( ^
Delay5Ms();
. s: q6 f( H* j/ A- r ET0=1; //打开计数器0中断
l6 V2 q. {7 i% Y- J* u; c) ` EX1=1; //打开外部中断1
" D0 P3 {; s# D- |* @- |! l( ]' n; u TR0=1;( l9 p- `, s G# K+ [2 @$ q' W
while(!flag)
& T% ^9 v6 G' m2 g- a3 ]0 Q {
1 v1 m) Y0 `. Z7 g. z* s DisplayListChar(0, 0, cdle_net);! ~- ], |, \: R) {! q8 s
DisplayListChar(0, 1, email);1 n( X1 E8 p$ q/ N3 _
}
0 Y% ? l# U7 _) i" S& n0 c if(flag==1)6 ^& C) }# {5 ^% v9 W! t; Q
{
/ b9 W1 `9 A: `3 [ time=TH0;. h! t a, L5 h, U& A' m$ @
time=(time<<8)|TL0;# Q b7 B7 j. K8 |' m
distant=time*1.72/100;8 |9 c& \+ n) m) X& t$ S/ {
zhuanhuan(distant);2 Q, W: m1 s+ w# N9 ~. _( `# [) h
if(DIS[0]=='0') DisplayOneChar(5,1,' ');+ E- p9 L5 Z. O" O! a; g
else DisplayOneChar(5,1,DIS[0]);( c/ ]6 O4 O+ [; D- e5 v: m
if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');
9 j! P, ^6 Q6 @' k. Y; m+ r else DisplayOneChar(6,1,DIS[1]);, I4 R) | v& T# v7 g0 l+ B
if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');
4 Q. M5 T( U, _; z8 ~: E else DisplayOneChar(7,1,DIS[2]);8 N" q6 g$ w7 h/ Q! W5 ?
DisplayOneChar(8,1,DIS[3]);" ~1 P8 x/ I9 A- s% W7 A
DisplayOneChar(9,1,DIS[4]);
$ p, F3 E: _8 k# s/ g6 z DisplayOneChar(10,1,DIS[5]);! x+ K. _) J( l5 _0 ^ L# W
DisplayOneChar(11,1,DIS[6]);
8 o/ K* v9 b5 W DisplayOneChar(12,1,'c');
2 u. W0 w! U+ {/ _4 ?& A6 a. R DisplayOneChar(13,1,'m');
- i+ a2 t, H S- Q1 W flag=0;
- `, c6 M9 O: m. N2 I1 L3 J }# s6 R) ^9 \- y7 _ Z& h/ Y5 t
else
' F4 ?% f4 C: I; k {1 H6 }0 d x0 {- w8 A1 l" G5 a
DisplayListChar(5,1,"error! ");
6 O7 T* F( I9 h2 P flag=0;
# w0 e* u3 [) r" t8 e }
( h' K0 v0 ]: V, q& L X" a5 P TH0=0;
) M( Q# ?: ~/ p q% r9 a+ T& e w TL0=0;7 r1 p+ V7 [* r% X0 {( c0 A3 |# d; y
Delay100Ms();
) k/ E5 p: {: k# X, Z0 Z }
* J, B+ E- K# @* V}
% Y4 C0 ^" P6 W- u7 Y: z( t) ?3 E8 p0 c) S3 k7 ^; D" O. `: N
( ^; Y j/ N% d7 }/ G1 Y0 R% {
" l; L* g) a6 A( Tvoid cs_r(void) interrupt 2
$ T) q$ A" k, ~$ w3 {% o) b{
, w8 ~* P9 O7 k: pTR0=0;
2 ]3 R7 ?+ C* }3 P* {+ L! P4 v& d' MEX1=0;
* A* F+ s4 E3 W/ }& z! KET0=0;
& Y4 x( Y. h* r3 kflag=1;
; }$ `/ b" H. p( w}) h6 K+ u9 F; w/ e
9 Z5 ^+ R% `& p' |& u E" s& ?7 t' |: s' G' u
void overtime(void) interrupt 1* O; i7 |1 d: e9 ?) {9 w
{
v# J2 g3 X2 I b/ d+ d$ xEX1=0;" @. X9 h& s1 |- Y2 q5 g
TR0=0; {, }& D% k( q$ l. G& m* t6 q7 D
ET0=0;
' ?1 o: y5 a3 qflag=2;5 o+ v& L& g7 C! C' \
}
! @, P v" U3 {! a% U' i6 Z
% w0 ? ^% ]5 z$ o/ l4 W
/ f x9 C. D# U5 D' L//写数据
5 W$ r. m# e+ V- Y/ v( n6 \void WriteDataLCM(uchar WDLCM)
/ o) T0 ]2 M, |5 A- {) R8 B{3 j8 E4 t! I B# I
ReadStatusLCM(); //检测忙6 b7 l, m3 Q7 g# S) p
LCM_Data=WDLCM;' E* D H o. C6 E- K
LCM_RS=1;" c' N a: k! R: C8 X
LCM_RW=0;1 }/ R9 E; Z) m, h7 ]4 p$ a8 j) ~
LCM_E=0; //若晶振速度太高可以在这后加小的延时
& Z3 C- R% n. M# O' w9 \7 s2 J' i LCM_E=0; //延时
6 I/ i( F+ l( e' Z9 z! ` A LCM_E=1;$ r, Q: H ~ J0 b$ t/ A
}
% A/ t+ n2 J" D1 E% d4 ~2 C3 T9 `3 l
//写指令
6 I5 y# m8 E0 }. p2 { C' L# R" nvoid WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测* r# v4 ]; m& [/ L+ R
{* F5 h8 ^+ n3 h
if (BuysC) ReadStatusLCM(); //根据需要检测忙- U* L0 n( k, R6 U3 l$ f/ i$ y
LCM_Data = WCLCM;
" r& ]8 c- Q3 R" C% U+ w F0 ] LCM_RS = 0;
3 v: O( O( p$ h& Q A! Z- z6 Y LCM_RW = 0; , g9 X9 G4 U5 h
LCM_E = 0;' ?3 ~& G6 q/ }5 y! Q7 z
LCM_E = 0;
! h! u7 c3 ^7 @1 C LCM_E = 1;
% P, I1 p5 N9 d ]8 ^}6 q0 Y: x6 S1 j n3 W% T
, `; S' Q: m4 j {+ R' n//读数据
8 J, C) z Y0 X) A8 b* O" ruchar ReadDataLCM(void) a1 h: i! g& K2 e' _9 ^/ e" u
{' u. B2 G/ d) g) b% Z
LCM_RS = 1;
8 z& C; j/ b6 u8 |+ ~$ E4 L2 Z; h; B( N LCM_RW = 1;
2 Z$ {6 A& a6 M: n: ~+ t, c LCM_E = 0;
3 ^1 @4 L) k# G LCM_E = 0;
( M; p1 P4 W5 ?6 s# B8 y. H LCM_E = 1;
' G5 v: \9 e* b0 Z4 A& p" w return(LCM_Data);* S [2 b4 M) |) }9 p
}5 a' ~$ |. ^3 x
& F: {- |6 @; h% b8 H) I7 J//读状态; h7 w5 O- _, C3 o, M7 a5 t0 A0 s
uchar ReadStatusLCM(void)+ t6 D1 d) |! [3 S. p% M7 S; `. `
{. U7 j! I) L4 W$ x
LCM_Data=0xFF;
' w3 |: l5 c8 K LCM_RS=0;$ F" e9 p) N" n, ?1 Y
LCM_RW=1;
" n5 X# g* G2 m+ p' a- K0 y. k LCM_E=0;$ Z& I+ p- |" X% m
LCM_E=0;
8 Z# s4 P {7 `$ A( P1 z# g LCM_E=1;
$ M9 U# E L# I8 ?$ f7 p* E while(LCM_Data & Busy); //检测忙信号
( o# Q- Q6 ?0 F. I$ J& C0 } return(LCM_Data);1 ]- T+ v% s6 y7 H+ k( {; `
}
2 q4 E a# l) Q% D7 u+ Q) g3 G" x' G/ c, `9 e
void LCMInit(void) //LCM初始化
8 B- O- G7 A0 {' Q! P{* g( V: {5 F* `! g: g
LCM_Data=0;
% F: ]7 |0 O! m4 P; r WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号0 e0 }' s6 B4 Q e- n3 M
Delay5Ms();
: B. s, v" ?% x0 I- ? WriteCommandLCM(0x38,0);
' K8 J% S T0 f' m: t Delay5Ms(); " U1 |0 ^; [$ ^0 p
WriteCommandLCM(0x38,0);
1 U7 ? R& M- i0 i9 ? L Delay5Ms();
9 l) w- q$ S6 r9 Y' ^$ w2 {) [( z- B
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
5 y6 z! d# y( [1 S2 c" N) g' |- M WriteCommandLCM(0x08,1); //关闭显示7 W7 e: x' b4 P5 s
WriteCommandLCM(0x01,1); //显示清屏0 @, @0 m& @6 D4 ? m2 {5 S
WriteCommandLCM(0x06,1); // 显示光标移动设置 f8 L( S& L8 y
WriteCommandLCM(0x0F,1); // 显示开及光标设置
3 w, `0 C N6 ?' h6 s7 Q$ D; T/ @}
2 |+ P; W) m @* B6 r
! j' S& M% X: [1 j* `/ B//按指定位置显示一个字符
9 m6 L: c' U( c- |5 U3 k8 E% `2 hvoid DisplayOneChar(uchar X, uchar Y, uchar DData)
4 ^( q& o2 Q& K4 B; f: |9 F/ A{
# h: v5 r2 N6 t+ f( M Y &= 0x1;
. \1 ^6 c9 ^& H2 \' E; ]( C3 \6 M X &= 0xF; //限制X不能大于15,Y不能大于1
+ O: @2 y4 h" k( |8 y |' C7 j if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;3 l" c# q1 {" W6 R* |
X |= 0x80; //算出指令码: t4 H5 Q L7 B/ c& i" {
WriteCommandLCM(X, 1); //发命令字 W0 N: B# `. I' u. ~
WriteDataLCM(DData); //发数据
- W G' G7 {9 a}2 u' W5 P3 X; f: A
9 K' m O( r7 @+ f% E' |. k4 x2 Y//按指定位置显示一串字符
% L9 X( M9 X; m$ W x6 j+ o- ^void DisplayListChar(uchar X, uchar Y, uchar *DData)3 O+ u: |! j! F# b! P
{: b6 L( P4 u% @' r, E' G; e5 r" B
uchar ListLength;2 U7 P" X1 {' h A, L7 @# p
1 }& M: y' \: T2 X ListLength = 0;* T/ v3 C$ x, q) s/ H) i
Y &= 0x1;
1 f1 k9 S( d& P S j6 v& u4 } X &= 0xF; //限制X不能大于15,Y不能大于1
5 ~9 ]' w1 {8 R: w" l while (DData[ListLength]>0x20) //若到达字串尾则退出
. V6 ^# d9 ?% w4 y {! ~! X7 K2 e/ n' c
if (X <= 0xF) //X坐标应小于0xF
* V. `: p/ B1 a+ c- y3 N: Z) k8 m {
0 B. h+ E; \, O8 a0 L# S DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符( ~0 d9 u7 H3 A/ b% W; o
ListLength++;6 y1 S- I- {# n8 [) V: x- P: J
X++;2 W# c" o0 H! k( o
}
# {2 [4 x. g2 F+ e% O, A }' m' L$ r, E3 e5 Y9 R( z/ E
}
5 @/ ~6 J0 Q8 N
9 ]) x8 ]7 m9 a3 f* ] _//5ms延时6 K8 K; Y& n+ l+ n$ o$ F
void Delay5Ms(void)
+ T* y1 X* X3 Q. e8 f9 ?5 q* j{- k6 j l" g( ^( ^6 M% Z
uint TempCyc = 200;: q+ b: {$ V [9 u: o/ c6 P
while(TempCyc--);
4 u, A' O4 o4 N/ T- I8 g: n}% [4 V( y: q* r7 i
X2 A( U$ @0 C5 |6 F! P
//400ms延时
6 c5 k F. U7 l% l# [) l: s% uvoid Delay100Ms(void)8 P, w- w; h: e
{) _- ^( u/ w8 e: X0 Q
uchar TempCycA = 1;
! v; k" T2 H+ @# V uint TempCycB;
! O+ `* v# ^1 Y( O while(TempCycA--)
" J+ w" j4 v# _ {
& ?0 Q2 h2 b* b5 s @. S TempCycB=7269;
# f) ^: ?! P% x* Y while(TempCycB--);
0 r* y* e" }" E$ [$ I/ |8 \+ n. C }. f. N, b) \' g! F$ M: B) k
} |
|