|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序- \- @. s; D4 D& D
5 g. A2 j5 f. F% S. L
0 W! J/ Q( k1 _: d/ o# w. E
3 g6 l/ C1 F% d4 k4 H& u
给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。
3 j) H/ _( ~ f. d0 x& T下面是proteus仿真原理图:
* G2 m2 G2 i u- k4 V0 h 6 }8 ~5 Z/ N2 x2 M8 n$ w
I, a- Z; l$ O' ~) W
3 ?7 n& _5 R! C) N; `主机程序:
6 C& ^4 d8 |& o" R0 X* \#include<reg51.h>
. P8 \( @; c" Xunsigned char i=1;
' A! K8 A3 B/ `! x( K: w+ funsigned char ACK=1;
/ i) e- ^9 ]; g Xvoid delay() //延时函数
2 \4 W1 J; i! `8 g# C. ~' f# n$ p9 h{7 X y! @6 V- I* K
unsigned char i,j;
" y( v. N5 B* m4 l9 N' z for(i=255;i>0;i--)
+ R0 M% M1 R. Q0 D7 k for(j=100;j>0;j--){}
) B' n. y" z0 d+ F; u% P}7 b/ \9 c- _- S; I$ @2 G( _
unsigned char kbscan() //键盘扫描函数+ X" U- Z- b2 [7 r) T) O
{: r+ C7 H- C, F% h
unsigned char sccode,recode; //定义行、列
- e/ g! o1 r3 t# `% U8 m) E# o0 ?! c P1=0xf0; //高四位作为输入先写1
! w% \5 T+ n/ \" S if((P1&0xf0)!=0xf0) //判断是否按键按下/ [# \( Z) N5 z! G9 w/ I
{
3 B9 C2 _1 l$ I1 b3 |3 [0 M delay(); //延时消抖
) K; L; ] Z" ?5 O! b* a0 d if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下8 ~; {' R- `+ L; U( V
{
% N) ?" j/ e- X! U0 ^ sccode=0xfe;! ]! h* Z4 s3 H, R, ~$ D: }
while((sccode&0x10)!=0)8 Z7 O4 V( T$ b/ O% ]
{
+ N" V" Q8 |. s0 P5 m5 @4 Y2 t P1=sccode;$ s3 P2 g ^9 s/ M7 f
if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下" H+ ^* a0 Y4 ~% _, s& }
{
$ r% ?: z9 \ y/ ?, L9 ` recode=P1&0xf0; //保留高四位输入值
+ S% ]3 Q, M, F* B sccode=sccode&0x0f; //保留第低四位的值5 T' e, I& v4 e
return(recode+sccode);8 S& O+ @6 W+ }
}3 h$ Y# T4 g5 u- N( Q% G
else4 \% x5 N( m: f4 q% n
sccode=(sccode<<1)|0x01;( \, e. @9 a1 j; R2 n$ k% ]
}
; M3 t0 w) v3 P7 }' D$ R }
8 g0 l/ A! R+ ^$ s }
" s$ M7 O5 p, j$ T return 0;" T+ d# D2 U" U c T
}
' J* F4 M7 n% K6 xsend()interrupt 4 //串行口通信中断, R# j- T. X8 U' x8 | v' O
{; J% i; `) _- d( U
if(TI==1&&ACK==1)
7 ?! u5 K @0 ~4 c+ x { . U( r. \- G- \7 f# h/ ?( S
TI=0;3 H" b0 ]. |( d
if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率
* `* a, _3 |9 s y0 l3 X1 K {
6 V" O& J! ]9 w; W, u/ h6 {' ]) | ACK=0;0 S) C" ]3 @4 @. Y) u" G
SBUF=i; //发送数据/ H+ t0 B* ^2 D
}
1 f1 ^! E3 k7 O4 Z: T4 d5 s else if(i==11) //循环发送,发了十一个字符后重新发
u$ H$ x7 j2 ~+ V& h {5 y5 j& c( X5 F+ I }+ |: a( E: z
i=1;
2 a7 O5 s( q' M SBUF=1;6 j8 s5 Y8 [* O6 V4 O, T- i
}; _( h- W1 m! ^
else
# c" U% w0 r3 x6 [ {& t2 B6 N& b7 y( K3 n
i++;- z/ M/ j* Z8 f( q# u
SBUF=i; //发送数据
& i" ]# ~8 W3 |/ @. F3 x) p* L2 w }
. I+ ]9 j& ~; i/ ? }
! P. \0 Q7 ?) P7 U9 | else if(RI==1) //接收回应的信号+ Q- a' n& V8 X; T' a" x+ C: `
{, r3 C* I, E9 x" M0 y# z
RI=0;
8 k3 A# \1 [4 v U9 |! G, l+ V& \ ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断
8 `# z: O l5 I# C9 i8 r TI=1;2 `& H8 ?. n& j' \+ A1 X6 I- W
TH1=TL1=i;
. V. U+ ^! m5 p& \, v# X i=1;
$ u+ B: Q5 b9 k$ w }
1 [. L4 n% ]! v" `! Y7 _5 [ P}
9 E3 z, Z! w! Z- P. ~1 Ivoid main()
, l& b5 N7 `9 P{
- o9 ? N; F3 E6 P4 s: l# O8 ~ F TMOD=0x20;
! h' i7 Z [" V- t. i) b! U, c: Q TH1=0x00;TL1=0x00; //置初值
7 m; w5 J7 j- [ A+ { TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断! Q3 P q1 n* X
SCON=0x50; //使T1工作在工作方式1, \/ p+ X Y- o& ]; U6 k1 b; L
SBUF=i; x" R: `" W$ K2 E: w+ {/ ^- C0 T
while(1)- Q2 P* q2 x0 |( U* v
{
" u2 x2 {# d/ [: Y" P/ j while(kbscan())8 M# [0 t1 i% H2 V0 i
{
; W8 t, E/ }0 n) ~ switch(kbscan()) //不同的按键对应不同的波特率4 |7 s# }& v/ W6 L) U2 Q6 \
{2 O6 b/ f( \" `
case 0xeb:i=0x00;break;
. d; R( C( V! H# n% S4 q case 0xdb:i=0x22;break;
, G0 E/ i! b5 _, V5 R. h& ^ case 0xbb:i=0x44;break;
% J( P( {3 U( G5 ~6 `" R case 0xed:i=0x66;break;
% q( d2 ^" J. W4 A case 0xdd:i=0x88;break;
' D5 Z% r) ]* o5 [7 E case 0xbd:i=0xaa;break;
2 D2 U1 v9 w% [+ \$ t7 ~+ }6 S5 T case 0xee:i=0xcc;break;
% H' H M2 t7 e case 0xde:i=0xdd;break;& z4 D3 h+ {/ V/ ?
case 0xbe:i=0xee;break;5 Z% K6 V. I) [; L" g, g
}
9 v% l A, p. U) i+ I8 K }
$ U! r5 ^: G. V }
" C) Z0 y0 E8 I7 C' i( W}3 o c( {0 A6 V+ G9 \6 x
! W) ]' O3 @$ Z5 t3 j丛机程序:
. W5 e X1 y+ ?8 ~1 e, p* M4 L#include<reg51.h>2 \- m' Y% l* B
#define LCD_DATA P0: X7 S2 A% n6 L0 G. t% Y- i
sbit LCD_BUSY=LCD_DATA^7;
. Q$ m& [) S: v0 a2 K$ J7 ysbit LCD_RW=P3^3;
0 n5 i' S6 ~& q* i, K2 `sbit LCD_RS=P3^2;4 g4 A+ \. ]1 c- V
sbit LCD_EN=P3^4;
' v, ^5 m( } O1 \sbit P20=P2^0;" e1 K% J, f4 O4 [7 D" n6 L
sbit P21=P2^1;5 f2 s! W8 J* n( \! c0 P
sbit P22=P2^2;
) y5 X; m- M( r& K5 N1 xsbit P23=P2^3;* h1 m* P4 ]% F" p" j% s
sbit P24=P2^4;
& d* ^1 y) ?- H/ Csbit P25=P2^5;
. r# Z' S6 r6 Y% c1 C& W5 xsbit P26=P2^6;; Z8 g7 l7 i4 b( \
sbit P27=P2^7;% y+ e6 a1 Q' q) }4 u2 `
sbit P30=P3^0;, W0 A+ k0 u _0 W) R/ m
sbit P31=P3^1;3 u' o* Y, {8 e
sbit P32=P3^2;& z6 ]3 k3 l Q
sbit P33=P3^3;
( Y. i/ V2 n% K: h, L( K8 Wsbit P34=P3^4;
, H1 e- {, ^; ~/ K6 }8 |sbit P35=P3^5;
4 z7 e/ H3 @ M1 R- g6 [2 Dsbit P36=P3^6;
" |7 H$ e4 z2 _6 ysbit P37=P3^7;( G% }; v0 X! U; ^# e% V
unsigned char i=0;
5 `. w3 _- n' o& d- @' w- C7 ]% yvoid LCD_check_busy(void) //检测LCD状态! R. t* A# C g3 s0 o
{. O4 m2 _* ]1 n3 y9 P3 v; g
while(1)6 C2 y+ }7 {$ Q1 \
{
K2 \# |) x' n0 V: L 3 ~2 o+ c. R# v( d$ o
LCD_RS=0;
* g; W5 P" W, Z/ I LCD_RW=1;
5 _% Z1 J! x2 \) ], H, L# O9 Y LCD_EN=0; ]) S, @0 D) p& N; {
LCD_DATA=0xff;
0 O6 _' ]5 r9 U! j- y LCD_EN=1;
* u* N5 k; ]6 ` P/ F if(!LCD_BUSY)break;
1 o& W+ [: f# S, T1 N LCD_EN=0;" r2 }0 b' }' E9 w
}# r6 I5 Y7 N: `1 k9 n
}
z6 ^! M) `, ~7 J9 J Nvoid LCD_cls(void) //LCD清屏
! b! W D4 I7 R9 f) W( s{
; Q Y: D0 D Q2 I+ F0 t) _ LCD_check_busy();
) o+ K! e' A) a LCD_EN=0;
# J, R5 i% t* t- \3 R LCD_RS=0;2 f& U3 u7 |; t) W6 T+ a* P! k7 ]
LCD_RW=0;' t: `( o/ V/ r: U
LCD_DATA=0x01;
! c) f! V9 @& i. `$ v8 N LCD_EN=1;
( \# N+ v. y) g$ k6 P! f LCD_EN=0;
6 P5 B+ n" k7 v7 m; B% G$ ]}
8 N: c: o0 ?( `7 zvoid LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD* B* o6 Z: t- |2 M! h
{) M+ b% G: v7 w" u
LCD_check_busy();
+ |6 N5 x V1 }# ~ LCD_EN=0;
5 [! n! m7 a9 n9 T LCD_RS=0;
3 p6 ]0 S5 [7 {9 F LCD_RW=0;2 I+ O- u2 y# @3 h
LCD_DATA=LCD_instruction;' z' `% k: n. i+ j$ N% q
LCD_EN=1;
/ y( F' d0 N4 e% Y LCD_EN=0;
; {6 Z. g Z0 t. `; ?4 E}
5 ]; M- L2 s& N; ]; m+ [void LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD
A5 @( r* C0 B. U2 M: i! q{# _0 j c! F+ N) W& f' L( J; Q5 ?
LCD_check_busy();' W" `0 J+ t ~) q: u
LCD_EN=0;
7 f, u7 r2 Z: v% @1 c LCD_RS=1;4 N, K: ]* S% F: r) Q
LCD_RW=0;. [; v* d$ Z* {
LCD_DATA=LCD_data;
& T. {. |. v# } LCD_EN=1;( M- z. l% @" b$ m# X$ c7 B
LCD_EN=0;
7 m/ e% ~% X5 i}
7 h, R* a9 H8 N bvoid LCD_initial()2 S( U! f2 V; |6 o+ F- T' u
{
4 F! j; y2 w3 D. q: i) k; o LCD_write_instruction(0x38); //两行显示
& x5 P$ j1 }4 y LCD_write_instruction(0x0C); //显示开
5 S X7 g8 ^2 N4 c' X6 L& r% L1 F, o n LCD_write_instruction(0x06); //光标加1
: r! C% G# U! Y- O& r$ ^2 V LCD_write_instruction(0x01); //清屏0 a0 K2 p1 y3 v; R1 [! U
}
- W3 l, L: L6 ?) V6 Wre() interrupt 4 //串行口通信中断
3 j- \1 h) q# s7 V3 V{ F! A# j7 q* Y& x9 g; B; U
if(RI==1)
( I% g k. @3 ^5 i/ M! H0 L {
) W8 T' ?* g6 x& f+ Y! @- j- h RI=0;
3 w! `# _3 Q6 i i=SBUF; // 接收数据! M0 G+ U1 e+ H
if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee)! `) c2 J7 C' ]0 ~
{/ f' K9 W) ?) e/ D0 t2 g
SBUF=1; //接收发过来 要修改的初值
" |/ C3 k1 w/ t5 s
1 l8 w# |( F8 Y$ L; J/ \ }9 m2 N5 W% k& w& ]
else //接收正常通信的数据- X5 a6 r9 M$ m' Q& W
{0 V" p; G% T# Q: `7 f5 s, d/ C
LCD_write_instruction(0x80+i);% _8 P+ e& t7 ^
LCD_write_data('0'+i); ' s' p' W' z4 b' y, ?6 |
if(i==11)LCD_initial();
. Y& Q( Q/ O' h& T H4 _. ^. @1 } }
- U) M' {3 u$ k" W3 O* Q. p" a }
- a; R( e. h' C; P/ {' B else if(TI==1). X2 L* ~' R+ `
{
" |5 I/ z |. f& R TI=0;
, c" A. f( s4 n9 W/ ?& | TH1=i;TL1=i; //发送确认信号后 修改初值: P+ G9 J" |; R% I" G+ u
}; y* `; Q3 k( {8 R5 y( ^
}
. a, T! [7 U# r& `+ S" k; Y _void main()
% j7 j6 s% E6 K1 @" O5 A6 P( z{
0 i* ~% E5 w! } TMOD=0x20;4 p! M# H8 H5 D9 H4 G
TH1=0x00;TL1=0x00; //置初值
4 s9 Z+ m# {/ W- N/ Y5 a TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断1 ~8 c1 i) @8 e& D' f* ^/ y0 O
SCON=0x50; //使T1工作在工作方式1
b# J- H, H* b" B8 R3 ~…………限于本文篇幅 余下代码请从论坛下载附件…………! G9 p4 s2 W8 J% e# }+ ]
4 T; M% R* G# p: T
3 G# X5 G8 t+ @ |
|