|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序" |7 C" [6 \ k# X; q
7 w3 {- B1 C! b- y
; e' Q4 p* G% b0 o
9 S7 F) p( F* v {6 i5 l4 P
给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。; }: R% I. t" E
下面是proteus仿真原理图:
) i$ }2 T' O: y* {( Z; R4 W + d' V- R/ J& t5 v& \/ \4 I$ ]
' {$ |4 o* [4 \. |& v
8 Q ^' C' J K
主机程序:8 d) g7 w2 a& G/ @( ^$ I
#include<reg51.h>+ j$ m+ E2 |" r- Y# G" B/ o
unsigned char i=1;1 l1 S4 d% w" Z2 ]+ x+ H1 B
unsigned char ACK=1;" i+ g. K7 n7 v/ O% K/ o
void delay() //延时函数
- t, f+ g6 m# }! ^) n/ N0 L3 `{! H2 }3 n) b: d: R. t$ {/ p/ ?
unsigned char i,j;
7 @& Q% ^( y7 p/ z" t for(i=255;i>0;i--)) \5 E$ H* y$ f$ j! P6 C6 y" ]0 }
for(j=100;j>0;j--){}
% x7 H: |$ a( g}7 r5 P+ d1 L) j3 h; P; @' J* B+ Y
unsigned char kbscan() //键盘扫描函数
: P' F, W0 l. `4 Y{
$ Y5 A% R$ L' I% U1 J m unsigned char sccode,recode; //定义行、列( F& w3 x% v4 {& U3 [3 e
P1=0xf0; //高四位作为输入先写1
7 J1 a6 ?. j( r- M if((P1&0xf0)!=0xf0) //判断是否按键按下
# b: X/ D; I: K7 \ {
4 p5 h" \* i4 V& s7 l, Y3 I delay(); //延时消抖) g/ M, V& S4 A' E" g+ W; s
if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下
' ^6 _2 N M" U. I {
; a6 u5 ^. S7 P7 _ sccode=0xfe;, N5 k6 _# A9 o( f: }( x
while((sccode&0x10)!=0)
1 Z# z, ] D- t! v. `9 u2 J% w {0 A& s5 x3 M2 ]
P1=sccode;
3 b, {& e9 m% ` N7 g3 s, G if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下
- `6 M+ F% ?; ]# d {! s8 e: Z% N) w/ R: M& U2 x
recode=P1&0xf0; //保留高四位输入值+ B; g. P; f" W/ E3 y
sccode=sccode&0x0f; //保留第低四位的值
' }8 @+ S0 g+ e% ?3 l/ O return(recode+sccode);
) S. P8 Q, C, D- A$ | }
$ k3 C* }! |. y: L/ ? else
, I$ C1 b$ X! ~ [& K9 q, j6 @ sccode=(sccode<<1)|0x01;% a- H) W# N, z; U
}
% D' l% T2 b' U9 E! d% `# G }) ]. u# |3 f0 S- r- |2 h) Y
}
. f- D& C3 Q/ M$ p) F return 0;0 H; | f. W/ N2 L; M3 v
}
* i2 ]* N6 u1 J; ?" G! D* Nsend()interrupt 4 //串行口通信中断/ A6 y4 _$ E( d- f$ l! _' ~" @
{% ]3 p; o! V( a5 |8 M
if(TI==1&&ACK==1)
- }' E- x) I2 W, T2 C {
7 O$ E! B) l; H6 @! S TI=0;
- |8 c: F! f5 f$ B if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率
, R# r1 O+ o9 y3 O) V7 p! r. { {: L3 i9 \$ Z" v/ f' V" t
ACK=0;: u& l8 V! `* b G! B! g
SBUF=i; //发送数据* D0 h& z% V# M m2 m+ z
}
- h% ]& W) s/ K/ z1 X- B7 \1 G' C else if(i==11) //循环发送,发了十一个字符后重新发; w' K4 Q4 P& h! T6 @
{8 c4 q/ z& j" W
i=1;
6 v; S: F( h1 u Y, l; k0 w SBUF=1;
4 m$ w2 j: Z, O# |. y }
$ [7 o# g4 y H3 Z0 x else' ^ a: O# \5 I5 \2 W- W
{. R8 j1 A9 q0 b' Z8 ~+ H' N$ p
i++;
% T a8 Q5 O6 M9 ^* C- @. d. m& A: E9 _ SBUF=i; //发送数据' v! W/ D# ]$ G. f/ ^ T- \
}1 Y+ h4 F* Q" M; k
}
( Z0 L( y* F5 d% X6 K! h else if(RI==1) //接收回应的信号
' L& H3 V6 f7 B {
9 `! B9 P ~5 n- Z RI=0;
5 F# E. U! @7 j3 V ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断
6 C- r) C! I1 R+ z( F- ~% V TI=1;
0 t5 k4 m6 n+ T3 Z% `+ b. `5 d( y TH1=TL1=i;; `2 S5 [; y* T' x9 V( \2 q
i=1;: [4 T( k6 l' B) P x5 @- @3 E q( I
}
2 v" `9 L+ b- k) O6 ?. V1 D}
: V/ @& Q+ e6 X0 bvoid main()
0 w2 p& e- r' n6 X2 p4 u7 O{
e: F: B* _' M/ ~ TMOD=0x20;- i1 ^$ W8 j# W$ U
TH1=0x00;TL1=0x00; //置初值
/ H* U. M3 T/ ^" Y TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断# Z9 X, p; t8 n- J! h( ~
SCON=0x50; //使T1工作在工作方式1
4 ?$ ], s I9 C4 x" P SBUF=i; : D; ^# D" r) O9 R- I; u
while(1)' ?: V! x! a w; r( n) p7 @
{( |: K; j8 Z- I- l0 s+ S! v" ^
while(kbscan())
8 _9 p3 n5 m; _2 t' N {
8 _, P( O" C4 Y+ q1 h% U2 T switch(kbscan()) //不同的按键对应不同的波特率
, j, L4 ]+ `6 Q$ v$ e. C' g8 G. h {
) `* j" R- X }$ t case 0xeb:i=0x00;break;9 G p& V E, q( o, L
case 0xdb:i=0x22;break;1 b; ?/ ^, X- e5 C
case 0xbb:i=0x44;break;0 [- L% e+ t7 {7 l8 A1 \/ l# F
case 0xed:i=0x66;break;! g% S0 E. L+ _7 u0 e$ b4 @
case 0xdd:i=0x88;break;
# K8 n. t& N. X r9 [& c; T case 0xbd:i=0xaa;break;8 r7 E- Y! r- I8 u3 T
case 0xee:i=0xcc;break;
0 | B, J, w/ ?6 _& S case 0xde:i=0xdd;break;
4 M* [" T1 g; G i* P3 q. h1 f case 0xbe:i=0xee;break;# M; j+ b# r0 d9 u) G6 f
}
* p" s) \9 i. i) F1 e+ x' L }6 g7 C( o7 n# U7 g- |
}
5 L. T# W3 _* W$ ~}; W& f% X n; [' `8 T, r% V5 v! h
9 w" u( ]2 c' o& X5 s r7 V
丛机程序:! u* _- L7 k9 o; v
#include<reg51.h>
3 H# @) @5 f5 y" }7 o( O#define LCD_DATA P0
$ v9 j% E8 U4 R8 j# c* `sbit LCD_BUSY=LCD_DATA^7;
' t+ ^+ \9 l) A7 _8 ~sbit LCD_RW=P3^3;
) ~$ _ [/ ]; H7 t6 E3 F) usbit LCD_RS=P3^2;
% U& I, _5 e3 q% a! Asbit LCD_EN=P3^4;
, c$ g. ?2 F" i! z& m5 b+ {( hsbit P20=P2^0;) e/ m0 }3 Q5 r
sbit P21=P2^1;3 S7 H* H# O2 @' }5 a& f
sbit P22=P2^2;. E1 E' X* K' o
sbit P23=P2^3;+ p$ `" b& a r9 b% x
sbit P24=P2^4;' Z2 u& |* z3 ^; l
sbit P25=P2^5;
f. x4 f" b. o( m; k+ K9 i/ D: rsbit P26=P2^6;
9 ^( n$ ^/ ^# \$ K3 L( i m! Gsbit P27=P2^7; X- p$ ^- b0 X
sbit P30=P3^0;
0 {" g' {8 s+ @1 _" T# O6 G0 dsbit P31=P3^1;$ L' Q2 {! y% s$ l
sbit P32=P3^2;1 d$ k6 @! |. K* ]5 T
sbit P33=P3^3;
5 r$ g, K1 @" ]/ H: s) \sbit P34=P3^4;+ W4 T' e. c0 s$ O* S
sbit P35=P3^5;3 \! ?7 A9 n+ B% i m
sbit P36=P3^6;
, Z7 n- m/ U4 ~" y V% c$ ssbit P37=P3^7;
- g8 t1 W2 F: F5 [$ c4 c6 |5 U* Munsigned char i=0;" D- L8 D/ [& i( l( N
void LCD_check_busy(void) //检测LCD状态 F7 a5 f- C% V5 N4 c: m
{
+ s, O6 Y f F8 O while(1)
! E) a5 `! V& L4 Q# p' }- y {. p) i9 y, X6 c* E4 M& d
& [6 Y, s% S& q0 j8 P
LCD_RS=0;
* v8 q* [3 A% \' C7 g# Q LCD_RW=1; }) H3 h' s. ]
LCD_EN=0;' t8 B. k" ]6 n; V- r; Y0 p3 X8 g
LCD_DATA=0xff;
! t: J# g3 }4 ?# g LCD_EN=1; q/ D/ t5 g" Z) a
if(!LCD_BUSY)break;; s: ^" S5 N- ?3 j+ i
LCD_EN=0;
6 E7 y$ x7 E; ^: w& Y }
/ e6 B7 P& E; e8 }2 s: l9 {}* |! A& t1 ?8 V" r' Q: B
void LCD_cls(void) //LCD清屏
$ G8 Z2 X: G& X/ E! Y{+ ^# g8 }, R9 f) J- A, k
LCD_check_busy();. B7 }) [( K p6 w$ r5 d
LCD_EN=0;
8 O. p( R3 _) O+ E: } `( e% } LCD_RS=0;& o% O7 I2 G) Z! l. Q, g
LCD_RW=0;
( B! C( y1 z/ O2 K3 [( A) G LCD_DATA=0x01;2 ?$ @% v8 M$ @" ]6 N0 b
LCD_EN=1;
4 V* ~9 e Q8 b, J LCD_EN=0;( s& f0 U9 w( R9 p: b; p) u
}
, _* P2 s3 Y: C9 V' K( lvoid LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD% f F9 i, m+ g5 b3 Q7 D2 i, r
{
9 S: }2 R* x% j j- F LCD_check_busy();& v1 e9 m% M& u1 j' P4 p8 o
LCD_EN=0;
- t/ Z# }6 i- b- p: W LCD_RS=0;
; q% Q% `/ {9 T) @5 H LCD_RW=0;
3 h$ o4 y+ O6 l LCD_DATA=LCD_instruction;/ y$ M" N: X! q* I a) A- C! d9 m
LCD_EN=1;
9 n, D( h: r. K" S6 ] LCD_EN=0;, A3 L. A* ^9 G6 p% a: P
}3 C6 p" c3 e/ ?) V. Y& W
void LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD) d8 G# A0 b G t3 Q- h5 H) Y5 u& ^3 {" d
{
( I0 c3 M- K7 q1 Z LCD_check_busy();( {( ~! `: j$ l( G" v; ~# t
LCD_EN=0;
" K( m2 c+ X) ?& | LCD_RS=1;) r8 Z }2 y+ s9 ^
LCD_RW=0;
# |: h, K0 A- k! `$ C* n LCD_DATA=LCD_data;
' F7 E G7 h% F4 v5 g4 z: I+ q2 o LCD_EN=1;
- n2 k+ i7 G* h L! j% f& w LCD_EN=0;9 `; e, p3 i. i9 U! r* V, H
}# y& g3 W( O8 f" O4 u
void LCD_initial()9 }/ B( ^! \1 m6 f% {+ s% C+ s v
{
/ V. t' n! L% m. I7 q& ^ LCD_write_instruction(0x38); //两行显示
- m3 C8 E, ~, P- | LCD_write_instruction(0x0C); //显示开) m& T, J4 ?, D" }
LCD_write_instruction(0x06); //光标加16 b( G% O' T% C3 B2 g3 @& e
LCD_write_instruction(0x01); //清屏
0 E1 G& d7 v$ ?. o: a/ Q8 U}
6 b" y P" f+ V7 @4 N6 jre() interrupt 4 //串行口通信中断0 e- g& S" ~, x, `2 T3 B0 V
{3 J$ U8 h9 V W) J Q% F: X6 O
if(RI==1)
/ B& m& g" r. r# j* @$ M {& q* o2 y, v6 B% c: W0 f% o
RI=0;
& N& C& Q; _ v( N# g# x- p i=SBUF; // 接收数据% Z# v- E* x4 t7 {9 M* Q
if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee)+ `: L/ S! d6 f6 D% n- h" k. ]+ F
{
5 e5 `# |6 _0 m1 E) ? SBUF=1; //接收发过来 要修改的初值. j0 B2 w+ o- |. C9 b5 {1 \
; C7 X" X* q; |2 V2 ?
}
& t4 ?0 W H0 K* e else //接收正常通信的数据
9 N; H0 [' h0 x9 l4 k4 t& L2 @ { j) O+ m' G% V+ M; k
LCD_write_instruction(0x80+i);
1 X) [- m- p2 m LCD_write_data('0'+i);
$ @" k8 |& K2 |; e+ M if(i==11)LCD_initial();( M0 [2 H. f! }! ^; ]
}: u2 v8 T9 K3 Z4 w8 Q/ \9 W: w
}
; X) U% [+ a# R else if(TI==1)' n' a3 \1 T1 _, r% V
{ / a! a1 x' G1 I$ \& W" q
TI=0;
' K5 \/ T0 q& U: O TH1=i;TL1=i; //发送确认信号后 修改初值
2 o" i4 h9 ?* d: b8 z7 Z& g' Q } B& B8 a% W0 l0 }7 X
}) d* j7 i$ B9 T2 u
void main()
- q) L% x" Q' C( I& S{
) G8 r& t e# _8 _5 M TMOD=0x20;5 x3 T) L1 B$ Y. k7 I
TH1=0x00;TL1=0x00; //置初值
1 W: D% w% d3 R0 ?( g3 O TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断! x# t1 q! p9 W8 W
SCON=0x50; //使T1工作在工作方式1* Z4 R# ~0 _2 |8 {0 p1 \
…………限于本文篇幅 余下代码请从论坛下载附件…………0 b1 v9 W& z' i8 s
% a4 K+ @ N0 p6 m& i' D( B8 Z g* C' r2 k
|
|