|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序" Z: E- a7 ]' G5 ]
/ g3 _3 u+ U( |, z. V' E
0 m5 q% ^3 s9 _3 \
% h z' i4 {3 V- C8 X给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。
1 b' ]; j. e& ^7 F, ?; S下面是proteus仿真原理图:
# ^4 f! c! x0 P; Z: g ! ]3 k) f- Z7 @( g
, ` \. a0 g0 G2 K1 b9 Y+ W8 ~
; V/ r* g& J s! e) e2 F( h9 V主机程序:% y# D5 p) h5 F( D, n
#include<reg51.h>
$ L/ G0 }$ {# j" o9 e0 m ~unsigned char i=1;" Y( M: f! o0 K# l6 b+ }2 f
unsigned char ACK=1;* b2 N+ a r1 X# R- q9 y
void delay() //延时函数
* w" o/ U4 \3 `" J3 C{
3 T9 x. f8 h+ J! F6 g% G unsigned char i,j;. v' ?% m7 U, I" I% T6 ~3 z+ s! ^
for(i=255;i>0;i--)0 A0 H) N! I; W# E5 n: ]
for(j=100;j>0;j--){}
- c2 b8 P' K7 W8 n3 ]. d/ m}9 a1 L2 q2 D! V# M
unsigned char kbscan() //键盘扫描函数0 |* D4 b; b& X8 M3 O( K
{3 Y2 d# t# e2 ~) @
unsigned char sccode,recode; //定义行、列 B& S0 h0 \. n+ D6 h! a( \
P1=0xf0; //高四位作为输入先写1. O7 P1 }0 G, U/ b
if((P1&0xf0)!=0xf0) //判断是否按键按下8 B8 _" [5 q9 v2 S1 f: a
{
7 T$ K" e* I. [- `0 ` delay(); //延时消抖
, N; d# m E' w if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下% R. ]9 n: ]5 x' I1 Z) k
{; |9 \; m5 ?. w+ O
sccode=0xfe;2 j; ~# q; H1 N1 ]
while((sccode&0x10)!=0)1 Y& p# ^: ~# e: _- Y$ F
{
; N7 P0 n* O* o* l P1=sccode;
4 b* C- c: q8 p0 g* _# K if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下4 y8 w# [+ {" P* r7 f2 Q$ S) @( Y
{
7 l0 |) w2 w: Y6 p" c/ P7 V+ u8 L recode=P1&0xf0; //保留高四位输入值5 I! L& ]: p' [/ X/ f3 v% s/ G# m4 U
sccode=sccode&0x0f; //保留第低四位的值& L K. k# E6 J/ `/ p
return(recode+sccode);
6 `- F. D( }% | s) U }" Y0 d! i0 V: Y
else
% [- {$ d8 T2 s7 K/ S sccode=(sccode<<1)|0x01;1 ?! }* M$ o) n8 z! h- X
}/ h8 P; F3 a2 j1 S! X
}& O7 L5 W' f- x+ d/ j, X
}
/ C7 u0 Q4 N* Q9 |, _ return 0;- _, s6 \. H- Y* D4 x8 ]. L* }
}
1 \. [$ b( y( x( ^7 y% Lsend()interrupt 4 //串行口通信中断
2 e7 r9 r' \0 M) O9 {5 w3 a4 ^. N{7 N& D1 W7 T# y* _* h
if(TI==1&&ACK==1)
! i: n3 [, T, p% k5 O {
5 r" H+ i( a* J TI=0;
3 R+ U4 |" i) y5 z if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率
: f# z% n X9 e- _ {& U6 F ?& ]! s9 P
ACK=0;; g% q2 a# n+ S: d
SBUF=i; //发送数据
( @3 |2 A) o+ {4 m6 X }
- a3 i9 D3 Y- }/ r+ A+ [8 w+ w else if(i==11) //循环发送,发了十一个字符后重新发
0 ?- G E3 K7 ^- S/ k! L( u {" e* _( L0 D) J
i=1;: P3 n# ^3 V" t& U, w/ @
SBUF=1;: ], b" b8 p6 p, w
}
0 f6 c$ ~0 W& ?: E& r# U: K else6 X& x' j; d) {' A7 M
{
& e6 V+ V0 D1 r1 h: G i++;
; m9 Z# }! r9 k: U SBUF=i; //发送数据
9 `1 Q7 z6 i- Y; O4 U. ~2 y }
, j& K9 o4 M( x$ g# j }
1 T# i+ o8 z/ U! G else if(RI==1) //接收回应的信号4 \- H, ?/ a: C: ?3 R
{
5 K' J8 W' ]3 \9 n' g1 O RI=0;
- l9 ^$ a4 e5 |3 b2 Y8 T7 z |' R ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断
( K4 g* g- B: A& j TI=1;
6 G0 }7 ~3 i6 t TH1=TL1=i;
/ C- M' b6 {3 c6 I# A, c8 `, a i=1;1 J- {& f8 ~# J
}+ E: f! ?0 Q+ g- [
}: S b2 f- z: x/ A
void main()
, \" n& d( g/ G% P I{( u$ y, r4 D9 r$ F
TMOD=0x20;
- f, f/ i, i) x5 d/ a# r( _ TH1=0x00;TL1=0x00; //置初值
& u; Z/ X x7 Y TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断2 \8 {+ Y. ?' H3 }; L; i9 r4 u
SCON=0x50; //使T1工作在工作方式1% y! _7 O: J+ s5 h. n0 F& w
SBUF=i; 2 X& y5 s# U- C& H L- Q
while(1)) s3 z$ I F7 u" Q9 s4 P
{
7 w# f, @' {- H% N while(kbscan())
) U; p+ O$ o5 X {. K! S8 o* m) q
switch(kbscan()) //不同的按键对应不同的波特率
5 S$ G( ^) Q4 c+ L4 }$ A2 P {9 y" }5 f8 Y% ~" ~) U
case 0xeb:i=0x00;break;
' [" B4 Y2 m! a( U' O1 B case 0xdb:i=0x22;break;
. B, K; a. p$ g8 G0 h& v; M case 0xbb:i=0x44;break;
8 `" `3 `; S/ g0 S+ F case 0xed:i=0x66;break;0 G9 J; p/ ]) E
case 0xdd:i=0x88;break;( |+ I* Z0 b# \0 n4 y2 n2 T
case 0xbd:i=0xaa;break;2 X* b& K2 B, C2 g! I* Q* G2 n5 N
case 0xee:i=0xcc;break;
$ O, j4 n' I( X0 x) Q9 Z9 B; ~ case 0xde:i=0xdd;break;
/ e$ s9 l; p2 H4 Z& H9 ^$ I) k$ B, p8 _ case 0xbe:i=0xee;break;
# c! j- O* l; Y' g7 v7 h! W8 y }
0 P0 i4 y# Y& `" w }5 s7 y* d7 [+ {
}
7 g$ C5 ~$ E% G' O) ?" t0 L8 w* Y}
" ^. h6 t \$ T! c# |
7 J! [4 A0 i3 k0 O% T3 V丛机程序:; Y2 T1 x8 E2 m' s$ ?
#include<reg51.h>
' M& Z, i! R; k2 `, R5 V#define LCD_DATA P0
0 D8 z9 E. O; Isbit LCD_BUSY=LCD_DATA^7;) z: c' N. x0 M% L
sbit LCD_RW=P3^3;) ?- r5 H6 }# x8 C U3 Y2 B E
sbit LCD_RS=P3^2;8 f% \0 W6 \4 x. B& D& K0 X0 Q
sbit LCD_EN=P3^4;$ C- \: l @ q2 N' \
sbit P20=P2^0;
) S4 N a9 C `- d5 s# w7 z1 @) d' Xsbit P21=P2^1;
: a8 B* N& k x% Z; w6 j nsbit P22=P2^2;
% U5 W# r; e% ?sbit P23=P2^3;
" `+ N+ ^( n/ Q3 I& E, tsbit P24=P2^4;
: w6 v+ |6 j0 P' osbit P25=P2^5;, F H& D6 e# J; F+ x `4 q
sbit P26=P2^6;
+ f8 a8 u* R; l3 Y qsbit P27=P2^7;4 H e/ u# k& D( [" y$ a
sbit P30=P3^0;
, v9 l1 ~. n$ |sbit P31=P3^1;8 {) `6 z* K; u8 ]2 B8 C1 p! a
sbit P32=P3^2;
$ F' M5 `7 Z8 J1 `# @& usbit P33=P3^3;% F% d( A$ p8 S, o; f. O0 t! E; ^
sbit P34=P3^4; n" L: x! Q! d! ]+ J5 `
sbit P35=P3^5;
& X+ F, P1 c. W) E! t1 d4 K: Bsbit P36=P3^6;* Z9 K& j! A5 ~* Q. H' q
sbit P37=P3^7;
1 ]5 A% F' L9 |% A7 [* G0 ?4 punsigned char i=0;
& _' k; B- {! b }void LCD_check_busy(void) //检测LCD状态! k0 Q# b! q; r% G! {
{
! {: G0 t% ^, t1 t c while(1)
! L. L" M7 M6 Q3 D. R. p8 k6 d) Y7 U {
) H3 m+ {0 e& r6 I- A( m
) x* y* {, |" h- U8 @9 g LCD_RS=0;
" W& P0 ]) g! ~- U: s3 C- j2 c: I5 }9 h LCD_RW=1;* |4 Y( b( j+ i ~9 {, y7 T R* Q, @
LCD_EN=0;3 \3 F5 n- H9 l5 c5 k* g" [
LCD_DATA=0xff;
+ ?8 N/ z, n: [7 M LCD_EN=1;
. T: B! v5 U- J; E if(!LCD_BUSY)break;
1 s# p1 s( S9 p1 U$ f6 P( _5 f5 c7 Q LCD_EN=0;) y9 Q/ q7 a( N( D. I- d) \8 ^( b6 A
}
! A2 u0 T# A9 z9 E' l! S! W2 [; e}( p4 F# L0 `$ J! X% T6 M
void LCD_cls(void) //LCD清屏
( o) S9 y9 N$ ?) f0 E% k0 i: O{% ?6 R7 y$ ^! N% z5 S$ p6 j" Q
LCD_check_busy();/ `' q4 E; {2 x3 g* P2 L* m; r
LCD_EN=0;
) z4 T! M, {5 c: V, v% q1 _$ z LCD_RS=0;
. V( b; q$ s& f' t. S LCD_RW=0;
+ P- Z6 S4 ~6 S6 r( D9 b7 `0 n8 @ LCD_DATA=0x01;
0 g' r) E2 n( V3 q# \* Q LCD_EN=1;
1 @0 e( ~. j) A* ^" m1 I5 P/ {& r LCD_EN=0;/ L% K; y& h) v+ p
}# J5 {; D; O+ _! M" B$ @6 U A
void LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD
# O4 r$ ?8 m/ c2 r{
9 U5 L8 \2 E, n" e; h8 x+ u G# G3 E LCD_check_busy();
& `+ W2 X S3 U" K0 W/ g! ?+ O LCD_EN=0;9 @; |: R; H7 l7 v: {
LCD_RS=0;" d$ R/ g1 [. C# p- k6 u& W
LCD_RW=0;
* j! X5 s5 x7 O1 `5 ` r7 J- ] LCD_DATA=LCD_instruction;
7 a9 ~8 N8 I4 L7 s% ]4 \ LCD_EN=1;4 U4 ~3 b. d, c
LCD_EN=0;9 z6 Q9 |2 V; j5 ^
}
7 d6 f7 n" A7 K8 T! Dvoid LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD
$ K2 |$ E, t0 M# p8 J{
$ Z5 L7 Y% p- |" n* s LCD_check_busy();
; |+ A+ V [6 V) N LCD_EN=0;
4 [; A! d: S0 ]6 Y LCD_RS=1;
, C/ A- l, N4 o8 r: a LCD_RW=0;) x5 `/ f |0 T3 T. o! x
LCD_DATA=LCD_data;. ~( f; N# G3 t9 z% I" g3 R
LCD_EN=1;
! h& x v I; X$ K' U/ u LCD_EN=0;
& z c! A4 \; p* `$ K; B0 F/ H* q) p}
& ]# h3 ?6 i* ?1 n( mvoid LCD_initial()4 c& w, d) U* j" ~% z& x: v
{, \( P d: s& `7 Z: N
LCD_write_instruction(0x38); //两行显示
' ^2 N* O3 U/ |$ B8 J LCD_write_instruction(0x0C); //显示开4 w+ ^! `! b9 p& E; r6 ^
LCD_write_instruction(0x06); //光标加11 R) ~! p4 r, [; m+ W
LCD_write_instruction(0x01); //清屏2 A( ]- I& ] j& R
} g" t1 e. B, N0 `- }8 j
re() interrupt 4 //串行口通信中断
, ^) A" N+ H+ d% |4 k! _0 j{
6 G0 U0 b9 v) P9 U) n) r5 S9 w/ O( ` if(RI==1)
+ e5 B/ @% h, j- _6 o {
6 c L5 h+ ?+ U" u RI=0;
: o0 d: f7 f9 _! |/ [3 c$ k i=SBUF; // 接收数据
7 U: H8 t# f2 T# E3 e8 T" \8 L if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee)7 D( p7 B) i! h
{
* y1 g5 K" b$ p SBUF=1; //接收发过来 要修改的初值 ]0 X' Y7 w" v% ^8 h; _
2 A2 J p: {% A U1 t, N+ R2 A9 K; J
}
6 ~+ v$ O( Y3 ^; } else //接收正常通信的数据4 ]+ Y# U% E: G* b' L/ O% S
{, i6 q3 ` m0 W& l1 }7 x0 G- D" j
LCD_write_instruction(0x80+i);2 h/ M7 E1 N! S) f4 Z/ |3 g
LCD_write_data('0'+i);
$ Z8 w* X8 H5 \+ @! ~, g if(i==11)LCD_initial();
# I2 J3 k P6 t }' c' s7 N) z5 c e
}
9 D0 C& Z/ g% ?0 H0 }9 I v- c else if(TI==1)1 B1 a- q/ b) o0 \4 r$ G* ?5 I
{
$ d$ D5 q8 J! A6 X TI=0;' G- Z" { s+ e; u+ {. ?- L
TH1=i;TL1=i; //发送确认信号后 修改初值
* J& R3 o7 J! U- P2 v4 ]( h" u$ v9 M }3 }1 v3 q: Y& _. {- T
}# \* w2 Q1 J6 A) l$ L( z
void main()6 B- M3 g( ~* g$ p8 o7 d' o+ r6 i
{* u: d$ i" [2 v) J/ c; w
TMOD=0x20;3 _9 e1 J: n0 W* i% p' g2 x
TH1=0x00;TL1=0x00; //置初值
$ @+ f: q$ D% o8 K7 E TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断
' f8 Y) Y* \. {- t5 [9 d SCON=0x50; //使T1工作在工作方式1
. L/ h, W+ z& V/ u& L) D…………限于本文篇幅 余下代码请从论坛下载附件…………
6 ^# G5 P) P( ~: G: l) h, a" ?$ ^! h; B8 r7 b/ p" b
* E9 g) I% E" Z- T$ a6 M4 f |
|