|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序( M# S2 U* S% W! B8 h! b& v
+ T2 D4 c2 p, q9 H% M9 |
1 D# C2 z# i2 h. z
, B+ z5 \/ ~ {6 I; n) ?; J给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。
. u* g! q3 p {. q6 D( [下面是proteus仿真原理图:) A" v: ~2 U& W1 w
4 ]: R/ V; |/ l6 r8 F% E; j* B7 J/ n
, O3 b% L; {3 w3 U6 A. I$ P; x9 K主机程序:5 I3 h: V: i0 n6 I- K8 p- O
#include<reg51.h>! W4 N* M, N, h
unsigned char i=1;
, d5 _% c! A0 l/ I% F; U+ t }" i; r/ ]unsigned char ACK=1;% g! j9 x6 l3 K+ ^; [1 I
void delay() //延时函数2 j5 D9 m" s- x
{
" c) K2 \% I7 E* q unsigned char i,j;4 N7 E% ~4 o; l4 m* y# x! u/ ]
for(i=255;i>0;i--), B+ L5 _ c6 Z. x3 w- K1 C |
for(j=100;j>0;j--){}- h3 t0 o' F' t, y' Z
}% y7 s' ~( C5 a$ w b3 |1 [9 }9 ]
unsigned char kbscan() //键盘扫描函数: g, ? u+ A* U
{; d6 b' j _4 v/ E1 M
unsigned char sccode,recode; //定义行、列- k) w Q0 y/ K# L( e! Q
P1=0xf0; //高四位作为输入先写1
/ H e. ~' M/ Y) y! `) d4 G if((P1&0xf0)!=0xf0) //判断是否按键按下
2 \& I( C; T9 v) f- @9 ]& \/ I {
; |; {% X: J6 w2 e7 @ delay(); //延时消抖
- h' L9 k9 p0 A7 k T if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下
: d, U0 n! E6 {, z {* F0 g8 J# J/ @, W; F
sccode=0xfe;# C( m6 t, a" F
while((sccode&0x10)!=0)
, c9 I5 t% D; a' l( _2 O {1 F0 I. V3 k3 \2 D" O+ T
P1=sccode;! Z# C. m2 N7 c! P0 x
if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下/ j8 ]& J- w6 \& i# M1 s
{
! t% E. h; R a( [8 G# l recode=P1&0xf0; //保留高四位输入值
" P5 c# t7 ]( G o$ v sccode=sccode&0x0f; //保留第低四位的值: R: H7 H6 M4 V+ U0 D0 b& y) S
return(recode+sccode);
7 t: D! h" l2 `" ~. V6 A2 j }" N8 q4 `3 `# r$ D. d; y: f
else$ _/ a3 y0 h. o$ \9 C5 V/ M9 P! N
sccode=(sccode<<1)|0x01;& E6 c, }* D% Y5 _$ j5 H
}
|& [2 Q7 V. c" h$ h+ Y }
/ |5 b! s. R. V }
; m! A) d7 F" [ return 0;
$ y6 G" U3 [$ M2 h: B; Q9 @6 M `}0 @- w& j. Z4 ^' m; T
send()interrupt 4 //串行口通信中断
- Z2 }1 R; T6 P( U7 N! o0 y{) K+ V$ ?9 [. E6 b+ I2 I
if(TI==1&&ACK==1): d3 W$ G+ W7 v* }
{ 3 w2 X- a( G/ \& a* {
TI=0;
4 b# Z. C6 o9 h if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率. c! H: J; Q7 e, X0 `8 t
{
7 A: h" b0 i/ x ACK=0; X( J/ a, m. J+ W8 \
SBUF=i; //发送数据! W$ H& r: d1 H' Y/ a
}
) |$ r0 j' t9 I: J/ `7 f8 U6 ^1 X else if(i==11) //循环发送,发了十一个字符后重新发1 r* M/ @4 Q( m5 J: l+ H, A1 J
{! f; q" l& v6 l1 \
i=1;
6 d' d! [0 ]% d/ P) z/ v SBUF=1;
0 y3 s# N7 v1 Q" L: w/ R }
( m9 v) J% _$ o else
$ {5 N" B1 }3 r* N) T {! B6 @5 R6 C! n% J3 N
i++;
5 X" }* l. L7 y SBUF=i; //发送数据* D1 K+ T6 t( u& n# H. @
}0 E2 L$ l% B8 h$ n) J7 z) i; d
}
) f* n9 T, P( {6 Q else if(RI==1) //接收回应的信号5 z- d0 x$ I3 E2 w# `5 I' R
{
. \. {! W O2 q5 e. f5 h$ {% p RI=0;7 Y0 m8 h/ M4 |" K- v# H* m2 b
ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断8 N, [! m2 a2 S, }
TI=1;
* \ Q0 D" n9 o8 t0 N TH1=TL1=i;
) V: C0 @7 o1 f i=1;; T+ R5 Q3 e7 G4 R6 ?
}
& [7 [/ R. Y2 Q2 ^1 y}8 A# W: D) P1 s9 I! K' P
void main()! g: @9 w2 H1 a0 j5 C! P3 U
{
* }( i4 w0 s/ M TMOD=0x20;
* `8 o6 ?0 n/ P) [ TH1=0x00;TL1=0x00; //置初值
$ ?) R6 s* G3 A TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断' t. E5 ^3 {7 C3 r
SCON=0x50; //使T1工作在工作方式1- Y3 z0 S6 K. n( L% b
SBUF=i;
9 D6 T7 X& _- ?/ o% ]% E while(1)
7 n. V& b/ M* ]% ?) v; `) K {$ K2 ]; D% p# i3 F2 s# m/ @7 [
while(kbscan())
6 l! H; S1 {( u/ e& t! C {
, D) ]+ y& _" Q8 c/ i switch(kbscan()) //不同的按键对应不同的波特率8 ?3 k5 @2 m" n6 P# ^
{
1 F& S( R( w5 u- c( Q0 D case 0xeb:i=0x00;break;
8 [& I5 e, N& M; G case 0xdb:i=0x22;break;
4 S) {9 s, c2 M/ p5 s4 s case 0xbb:i=0x44;break;
% q) q U$ p# S case 0xed:i=0x66;break;" y Z$ J# K3 I6 y3 g9 P9 {! W
case 0xdd:i=0x88;break;3 e. F# x2 N; p$ m! E1 V
case 0xbd:i=0xaa;break;
* R' g+ c+ D4 _" o case 0xee:i=0xcc;break;: w/ s+ L/ P4 w! k' J8 d
case 0xde:i=0xdd;break;
. V: B6 b: v- X1 D5 e3 @ case 0xbe:i=0xee;break;: d: [5 J+ n+ ^' s
}9 [! |, j* S2 S: [1 E
}
6 u3 n1 O+ z* E- I; U }6 M7 y6 p3 t/ B* s% m4 M6 [6 ^
}
0 |' M8 B) J% g: e9 l, T M( q* Y4 E
丛机程序:" G8 t% i; {2 Q/ T. r! J
#include<reg51.h>
0 t5 _: S4 S! l) _4 f" B: O#define LCD_DATA P0
' Y. N2 B' m5 F T; U" p& tsbit LCD_BUSY=LCD_DATA^7;
# \5 L' w" h. F, asbit LCD_RW=P3^3;
$ ~9 g2 E5 B' F0 K6 ~& gsbit LCD_RS=P3^2;
$ g8 h4 H, B7 }sbit LCD_EN=P3^4;
9 t/ I. v% e1 ?3 jsbit P20=P2^0;/ p! {! b9 ^0 k1 o8 B$ P0 f. b
sbit P21=P2^1;
' }* \: E8 B: e5 Wsbit P22=P2^2;
' q- k' {; j( ?- w+ E$ Nsbit P23=P2^3;, U3 E6 p# |/ d
sbit P24=P2^4;
8 y0 ~% `$ s7 X7 C5 y0 F+ fsbit P25=P2^5;; I3 u' f$ G2 ]3 p H
sbit P26=P2^6;* b* ]+ _& M; J$ I. ~
sbit P27=P2^7;
1 ~0 x( c; o# w# I' ]: msbit P30=P3^0;
+ B8 }; S+ ^" w) v& T: q2 _( Tsbit P31=P3^1;. R5 V! m7 p8 ^0 |9 R6 I/ W
sbit P32=P3^2;6 ~( Z+ o+ v+ l9 } i8 a" M8 C1 |
sbit P33=P3^3;: n9 u5 i' T. b9 U6 L
sbit P34=P3^4;- O: b" n! O6 j4 V1 i! x
sbit P35=P3^5;
8 `8 B0 r! u7 v; r8 S" z4 p& K7 Ksbit P36=P3^6;
# q9 G E2 R3 M$ X- ]0 \5 [sbit P37=P3^7;; q2 M6 F+ e5 r" A( i
unsigned char i=0;* C# W% B. v3 h/ I# V1 d
void LCD_check_busy(void) //检测LCD状态
7 P. z2 L( U6 z1 J{
7 e/ g% e5 v# L% |# D, z while(1)/ @5 W1 h, ~, D& @
{$ i$ i5 P; g' I. x
5 ~; `$ w: w* u0 I& K: R LCD_RS=0;: W) J* K- T* R. X2 x* S& F" L
LCD_RW=1;
& k* x* v: h: i( M8 i; [ LCD_EN=0;0 ~. ^5 d( I* A
LCD_DATA=0xff;5 `$ o& b( f5 [3 W
LCD_EN=1;
4 A7 k g' C, t; t1 k if(!LCD_BUSY)break;7 F+ q4 W6 \; ?
LCD_EN=0;8 u+ D$ X' h6 c q: W
}+ G3 T% a' [6 ]- {6 C4 F/ {
}9 T/ U$ J9 j1 ]. `
void LCD_cls(void) //LCD清屏# Y9 S% x; G& p& e. c; L
{
2 c) M3 M: l8 g1 I/ n( n7 U: r8 v; | LCD_check_busy();
& m' m, y% b( [2 Z, d LCD_EN=0;/ x) |9 n' n2 c0 P0 G% l9 N: @
LCD_RS=0;
+ `, r* K, S. l! T1 q" E/ | LCD_RW=0;
- s: v5 Y: Q( B+ s, f' W& ]9 z LCD_DATA=0x01;0 i' s! T0 V# x1 W5 V) m
LCD_EN=1;
/ P2 t/ h3 ^; m! t LCD_EN=0;1 ?2 V! A1 G/ C5 M1 a$ l
}8 J) J. T# x; E% D( \$ l. }
void LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD# A; \- i! o; ^" V; C: x% A6 f
{) Z3 I0 x2 E. C, P& h! D
LCD_check_busy();( A3 a G+ w, a f7 n' V
LCD_EN=0;
! _7 o7 J% h1 C" V* e( }5 L7 r LCD_RS=0;
' J4 R+ f, T! k. f2 B, s5 ~7 ]) Q LCD_RW=0;
v3 B2 q0 t, K5 d1 W LCD_DATA=LCD_instruction;
0 j Y% s4 Z3 l& N9 h LCD_EN=1;
8 `& v: t2 X0 Z8 I LCD_EN=0;
% `/ Z7 p( I K# u, b0 u2 A}
. ~3 Q" B" r7 W. lvoid LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD
, W: v! f* f) w" B{
! G }1 S9 U& [; W LCD_check_busy();) u! P* b4 Q v. p1 ~# k
LCD_EN=0;$ t5 O3 F# B5 Z+ R5 M" U- Q( a. t
LCD_RS=1;
5 Z2 {2 a$ _( _( J& d3 d LCD_RW=0;) ~0 X8 n' S( q7 L; ?; A4 Q
LCD_DATA=LCD_data;2 _: E& y9 X! u9 T, u3 r/ J% D
LCD_EN=1;5 j8 [; A. s: } N/ V/ Z! p
LCD_EN=0; m4 j8 B* N" w' V. B" P
}: ?8 P7 t U! G# D- K% Y9 l# D
void LCD_initial()* a$ ?) {3 ?7 Z% T; ]
{
9 D( p% P& o$ c- ^1 a& r2 ^% z( D' { LCD_write_instruction(0x38); //两行显示/ m. ` ~7 b( G2 X
LCD_write_instruction(0x0C); //显示开$ U5 m% }; n, B8 _9 V# H
LCD_write_instruction(0x06); //光标加1/ ~; Z' [- n7 h- o: W+ E Z: n, _2 D
LCD_write_instruction(0x01); //清屏. B' z. Y" I( O, G" x& x2 {
}6 j! {. h! S' f4 B" _
re() interrupt 4 //串行口通信中断! G, p( ~$ F; E9 ?: g
{
3 U0 V; k$ r+ l if(RI==1)1 c }1 Q! x# j/ G/ g* a
{
2 U' P9 |$ {( z6 A+ s2 l+ b; e RI=0;
7 g6 q. `2 n6 G) ^ i=SBUF; // 接收数据
9 `, E) Z0 ^/ o( j# M: l if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee)
( B, \" }8 V9 x: U. w {3 N8 ]2 k4 {& b: d/ S. }
SBUF=1; //接收发过来 要修改的初值$ u, X: W5 j' t0 L
) n8 V% q& x# _
}/ X9 \6 n8 C/ D
else //接收正常通信的数据, c/ M; H+ L! a9 V- Z. Q
{% ^2 q- y2 F, W
LCD_write_instruction(0x80+i);
( n. O; d$ i5 y3 s) o) O LCD_write_data('0'+i);
4 t, {7 Y0 O+ E* p if(i==11)LCD_initial();
" l( Y' j2 A1 |0 ]9 l9 i }
6 @6 I- t+ C& ~ }9 ~7 Z, @* E7 C# c, J
else if(TI==1)* b1 W6 P. X+ a/ S( |! C3 P' U
{ % U5 P1 H; I, K$ R
TI=0;
3 e, W: w: p% i1 G$ u$ G1 M TH1=i;TL1=i; //发送确认信号后 修改初值
+ |1 D& }/ h9 o }0 g+ z7 a' c3 U8 b9 C3 a3 Y
}, P2 Y/ }( ]4 a
void main()
) N, w; e( w: A. Y j- \* B V{
! o/ `- ^2 a4 A V+ J TMOD=0x20;! l, G- E4 L3 ^8 y7 ~9 A( y
TH1=0x00;TL1=0x00; //置初值8 y( h+ v; H8 d0 y8 E
TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断0 |9 e( X( }8 j
SCON=0x50; //使T1工作在工作方式1
# h8 t; h5 n4 s9 g8 N…………限于本文篇幅 余下代码请从论坛下载附件………… f" X! @1 n: K/ d# s( ^
' s; P& Z# t, [, W r
0 W+ ]+ T1 n) D& ?8 {( g |
|