|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序* P# B+ j# n* y% b( B7 \
! [9 }* S' n$ ]- u* }- E8 a
+ \ ~2 o3 b ~" q3 [; D6 H/ \
# ^5 }0 l' b" _6 }" @
给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。9 h3 X- a6 V- D& I- l. {) [
下面是proteus仿真原理图:
F' n/ ^' Q% u( @2 t% A
' F" J& V( W9 f. F" i7 I$ c4 T( \5 `5 i+ {" Z2 X/ f& p7 z
0 `/ C* h& b% p1 o. Z主机程序:- F( _5 z. V( f$ r9 P, y0 j1 c9 d
#include<reg51.h>
* Z7 i7 N8 ], K# y" Hunsigned char i=1;5 j3 _8 | S' K" O' @7 S( [2 \3 Z
unsigned char ACK=1;' o O' U& \! i
void delay() //延时函数
$ u7 {- b8 v* g v4 ~8 M( H9 G{
5 G( k$ |4 J% m4 D* _ Q: a ] unsigned char i,j;. m' D# I3 f) U3 }6 E& e! Y) F5 j! M
for(i=255;i>0;i--)1 `& y% V' R& D1 q( q. Q
for(j=100;j>0;j--){}
, q6 F' [' L" B8 K# m, s" _5 z& _5 h}5 k) s( y3 s5 S; @1 M
unsigned char kbscan() //键盘扫描函数
6 s; C8 S" Q. H2 S/ j% G: p{
0 C1 m7 y3 M( H; }: T: f unsigned char sccode,recode; //定义行、列) ^+ w4 j" o5 K
P1=0xf0; //高四位作为输入先写1" u" _* T! K4 |$ K0 V7 ^
if((P1&0xf0)!=0xf0) //判断是否按键按下( b6 d7 L" f- h0 |5 M
{ : j* a6 b* t3 C8 P9 D
delay(); //延时消抖
% {1 W/ ~6 v$ I* F& K5 \ if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下
' \# l# V& Y. l [) y {
& U8 ^) k9 f8 w7 V0 D sccode=0xfe;% Q% b& P* P: }4 A5 \0 j0 a. g
while((sccode&0x10)!=0)2 A8 M7 w+ r/ p. @1 O& g
{/ m) X4 z/ R5 |" u% U# m
P1=sccode;* m, S9 _# p+ ]4 g$ {
if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下; O6 D% S. r3 s7 \7 R# H; z5 N3 h/ R
{3 I, g% B7 P' k- N/ D) l
recode=P1&0xf0; //保留高四位输入值
$ u. L6 _/ x% N$ A6 s" G3 B sccode=sccode&0x0f; //保留第低四位的值$ L8 y5 T- S" p" M+ p3 x
return(recode+sccode);# {0 k( i! D& J8 z9 p' R
}# C+ A6 K9 d+ A
else
+ U) Z7 Q6 @7 I7 h% I( F$ A/ h sccode=(sccode<<1)|0x01;. S/ H5 Y$ S" e' k) v' Q
}
" Z5 [; f& m" m0 u; H9 `0 A }
, K1 r& d) S, K }
# u8 q- i$ ^& _ z, x6 T4 U return 0;1 O! \( {% G( b) L1 V/ R
}1 Z+ A& q7 i7 E$ h \) B7 _* k
send()interrupt 4 //串行口通信中断
, T y; F9 Z% g" \; e{
2 S' |9 r0 ^# A+ m( h; ]( S, C if(TI==1&&ACK==1)
) h6 @9 F' P5 Y6 H4 c" ] {
& M% |6 X( [( J) |: q TI=0; B6 q1 d W" a- {& b$ g) c% H
if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率
+ z( K2 X3 [& q. X* c# k {/ b% l! a- y0 h; \; Y& `! L( x
ACK=0;
) E. e) q! t; S! o SBUF=i; //发送数据. U" m1 V: U6 d
}1 _4 [% a Z# ]
else if(i==11) //循环发送,发了十一个字符后重新发
; w9 h1 X* @/ A2 A$ ?% y4 y$ z {
4 x8 k; s( q- k$ e- y i=1;- z9 k x* f0 Y1 b" K
SBUF=1;3 B9 O' w$ a' J# T! P8 m
}
2 z+ x) R% n/ ^/ ` else
- a2 a8 J e. o. _4 b {
1 V7 U5 N3 w; |: w& R M i++;6 C( `% x6 G9 V8 t. |
SBUF=i; //发送数据$ D5 ]8 H/ ~* t6 {: A3 x
}
3 k3 T# X+ D# I5 ] }8 B) T& h% F K9 `8 [: K: q! e1 B% i
else if(RI==1) //接收回应的信号
m4 n5 o* G: s3 ` {2 E9 N7 K8 \2 z# t' T
RI=0;$ i9 |1 {( p. N
ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断$ _- a2 q9 Q) B* o
TI=1;
" z* e' T1 W, g7 F1 l3 @3 ? TH1=TL1=i;) s5 T: ?# L& C5 Y U2 }
i=1;) ^; v1 x$ u6 Q% F, S1 v8 P* H% |
}
" O4 o& l9 i! D/ R2 `, T}
2 i8 o5 }) ] ?) ]: f6 S/ g6 { Fvoid main()+ C: _( `4 m" c- c3 _2 d5 R
{0 f" ?1 F; ? T9 W% m
TMOD=0x20;2 G: A/ [2 ]7 h. O
TH1=0x00;TL1=0x00; //置初值8 L1 g& O# a3 |2 K2 U4 y& S% \
TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断
2 B) g4 M, L9 V2 r+ n$ H SCON=0x50; //使T1工作在工作方式1
) g4 D9 e4 J9 p! i' D SBUF=i; 5 ?8 p0 ~, ~) g
while(1)
( g1 h" W% ~8 T9 B$ D {
5 r/ _! X$ i# b* S. G while(kbscan())
1 `* ]& M u& g' t! D m% A% l; g {7 N- j8 n: r" l6 I+ ?% U
switch(kbscan()) //不同的按键对应不同的波特率& _ [ n* p" L0 z5 d r5 b
{& w9 s4 Y7 w9 \6 l4 I9 M' R; ]
case 0xeb:i=0x00;break;6 |* @ D; u4 O5 i7 L1 ] w' D+ S6 s
case 0xdb:i=0x22;break;0 C Z1 ^4 f3 w# Z) b5 u
case 0xbb:i=0x44;break;: I, n$ y& O& G% ^: {1 Z0 S
case 0xed:i=0x66;break;
% x) E7 _2 b' K case 0xdd:i=0x88;break;
( N* V9 {& n( w& H% F, v case 0xbd:i=0xaa;break;
& o# _- g2 V n! r7 G4 B" n, q+ l" p case 0xee:i=0xcc;break;8 i) t3 e' A* V' Q, k7 T+ _
case 0xde:i=0xdd;break;
$ K# m6 p4 M) ]/ X case 0xbe:i=0xee;break;5 k# d3 h5 w) Q5 W$ Q& `5 o
}$ p5 t' E( m1 m9 s2 ]+ F# W
}; \+ G" F1 {) j; ]/ w+ M
}' S" D+ k7 l3 U
}9 L n% a% U; A9 W; \2 }
$ X4 `6 L, C+ K k& B2 s丛机程序:
' I+ t+ h* y/ h! F; z) s#include<reg51.h>9 @, R4 H ]! }& d! h; w" U2 @
#define LCD_DATA P0; Y) d0 m4 R* `( q3 M
sbit LCD_BUSY=LCD_DATA^7;
) C2 ?! U# p% i$ g6 ysbit LCD_RW=P3^3;
9 |* ] p3 R% B, }sbit LCD_RS=P3^2;) \9 s4 m; c7 g8 D
sbit LCD_EN=P3^4;
; t2 z- ?7 u9 j; q. U8 K& g' nsbit P20=P2^0;2 [! s; K5 [% F: F
sbit P21=P2^1;
: t; p, w) l5 b- c) A6 vsbit P22=P2^2;4 p4 G7 v- ~+ V! `, A9 O4 ]
sbit P23=P2^3;
( [1 n9 h, i9 p# ^sbit P24=P2^4;' k) ] r5 r Q
sbit P25=P2^5;
6 Z! D% Q* m S! T: ?# c5 r! s5 {sbit P26=P2^6;# O( n+ }# J: `2 v0 F" b1 V1 r
sbit P27=P2^7;
" X8 }7 c5 g" m1 q& Z" M+ lsbit P30=P3^0;( X. y2 ^5 a$ }: ^) q! Z1 z
sbit P31=P3^1;; a8 ]8 S f0 e: s3 ~1 X8 e
sbit P32=P3^2;
/ B' L5 b2 I% _: n6 H! _2 Q8 ?sbit P33=P3^3;' R, ?' m! B9 c; w5 w2 o
sbit P34=P3^4;
1 W% C- A$ P: Wsbit P35=P3^5;
7 o. r4 f# s8 e. f+ y+ U( q D* Ssbit P36=P3^6;5 V) P% B2 [/ j; J
sbit P37=P3^7;, |: R9 N8 t& w2 V0 Q
unsigned char i=0;0 ?8 O) I2 X6 j7 W0 ~0 N/ r
void LCD_check_busy(void) //检测LCD状态
p0 b# L2 s: A9 I( U6 V/ u! x{8 G, Y$ _: ~, H, z
while(1)
% `6 o% Z" ], J1 r4 p3 ^9 t3 {& F {/ R3 z$ {+ S0 l7 S2 K, S5 A
' g& J4 {3 `. `; }' F4 N0 s
LCD_RS=0;
8 L& w; i# x: y# n9 t T o LCD_RW=1;
& r; T0 W2 f7 d2 z! D2 p F) f LCD_EN=0;
) O: [' n# u1 E& ~+ v: V8 q7 g LCD_DATA=0xff;+ V6 B0 K* s- _
LCD_EN=1;$ W n- L* Q6 x$ r3 `" z+ w C
if(!LCD_BUSY)break;
: s/ s& q4 _ S LCD_EN=0;
! C, h$ q8 f6 n }+ n8 J" n% M, D0 }' w+ d9 l. F' k
}
9 [! h% h2 j: ~; x |+ a- [void LCD_cls(void) //LCD清屏3 v- ]3 Q4 N' X) c* b
{
* k' E3 Y! \ u F# m3 g! e2 r @ LCD_check_busy();. N" p& r0 a- }$ L6 R0 d) h9 ?
LCD_EN=0;
+ n0 G5 u& y: O& Y LCD_RS=0;
, u6 o, c# M* G* F LCD_RW=0;0 @; W+ r6 C3 l! T
LCD_DATA=0x01;1 t% j1 t6 k/ A/ f- u
LCD_EN=1;5 V& G2 A4 Z/ q9 i) N
LCD_EN=0;/ s# M1 L6 y, ~$ ]
}! ~8 D6 K# r5 {
void LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD3 p( T8 m' l% L2 {
{
$ n1 ]5 ?# I& T' N+ N LCD_check_busy();
; E6 g' T' @4 H) o LCD_EN=0;/ y* K8 O1 ]! d
LCD_RS=0;% k/ f/ C% t1 s5 a. }
LCD_RW=0;
5 L2 m# ^5 O$ ?* H LCD_DATA=LCD_instruction;
0 l D8 ^5 ? Z LCD_EN=1;
$ V# ^7 G. X' {9 Q6 d1 l# X0 Z! L) l LCD_EN=0;
% \# a* ]* o/ o2 L& ?% S7 y}
3 {+ Y$ s) Q( G: H/ k, A( a/ Mvoid LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD; A5 K B% y7 n' a' E+ U. r
{/ Q: w, E a# n
LCD_check_busy();
5 t& ~4 r+ a# L. q/ r \ LCD_EN=0;0 H8 P( o' U) ^
LCD_RS=1;
9 F, G) O! X$ \4 L0 X$ `" ^3 q LCD_RW=0;1 ]! l' @ Z' _3 v. S8 M
LCD_DATA=LCD_data;7 v2 t1 Y: p e( ]; R% y6 ^
LCD_EN=1;
z# V2 z; h' S% Q8 Y( V1 Q LCD_EN=0;' J3 e% N7 v% {
}
6 a$ Q6 P% S3 e; _- Dvoid LCD_initial()
v" T, A+ j$ l. R" n, }{3 ?% q, A& E" U: t' S: T: @! ]
LCD_write_instruction(0x38); //两行显示5 o- s6 L5 L! O4 |) N
LCD_write_instruction(0x0C); //显示开
) Y) K" R! r' o2 Y1 ~1 ^ LCD_write_instruction(0x06); //光标加1
/ t% M( l' L! y LCD_write_instruction(0x01); //清屏
) b8 r# r/ l& I/ E, p8 n# c}
5 d! J. P1 v; Yre() interrupt 4 //串行口通信中断
; D1 w0 \- N2 ]5 k! g6 m{$ O9 W4 H5 d0 y
if(RI==1)
) B: T* {5 ^# e. a) a {3 r6 v; b- t" t
RI=0;+ D4 {# j/ Y0 P* G2 ^6 f8 d1 a
i=SBUF; // 接收数据
7 r$ Y3 T1 ^8 N2 l) H4 [ if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee). ]0 ]" o$ C- I1 g
{
; t2 X D8 r. n+ b& h SBUF=1; //接收发过来 要修改的初值
; }) |: U( d6 c% e- m: M
9 r3 A/ p, h2 Y7 _7 E2 s }0 |1 O9 ?6 }0 y4 ?
else //接收正常通信的数据- D2 G' \. O6 J% W' f
{
2 r% K4 r/ {% } Y6 w( o' z/ { LCD_write_instruction(0x80+i);
2 R- f$ b0 s; P& Q LCD_write_data('0'+i);
. z3 \3 u* X; B) s if(i==11)LCD_initial();1 c6 K( L( @3 Y: S# [8 H8 T( O% B9 S
}
' \7 k/ O/ ?3 ~: S/ _2 a }
0 h q- w5 G7 N$ O$ e else if(TI==1)# m% V: n3 P9 q( I9 Q/ s
{ ( U$ W, v* w2 W2 r
TI=0;; O* p7 Y. ^1 }9 D
TH1=i;TL1=i; //发送确认信号后 修改初值
' o+ j8 V7 y- X }
; A/ u# d; w4 ~}
% f6 K8 G! {9 M3 Hvoid main()
+ m' J# s0 f+ O- S% o{
% b. c/ U3 |" r) l: W/ \ TMOD=0x20;
; f9 M7 c$ {1 f( O6 E9 @ TH1=0x00;TL1=0x00; //置初值0 q2 x8 N' p4 _% [3 {; }; K9 x# d2 E
TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断* X8 ~! e8 g. v% [) Z8 n8 A8 k
SCON=0x50; //使T1工作在工作方式1
$ h3 v9 j5 @# @( Y) Q4 b…………限于本文篇幅 余下代码请从论坛下载附件…………. C0 [3 Z+ ?% O
% }% i% j4 P0 u$ P; F% {
3 q6 s* V5 l) l1 g: A5 H! R |
|