|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。
% L# A7 y7 q5 t硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。3 _# Z% m% z1 N. g. v4 p+ g
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。 N1 l5 ~9 ^$ }2 H( m6 y
超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。0 `* T6 ^$ u7 H+ ^. Q, e, O
超声波的接收电路包含一块CD40106处理芯片。
1 V @- N, y# U; ]8 d% i1 e" W' L9 b技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。$ H! T. D3 z5 A% ?0 ?: x" ^; r. p$ T
#include<reg51.h>: P- D' r$ O; H$ P9 N: o6 j
#include <intrins.h>1 f0 c" Z( R; d$ H0 U
#define Busy 0x80 //用于检测LCM状态字中的Busy标识3 c0 X* g+ t! |. {
#define LCM_Data P0
& h0 m& u* c* G#define uchar unsigned char
( U, a' D2 f" V#define uint unsigned int
4 I$ T! L3 V: g+ d! Y6 c/ Y8 B#define ulong unsigned long
, M" w! O4 H6 h8 W4 x; Q( }3 B8 l* d# v! l6 S; j2 d- C: b
) f) H0 f7 w0 ]* b$ H. y5 @extern void cs_t(void);6 w% ]( E: E' J9 h- z0 J$ ^) \
extern void delay(uint);
- r" x* i" |* k
( E" F0 [; j( Q8 l8 J( X$ T, ?: T) A8 ~' J! N/ G+ a7 a/ L, \
3 L, O$ d# F( `/ I, P7 ^& ]4 Xvoid LCMInit(void);7 s4 Y; T+ h0 X' v; ]$ |
void DisplayOneChar(uchar X, uchar Y, uchar DData);
' J* p: m8 ~8 r. J# H7 Svoid DisplayListChar(uchar X, uchar Y, uchar *DData);( z/ ?% e+ w ~ P4 ~
void Delay5Ms(void);
9 B( n# Q$ I3 \' k F* ^void Delay100Ms(void);, _! @ S( A4 g9 ~) c9 m4 T
- @+ V, Q0 P e& s2 evoid WriteDataLCM(uchar WDLCM);
& _+ ?& `. e* Z) G: y% ovoid WriteCommandLCM(uchar WCLCM,BuysC);) G3 t# X! t* p& ]7 \
' U3 L' E5 n" J) a& D
4 r; w# m1 k% U# n5 s# W, Udata float distant=0.0;
/ ~7 j0 J+ E9 C9 U' T5 Buchar ReadDataLCM(void);5 h: _0 B- ^$ L
uchar ReadStatusLCM(void);
% w4 e4 K5 V A" d2 Huchar cdle_net[] = {"--Daoche_Leida--"};
( H$ p& O1 q; a L1 H1 V! f0 U9 [uchar email[] = {"Juli:"};1 [6 n, P% H9 I9 J% i; Q* c
uchar cls[]={" "};
8 v" t* J. B! c& b4 f2 l! {uchar DIS[7];
' h: K; F* g0 U3 T- k- q% Y3 Gdata ulong time;* x f3 S) o ~/ _* o6 r1 [: g% S
float distant;4 E+ }6 H* c! _' Z3 X. Z1 x
sbit LCM_RS=P1^1; //定义LCD引脚' {) V1 I; _% ^* d+ {
sbit LCM_RW=P1^2; 9 U% z. U, c$ ~: U
sbit LCM_E=P1^3;
: X" C; n" X5 B* t- _: g( ~9 }. Xsbit P10=P1^0;
4 W9 ~, v. e2 h+ z( |
8 ?! g# Z5 c# C# _2 U
/ n8 h% b4 S) I, R3 T2 Z( T0 z! @data uchar flag;5 ~0 h t p( X. M3 m2 U1 J" X) J
4 X" o" N8 t% Z$ M uvoid zhuanhuan(float juli): u" y! ~: J* r; R$ K
{9 K/ _& E" j% k- K
unsigned long juli1;) L; c9 i# [; H$ X
juli1=juli*100;5 i3 _$ V7 F9 x5 o: G9 {& d8 y5 @
DIS[6]=juli1%10+0x30;; h, @$ X' Z% _$ _4 X$ v
juli1=juli1/10;% B) q# Y1 N+ W( v* a, }2 {
DIS[5]=juli1%10+0x30;2 f. F( \9 F+ k* `/ I6 N r+ j
juli1=juli1/10;5 E$ a, _+ V+ ?7 D
DIS[4]='.';
4 L7 s# |0 A- |& H) IDIS[3]=juli1%10+0x30;: q8 L9 z8 g( I5 d
juli1=juli1/10;
0 H7 E& x# }" I8 O9 @+ W! xDIS[2]=juli1%10+0x30;, b7 a- F9 \ Z1 ~( }+ l. ~
juli1=juli1/10;
& b# u, d/ y; Z- V4 s: CDIS[1]=juli1%10+0x30;, F- a# h6 M4 m
DIS[0]=juli1/10+0x30;8 k+ `# A% R, S5 g. R5 _
% C0 h* [ p) K}
; ^/ d; @! ?$ H# t7 h" d" U- `1 y( ~! w; f3 c* M
void main(void)
6 U! p5 D3 E. i, Q* q" c' Z" z{
' m4 N& I# |( b2 Z; \
4 F3 u6 }! F+ |. ` Delay100Ms(); //启动等待,等LCM讲入工作状态& v0 B1 B( o( O- u w
P10=1; 0 R* ]5 B- [% l3 P/ g; o6 Y
TMOD=0x01; //计数器0工作在方式1# o6 U, @: y3 a% v P' K% w* N
TH0=0;( t; D }- y0 G: V
TL0=0; //计数值初始化
2 R: R/ l/ y+ _% a- ?3 O' t IT1=0; //低电平触发中断0 G) e" O, c n
EA=1; //开总中断) B# `; ]! q+ ^# a5 Y+ {; {+ b \
//IP=0x04; //设置外部中断1为高优先级中断
* _6 _3 f( s7 E* y2 R flag=0;
0 Z* _9 D& E+ k LCMInit(); //LCM初始化" D' l$ u" J& `6 |: u0 V# U
- U% s8 c* l4 F" J2 q6 K/ x6 g" l
4 L1 Z$ v3 n7 k. W7 E
while(1)4 w5 j2 P7 P+ V9 g7 j5 X. ~
{
1 f* R# G" |( p* }6 p8 D/ H# Y cs_t();
* o6 ]* P5 ?; Y# K# u Delay5Ms(); " J3 c/ S8 `# W* v
ET0=1; //打开计数器0中断) ^8 n% t# P! i) s2 L/ I2 C! o
EX1=1; //打开外部中断1
/ Y; h9 n, @5 b& c- K/ O# q# N TR0=1;, r! L: K: y( N. W6 ?3 \+ c v
while(!flag) 8 F+ r Q% B8 |1 R* C
{# x! T0 m% E' v% X+ M. S
DisplayListChar(0, 0, cdle_net);
! F% l6 L- |8 c% F# g3 j DisplayListChar(0, 1, email);
$ O: B H9 s; B O* ^8 w: |( f" L }2 w) o. e' X7 l
if(flag==1). c) ]( o$ v, R4 H. v$ G
{
/ k# c+ D \# |9 j time=TH0;8 C6 ^2 U( H* s
time=(time<<8)|TL0;
- T1 O( q6 j& U% g; W7 i { distant=time*1.72/100;
- y% a* |, `: z* _) T; } zhuanhuan(distant);
) n& ?% e. d! _' E if(DIS[0]=='0') DisplayOneChar(5,1,' ');% x5 c2 V% \6 }5 `- [
else DisplayOneChar(5,1,DIS[0]);
# w$ Q+ y5 n# T if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');
% q y& J$ W: Y* s {% K else DisplayOneChar(6,1,DIS[1]);8 s: P$ `$ d& M# @
if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');* O/ K6 N# l1 V. a' @( ~7 Q; F
else DisplayOneChar(7,1,DIS[2]);
5 [9 L$ _, p2 M) X$ r& C+ L8 E DisplayOneChar(8,1,DIS[3]);! F/ O2 o( P6 f5 J) Y
DisplayOneChar(9,1,DIS[4]);7 ?+ a9 O% r, Y/ U1 z
DisplayOneChar(10,1,DIS[5]);
: d4 {$ |/ @. b A/ T4 \( a DisplayOneChar(11,1,DIS[6]);
@$ \. [# v6 c" @& B DisplayOneChar(12,1,'c');! y3 m) J5 x5 y/ ]+ l. z8 x
DisplayOneChar(13,1,'m');
6 S+ v" K/ H' F- g! o% y g+ V flag=0;* M; i Y" Z/ J8 ` S q1 |3 l
}2 e8 x# V7 b2 S Z. D: r
else
9 Z1 O. C; q( v# F) [: f9 o {( H$ T# L3 @$ D1 _. y2 s; }. J
DisplayListChar(5,1,"error! ");) o' u. ^4 n5 h, M& n
flag=0;9 r, m. X0 u% I' O9 h8 s
}
8 y* k* E2 m7 m- \ TH0=0;
7 _! v9 M* d; {$ x" a TL0=0;
: N) W9 X% T1 T, \5 A) A8 a' [ Delay100Ms();6 X5 ?7 r$ x) @! i* x. d' {% E
}
" t J+ Z; L! X& A! P}' v. G; M q7 X+ Z
# _0 ]( }( O0 h2 K9 E W9 y z$ C
. T5 S, b' s* A, ~
) f9 z. d( M: n( @5 Ivoid cs_r(void) interrupt 23 L* T4 R6 {8 w h: V9 [% r
{
+ B! b9 W& K8 {- O4 k% @/ ~& S& h' kTR0=0;& b1 a M! c/ A% b
EX1=0;
; c( k5 ]/ w" h, DET0=0;
( h5 [& y3 [; f# c/ D1 {flag=1;6 d( y% V: l- U% y
}
8 X4 {; _ R* Q2 a1 c) U: F# U6 @* x: w4 P% t% `
. y0 Z0 ]& V# Z, g9 Zvoid overtime(void) interrupt 1
2 n5 n; |' n9 r3 A- `{6 |2 M6 r0 u4 [' o, {
EX1=0;6 I) s- R/ K& L7 z5 i! |
TR0=0;9 n( J4 N! L9 t- D: s2 O7 I
ET0=0;
: u) p9 y& m( {" z& ~# Oflag=2;
. Q: c" _2 G% ~}
. L7 W4 V4 Z( m
+ V- N3 A2 ?' B, X5 r: ^
$ c6 N2 f9 R' n. b//写数据
& z; h* W4 W! W: kvoid WriteDataLCM(uchar WDLCM)
4 q2 E5 U7 }, F. E q2 M4 B& P+ S{8 M6 a& Z- F" @" g2 h3 K
ReadStatusLCM(); //检测忙
& ]! ]6 P6 [8 K0 g5 m( w LCM_Data=WDLCM;
. t; P0 T) W6 `$ Q8 T; X LCM_RS=1;
3 s% m' [! H3 k' S9 [ LCM_RW=0;
3 B. p! e8 e0 a& q, Z LCM_E=0; //若晶振速度太高可以在这后加小的延时2 K' o) L8 Y! W
LCM_E=0; //延时
2 p! M u1 K; s& L LCM_E=1;
/ P/ J( i; Z* q' \+ N+ ~}
# G. V. o: a5 G# V4 ?
+ m: h- d- ]3 C$ l+ e//写指令+ j. _) K, X. J- I6 D: u
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测* O5 u$ `* ~" O% g$ |$ |& O
{
+ F! x6 b+ ^0 M1 O, p$ \' Y! K1 v if (BuysC) ReadStatusLCM(); //根据需要检测忙
3 M5 a( g4 A/ D/ A8 O+ ?- a2 ^ LCM_Data = WCLCM;6 y: Y0 j$ Q6 c' c* }
LCM_RS = 0;
3 q7 R+ ~7 e4 N/ ], y, s LCM_RW = 0; 7 l [, p5 s! R, D' e8 X! R
LCM_E = 0;
1 M' l5 |5 Q! q e$ g1 x7 p LCM_E = 0;
# a2 A( B5 j0 ?5 q$ p LCM_E = 1; ' g. W5 @, W; h& K& G, j
}
! s4 v4 F+ ?) P+ j. H- N6 O& X6 y2 j* a
//读数据( k+ P' D$ h! q" J/ C5 X1 n: Q3 ?
uchar ReadDataLCM(void)
9 ]( Y" F) G$ ?5 n& {- p' u{ r. `0 A O& Z# [
LCM_RS = 1;
9 n( c; x. }( v0 v! ] LCM_RW = 1;# _* u% {6 u, b. L+ }: p: V! o
LCM_E = 0;3 `* g' ^0 n3 G- _
LCM_E = 0;$ ]' U! P/ v/ a. t
LCM_E = 1;
9 h7 {4 E) H+ x' R9 M S- O return(LCM_Data);) ~* w3 b$ ?4 D) v7 k
}0 h% `& A- o- P" x5 ?. M/ d7 I# f
" _" d. @, `* y- v4 {3 ^
//读状态% N/ h* @! x- B& q U+ S
uchar ReadStatusLCM(void)! Y1 A9 T5 ^5 }. R9 c6 n" w
{7 U4 t* z$ r7 }6 z8 U* o
LCM_Data=0xFF;
& b0 f# R: r% l2 c LCM_RS=0;
# O$ s; R% l' r' F# W LCM_RW=1;
- ?) P7 `% z: `- { LCM_E=0;+ ~" z& o0 A* W) i
LCM_E=0;2 g- W: o, d9 |
LCM_E=1;) s% u- T, k3 e# E
while(LCM_Data & Busy); //检测忙信号( C' r+ K' f7 J: j2 ~% `6 }
return(LCM_Data);8 \6 C" q8 S0 @( X- D& L5 f3 k/ H8 J b
}
" A( [' y& j! q( V* j+ V5 ~+ b0 ]
' z+ p/ r7 u: kvoid LCMInit(void) //LCM初始化
3 D3 S. f0 Z% J{
1 C& J4 w5 o% @0 i4 ?% w LCM_Data=0;
+ `* ^! Z3 ~: z3 \/ ?: `$ A2 y WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
8 e. A# Z6 e( ], K Delay5Ms();
: q6 a/ N3 ^# f- c0 V WriteCommandLCM(0x38,0);# y4 m. j% B- Y! W) W9 M
Delay5Ms(); 9 t; C8 Y% x) J* I
WriteCommandLCM(0x38,0);% k) N# A9 K* B+ ]6 v' h
Delay5Ms(); 6 N4 C3 O9 }( h3 a9 U6 j
9 }! M; N( Q, w WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号* Q# e. g, p+ y3 L/ T7 a$ _% z
WriteCommandLCM(0x08,1); //关闭显示
( M0 c1 P% W1 c WriteCommandLCM(0x01,1); //显示清屏* Z( z" e: ]; u* u! J+ X! d
WriteCommandLCM(0x06,1); // 显示光标移动设置3 j. `2 h4 J+ U' V
WriteCommandLCM(0x0F,1); // 显示开及光标设置* `- F7 Q: {1 O' ^: `
}% h$ e* m4 j. S8 _# ]8 L
6 R' ~0 G! ? j8 t3 q) A
//按指定位置显示一个字符' K# s, s6 ^; R5 f( A
void DisplayOneChar(uchar X, uchar Y, uchar DData)
$ a/ r- I* c4 H! q3 X1 ]- M% C{
+ C8 ~( o) C5 D" ~% G# y. L4 R0 A Y &= 0x1;
7 G1 p6 e4 g: G5 k* Z) J X &= 0xF; //限制X不能大于15,Y不能大于1
1 O1 t6 ?! C# }& {6 x v5 d" ] if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;8 W- A: {+ [0 L; h9 U
X |= 0x80; //算出指令码
2 K6 @9 T) b0 E: ^3 e WriteCommandLCM(X, 1); //发命令字
5 T6 S$ F& @# I: {# ^ WriteDataLCM(DData); //发数据$ S' O! o; K! {
}
4 I; T1 D% T; A5 a7 e+ j/ i8 a4 a
//按指定位置显示一串字符
0 w7 R! E+ \/ y: W8 X' |3 a% l wvoid DisplayListChar(uchar X, uchar Y, uchar *DData)
( {8 Q& v1 N! Z, O{; O% x. O; B. O5 \ b- s
uchar ListLength;
6 [+ U$ h6 N- |, e4 O0 n3 e! ?1 ~ W7 V) H$ T: I: p
ListLength = 0;
3 [# o9 n1 X1 \- T9 J+ t U& y9 ` Y &= 0x1;
5 ~" r& b' @9 |; I- { X &= 0xF; //限制X不能大于15,Y不能大于15 u/ y/ d% L. z7 e
while (DData[ListLength]>0x20) //若到达字串尾则退出
E9 Y" ?: k, k. W: `) U; h% k! x {2 W3 H5 y1 L* P& h, B6 {
if (X <= 0xF) //X坐标应小于0xF. j0 t% Q% m* p; d: R1 Y& }
{) ]: v- b5 Y5 [9 Q. J
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
, f' x! W" Y& M ListLength++;9 D! f/ N6 ?. v9 L
X++;+ k6 u) l3 G2 Y( z
}
- ~4 j) [" V. x7 M2 b }
* w. e4 E" e" K& p}( h2 s3 E% t/ }! m
E( o1 S: s( A' _" l8 \" M9 G//5ms延时/ r9 O9 L8 ~7 ?
void Delay5Ms(void)& I2 c: @- f3 S+ ^$ t
{, g4 n0 ?. b# q
uint TempCyc = 200;: c$ V \7 @# Y$ h1 ? d* t6 N0 t9 n7 X
while(TempCyc--);
1 W, m9 b: y1 ~' d0 A/ V7 B7 n; h" W _4 K}
# f; B }3 B- b7 D H! n. {) {' z9 H7 B. G! v" D
//400ms延时& F% F: U0 Q8 p1 F3 Y8 j x, [
void Delay100Ms(void). }# N5 g0 r4 E
{
9 V' \3 k" n3 r# x7 ] uchar TempCycA = 1;, j/ b( L0 Z0 k
uint TempCycB;
& R, W. S' `/ ?% B* A( V while(TempCycA--)( Y1 |8 V& m/ t2 Q) F0 N, ^9 ^' m3 t
{
& \. `* h6 }. p, R+ X TempCycB=7269;# `3 x! \( ]& ?: {( Y( `+ U
while(TempCycB--);- o! v# q( {1 x( C L' t
}
$ y$ g' ~6 @1 { B1 t& J} |
|