|
|
|
马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!
您需要 登录 才可以下载或查看,没有账号?立即加入
×
下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。! o" M* B v- W# i
硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。$ `# ?2 s) E$ q0 ?* J6 u0 l
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。' i9 f7 y, _' I7 w
超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。" ^/ Y' q8 n4 u: r6 `
超声波的接收电路包含一块CD40106处理芯片。
T5 J# v* i5 b0 ]* X& I技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。: ]& B2 T/ ]6 T+ b1 Y& R$ @7 K
#include<reg51.h>
1 v; O6 p( n$ L, ]) E# p#include <intrins.h>3 G# J( ^; K |0 ?: Y1 {
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
+ F# s# H2 o8 I8 \1 a6 U#define LCM_Data P0
G4 G( o' T7 k#define uchar unsigned char
% G3 i! E$ ~# i% ~. @5 a( N#define uint unsigned int
0 K2 ] M5 D& I E; ^#define ulong unsigned long3 V3 a; r N- F$ A
- q/ J) K0 Y. ?5 H" n; ~6 g! q+ c4 V# p
4 [2 P5 \* X2 C1 E8 Y
extern void cs_t(void);
5 [: K* _8 B" t$ D. T0 U/ ]extern void delay(uint);
; z; H8 ^9 T; j% j, H9 S4 [
7 {% A; u2 j6 j9 a7 X# M* f0 _* i/ T* V2 [" F
# J& F' X( o i4 t Q" x
void LCMInit(void);! g2 t6 Z5 Y: }4 w% P% }
void DisplayOneChar(uchar X, uchar Y, uchar DData);
" _4 d9 Q4 M0 l l N3 M, R( p X; I9 Kvoid DisplayListChar(uchar X, uchar Y, uchar *DData);: B" N5 H2 Y$ n1 @$ X' O1 B
void Delay5Ms(void);
) u; W; q6 Y z4 Z9 s: yvoid Delay100Ms(void);
( f$ P, g% m; a) d; K1 D, t2 f# P( J9 U* H. s
void WriteDataLCM(uchar WDLCM);
/ g. J" Z7 x, I2 Lvoid WriteCommandLCM(uchar WCLCM,BuysC);
' t8 H9 c; J/ ^; ^1 d% m0 e' l
) K: m9 F, U1 d; X5 G$ p5 v- e+ K. p& Z
data float distant=0.0;' U9 k, N5 F! Z% I. i
uchar ReadDataLCM(void);
9 |; @! O: h" T6 o- K1 q ]' E* quchar ReadStatusLCM(void);
/ }( `$ e$ z: S Duchar cdle_net[] = {"--Daoche_Leida--"};
4 L3 ?+ P0 j. s2 T5 V; wuchar email[] = {"Juli:"};0 d6 O. b# ~7 w6 l3 W
uchar cls[]={" "};1 ?/ v' G+ @. a- J# |, n. B
uchar DIS[7];8 z" [5 G. q* m5 g
data ulong time;7 B5 j( c$ f8 v3 `
float distant;
& b+ f0 u2 A- K0 ?* isbit LCM_RS=P1^1; //定义LCD引脚& W8 W( q- U' ]) M- Y l
sbit LCM_RW=P1^2;
. s# u {% E& d" e1 K0 k* Msbit LCM_E=P1^3;
( }9 o9 f3 W$ C% `* d! Gsbit P10=P1^0;
' [# b3 U0 X1 ^7 a F" Z+ j0 U+ i& k1 B* _
# d' m6 ~( X7 ]- [- @. G o' x+ Gdata uchar flag;
0 `- m2 F& j) X4 C2 E) W
) L# z+ T* i8 n2 vvoid zhuanhuan(float juli)
6 n8 }9 d9 m: f: O+ a: ?" K{
; h' z) V- J" f' c. `- Y) a3 Eunsigned long juli1;; t- L% d$ a2 _2 s5 }: Z
juli1=juli*100;
; r4 E3 s2 B7 x* k, jDIS[6]=juli1%10+0x30;
/ _0 @3 i5 O& y3 Ijuli1=juli1/10;
! M. l7 E, e7 T7 ]DIS[5]=juli1%10+0x30;- X8 N6 c D& }" _$ K# m
juli1=juli1/10;' H/ |6 Q: x' r) V* Q8 e ^
DIS[4]='.';
6 j7 {* m& r# V; b; t2 z0 f5 x& ?DIS[3]=juli1%10+0x30;2 w8 Z: ]5 `4 k
juli1=juli1/10;
( e$ r) l( H W# [( XDIS[2]=juli1%10+0x30;$ ?/ |% E% x4 K$ M& a% A
juli1=juli1/10;
! Q/ X/ U% b$ v+ s9 MDIS[1]=juli1%10+0x30;
$ c' L" D/ k8 L: d9 ZDIS[0]=juli1/10+0x30;/ x/ K/ v: @& g0 a% o& s7 ]
- r& K7 o8 ^' _6 }
}
: \$ ~) s# J `
, J' `! H2 ~: B1 u. }& O+ |& t& `void main(void)* a( t" V& F, S/ ]/ p
{' i; O4 E0 I& Z: P; f$ l
) F. i5 ^0 a( v0 O. l
Delay100Ms(); //启动等待,等LCM讲入工作状态
" ^% m: ^, f7 j+ I$ d# w+ S. w2 A9 F0 W P10=1; $ V" g: |( c7 n1 }1 R" U
TMOD=0x01; //计数器0工作在方式1
) K7 A" ~8 M1 b" z* d7 W TH0=0;
9 z g& ?# C$ z0 X) ? TL0=0; //计数值初始化$ H0 |" N- l6 E- f' P! M
IT1=0; //低电平触发中断" q- r" o: Z& A0 F' w( k8 @
EA=1; //开总中断
H& g+ H3 X4 _4 R6 ?% J' @+ s9 X //IP=0x04; //设置外部中断1为高优先级中断 `9 @' h3 v- c+ G. p
flag=0;$ w0 }" f2 M8 Y; u6 Y
LCMInit(); //LCM初始化$ g& F T* |$ m9 S! K# C# p+ u
: ?2 g. n( i) |2 H; r1 Q, \
0 B# n& `. q3 Y4 w- q# Q+ [ while(1)+ W, N& {5 S3 Q6 N0 B
{4 v l a; H; Y5 U! ]2 |
cs_t();* Q$ s1 a0 N9 k! q2 `5 b
Delay5Ms();
; ?4 c: ~2 J, v+ ~2 m: K; Y' P ET0=1; //打开计数器0中断
* l+ P1 S! G0 g. I EX1=1; //打开外部中断13 F4 }" S+ ]6 Y8 R, x1 g; V
TR0=1;
1 t2 u, D8 u+ z( u" n, N while(!flag)
; E) |1 n! B/ E( N# x {$ y* x1 \% m2 ^1 p
DisplayListChar(0, 0, cdle_net);9 ]8 |# o2 Q- S+ l8 S g
DisplayListChar(0, 1, email);
8 F+ f1 V8 g# d# a/ } }. M% v' q {/ U
if(flag==1)
' R5 j+ M' H! O/ q2 w' P {
, ~, J* o7 Q, i* k0 }6 V. G+ p3 d time=TH0;1 O6 b; H) B- N5 H: `9 x/ m
time=(time<<8)|TL0;
% h. J6 `& B! l: P2 r distant=time*1.72/100;
/ P% |& B8 V1 X1 A7 X zhuanhuan(distant);
5 f4 M0 [; z7 E! u: g if(DIS[0]=='0') DisplayOneChar(5,1,' ');
& _2 \" |( F% b+ A% ?/ B7 B else DisplayOneChar(5,1,DIS[0]);5 n: n6 a$ z# x, k
if((DIS[0]=='0')&&(DIS[1]=='0')) DisplayOneChar(6,1,' ');2 ]; S1 Q6 b7 J2 \ }/ r
else DisplayOneChar(6,1,DIS[1]);
6 D' W! b$ W& } if((DIS[0]=='0')&&(DIS[1]=='0')&&(DIS[2]=='0')) DisplayOneChar(7,1,' ');
" `( g2 C; D: K) f i% e( y2 ]4 W else DisplayOneChar(7,1,DIS[2]);
" Y) N8 p6 {. R$ U DisplayOneChar(8,1,DIS[3]);
* Z1 c" M4 C5 C1 G9 U DisplayOneChar(9,1,DIS[4]);
: U( l9 |9 u( d: p DisplayOneChar(10,1,DIS[5]);( ]1 { Q5 N* ^* d3 Z
DisplayOneChar(11,1,DIS[6]);
) T* m4 `; j7 x& a j DisplayOneChar(12,1,'c');
7 P c# ]' c G9 z DisplayOneChar(13,1,'m');
0 V3 P7 x7 v/ n flag=0;
, h2 p( h! g( K! n/ u }6 z% O3 U& Z& Z4 W+ |0 e/ a
else
5 \ M. \4 @3 F: A& o/ d1 \+ ^ {
! n- [3 g8 ?9 A; b DisplayListChar(5,1,"error! ");
- {4 x8 i& m. b3 `2 Y' P% v flag=0;
# v6 }4 g: K7 }+ X) c: n4 o }
1 {9 b4 i% [* _1 h TH0=0;# j4 `! F9 `- D* l, s% k' Y: L
TL0=0;, S: w+ T+ a! l' P4 i- D ^' |* ~
Delay100Ms();* Q3 n% E6 }# j0 \3 i
}1 G7 t! {. j( v
}: e9 B! f2 t! y4 w, M4 v& c' F
3 A* \5 @. T' l p2 R! r. ^0 {, ` |" h' Y1 n+ A
6 I9 Z" d) V8 i+ w. c9 X* a2 b' Uvoid cs_r(void) interrupt 2
/ D% k! H" u* |; H( }7 C{
" [9 ?( c* \1 |- hTR0=0;
I2 S0 I' x3 \8 oEX1=0;
) z9 |; I/ Z8 } v& |. dET0=0;
) [8 v5 S; G$ I4 I# a/ X% F9 U/ T- y8 ^flag=1;9 E* k2 R) o& I, K$ B: h
}
2 Z+ V: _' N% ]0 N( w$ _4 v+ f, D; T" {% p; R
0 _ [) b/ z* F1 _( n0 S
void overtime(void) interrupt 1
3 l% `& i9 n& F3 y+ L9 y2 Q" J J{
. Q. I7 b8 n( x; H. jEX1=0;4 F. B4 s8 {5 A0 C; G
TR0=0;: L8 i2 F) o8 O* B" t$ W
ET0=0;
. ]$ I9 g0 K# B/ }. f' X9 x- u% Iflag=2;! p0 ~: h4 p1 g5 h& h6 R
}
- ^1 w3 | H2 k! ?( y- d: l' D
! y n9 H& f1 W$ A4 p% |7 t6 {
( w' \( e+ O7 I+ W" U# O//写数据
2 Q- I# A) S5 j% H6 v1 zvoid WriteDataLCM(uchar WDLCM) + r& ?- Z( N. s
{
& } H! x* E% K. `: C; c7 C, k ReadStatusLCM(); //检测忙
0 h& c2 y8 J) s, v2 Q8 p LCM_Data=WDLCM;
/ c+ d8 T7 P- Y6 F' l LCM_RS=1;
: F3 X! H( r" T8 @- i* D LCM_RW=0;
, y5 |5 l- N0 p+ u4 b8 A LCM_E=0; //若晶振速度太高可以在这后加小的延时
! C7 X% j* R* K; D% s LCM_E=0; //延时( X& f0 r6 E+ e% U- y! V3 g
LCM_E=1;4 }( c) X0 D$ I9 W' g, M
}
/ `7 Z& }( b! V: o t: t/ ]) c
4 X) I0 P [- v8 U' x//写指令
+ g* D7 x1 Y' Q$ M& y- ?9 }( yvoid WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测, }4 u a& D5 G3 f2 x( m# `& R
{/ S3 m% Q4 | S9 q$ f# N4 M
if (BuysC) ReadStatusLCM(); //根据需要检测忙2 Y' k' L2 @# P) @% o+ ~
LCM_Data = WCLCM;
, T: R1 ~7 n: T LCM_RS = 0;8 Q1 g! t0 Y. L: i6 L
LCM_RW = 0;
* A g; W* D, ] E8 T LCM_E = 0;
) |3 z; B" i6 o! d" l LCM_E = 0;
2 z% u* J# U6 ?1 L LCM_E = 1; ( w. ?4 L4 ~9 \3 [0 n
}
8 I' o2 d. i/ }. `8 r9 i+ h! n( d7 a y: G1 w5 s. w
//读数据
9 ~3 l C- }6 P4 h, J$ quchar ReadDataLCM(void)" ?- E' V) W. _& [2 J
{6 X% N2 M: m, Y: e; B
LCM_RS = 1; / E8 o8 ] M5 p
LCM_RW = 1;5 } O' X! s4 ` Q. B$ A( L
LCM_E = 0;- v. {) M! [+ x$ a, V; E
LCM_E = 0;5 B' w" ~( E, i2 X
LCM_E = 1;
5 Y+ Z C L. X+ U4 j6 S$ g: q: [ return(LCM_Data);
& r9 F1 d7 t; x$ u; k}" @% F {# }' ~# G9 {, d: N
4 n6 q3 N, V5 W" j7 ~- `! U//读状态) }' E8 Q* {6 _! m4 e% X
uchar ReadStatusLCM(void)
1 Q6 k5 R' @$ g o4 Q7 k6 z{+ o' V+ o* U* v1 o
LCM_Data=0xFF; % t7 C' h; p1 E! `
LCM_RS=0;* }# l5 U! c! h" U6 b1 Q: [ [5 O) L
LCM_RW=1;4 r& j# n+ ?. p( A$ r* R2 g
LCM_E=0;( X/ w9 K, i& W1 B# B3 y
LCM_E=0;& T. @( Q# D: A* E+ E5 q0 I- m9 @
LCM_E=1;
I0 Y$ k( u/ Z1 w+ i2 M2 C while(LCM_Data & Busy); //检测忙信号- z2 T$ Z4 q& {4 q
return(LCM_Data);
' X# ^1 f. D! J# A( X5 s3 C1 p}' D- ~8 s8 f6 C" J2 g. e( O! g. d
/ I4 [0 M& [6 u" d
void LCMInit(void) //LCM初始化) ]; T# S# ]3 b2 {
{! S1 g w' o! X1 ~+ x9 ]2 f
LCM_Data=0;
$ Q% P k3 O+ ]# k& p WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号6 V4 `& F$ j7 i$ a- R
Delay5Ms();
* V) Q* f+ L" b& x$ H WriteCommandLCM(0x38,0);7 b& X F- g$ H4 @% ^: u: P }1 I/ I4 j& i
Delay5Ms();
7 ~( D, u4 h3 x6 A# v' q WriteCommandLCM(0x38,0);
7 ], }% W z# [5 C/ ^- Q. o+ X6 E% { Delay5Ms(); , P- \7 k7 R6 k* q+ d% Y
5 b& t2 ^$ a3 j6 P; V WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
3 e- F2 p- v- ]2 H WriteCommandLCM(0x08,1); //关闭显示
- t9 r; N& R8 I5 I WriteCommandLCM(0x01,1); //显示清屏) r1 `& `7 q! _
WriteCommandLCM(0x06,1); // 显示光标移动设置
( f% n/ ~- v+ U& \% f WriteCommandLCM(0x0F,1); // 显示开及光标设置: J H+ J4 d2 j+ c& h
} }: z( J% t5 E
7 o6 L' j7 ?3 _
//按指定位置显示一个字符6 S8 E0 w4 D3 n# v% y; N1 F' v
void DisplayOneChar(uchar X, uchar Y, uchar DData)
`# o2 ]3 p6 P; T" i' K{
" y1 ^7 |' G$ d/ E2 g' o- Z Y &= 0x1;
) V& h& ]9 l5 D% q5 h. q X &= 0xF; //限制X不能大于15,Y不能大于1
% ]4 ^0 R$ p) y+ i9 F: U if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
- R d$ ] B# Z: {2 ` X |= 0x80; //算出指令码
. n' d7 Y& S* H: E n# U2 D WriteCommandLCM(X, 1); //发命令字
) p0 m! C) c' C1 U- F5 N) N% f WriteDataLCM(DData); //发数据4 z' {/ G. W8 i5 X1 P
}# o- s7 x! }+ g$ z+ E1 Z
4 S8 H+ n2 j! \5 `/ O2 h# {//按指定位置显示一串字符: d) W, c' M* I# U+ N$ z
void DisplayListChar(uchar X, uchar Y, uchar *DData)
2 U/ y0 C0 l; b* J{9 [2 m1 a j% B$ w/ |
uchar ListLength;
0 p: i: d% N7 Q# J' d( _3 @2 {% l& V" q6 d. P. Y' @
ListLength = 0;, I, f0 K1 L7 v/ Y
Y &= 0x1;
) |. y7 o4 C: ] f X &= 0xF; //限制X不能大于15,Y不能大于1( p6 G8 O) t! {8 }; j
while (DData[ListLength]>0x20) //若到达字串尾则退出- D5 {5 ~( p" Q. O- q
{
. i2 Y. i6 Z2 ]" N+ w- { if (X <= 0xF) //X坐标应小于0xF8 f; I; @& e/ x6 R4 b% C
{
) }; f' [ ^! l DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
5 n9 o* t- T) n, c1 a5 r/ k( O ListLength++;
) D! W; ?# I( ?5 `$ ~$ K4 v( ~ X++;
2 B, d4 A3 N; ]" |( n, E/ D. Z }9 ~% M8 Q0 _5 R9 b' j9 O7 F
}& p0 `! E9 @, \7 Z% Q
}! {. d8 B4 u4 Y: p; o9 V
/ a8 ~ J3 C' v- z2 Z# f
//5ms延时# ^( J4 S( Y8 b% v
void Delay5Ms(void)6 e1 I1 R7 q. J
{
3 c" Y4 f1 z- r* e) F4 y' E8 | uint TempCyc = 200;" J6 t5 }% R' l; p, C
while(TempCyc--);2 t' P! I3 N7 Y0 C* G% \
}' ~& {7 }& _' z; u5 a. b
+ K9 P4 x. o" k//400ms延时
5 l ?3 I) d( }- L' ^- v- b, @6 hvoid Delay100Ms(void)
! H4 S) n, f) N4 C6 S6 K) A+ A: M8 w{
1 K# b5 y9 E+ m8 E& ` uchar TempCycA = 1;
' |0 ?9 h% V; u; N$ Q uint TempCycB;, m+ |3 I7 P& E9 w& W! @! R
while(TempCycA--)
% m, w2 d9 S# g: S9 n {$ Z; o S' B1 y) ?: G+ x/ _% g
TempCycB=7269;6 i# o% S; w3 J, I
while(TempCycB--);$ M9 r3 @+ d# a
}. _8 O$ x8 K6 z _. s
} |
|