|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序
2 b/ J% O, r' B; C2 ~/ ?) b! E" i' U" u' P7 V: F4 C/ V# ^
1 z+ ]8 k, z# Q2 Y" i
5 d$ K: r* P2 x2 w% D8 G给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。
1 l9 g. Y- ` q5 a5 o' w! k下面是proteus仿真原理图:0 \. ?) [$ z. @: g
# x+ F5 u7 n8 d. b0 _ h- k) o! o7 M* B, q4 D
! e8 \8 }7 {; F8 P, e1 u% r, X
主机程序:4 S- X: V& _1 E1 G J5 K
#include<reg51.h>
5 v5 X) q6 g d gunsigned char i=1;
5 s7 n' N! T6 n8 {& n( _unsigned char ACK=1;
' @6 k" w( p1 g, o% i& {% ]void delay() //延时函数
# T1 v( c8 {' k2 ? r9 E; i{3 m5 i: o( S; M8 N% s2 r
unsigned char i,j;
1 u. U/ V: U: E' V6 c for(i=255;i>0;i--)
8 }' l0 q* K3 F8 O% h1 O7 R+ o for(j=100;j>0;j--){}
* [) ]% a2 I" T5 i7 n% D( L}
2 H2 y' g( G$ H. D; v) G7 K- iunsigned char kbscan() //键盘扫描函数( n( f7 H' `& \% C, Y
{4 K7 [: `1 j# b o M
unsigned char sccode,recode; //定义行、列: h& R C! g0 d. ?1 Z% }
P1=0xf0; //高四位作为输入先写1" k$ W/ F! X, L* i* Q4 f# Y; A' V
if((P1&0xf0)!=0xf0) //判断是否按键按下2 q& t. X$ _2 \
{
) o, Z& Z- }. I& w" `% |, T3 c delay(); //延时消抖, N: N9 w! V6 F" H+ f
if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下
7 e9 I9 c; m* c3 d' H {
: t9 B1 X7 i3 S, G1 k" i" g4 } sccode=0xfe;* G' j5 T# u1 b8 D' Z# Z$ m) }
while((sccode&0x10)!=0)
. O9 ]( _: W7 | {- d( T9 F& k6 V
P1=sccode;9 d; H; X2 ]8 v- w5 i7 n
if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下4 D5 W' [4 o1 n( M, h/ k, T/ u) O
{
' b4 v/ q T: j+ d recode=P1&0xf0; //保留高四位输入值) l Y0 k9 `6 A; r7 ^
sccode=sccode&0x0f; //保留第低四位的值
; C8 Z/ b* f& k$ z6 L5 Z$ X return(recode+sccode);; h6 U& D9 X }1 \6 G
}" C0 Z* i2 O6 a1 T6 r( L$ U+ z
else1 G: \% p+ `5 M8 E$ \8 R; F& I
sccode=(sccode<<1)|0x01;
7 }( j! N$ f \% Q$ O2 d* K }. N/ `# D' E2 N/ a
}! t% {* j4 F, ^0 l) v7 q
}; S( h& }3 J8 Z9 L+ O% m# A% l
return 0;
9 C" T' C0 O4 ]. P1 w7 M; R1 K}
' H9 ?+ P, }& P5 Wsend()interrupt 4 //串行口通信中断& i7 |" M9 J Q, p2 C0 i) X
{# |% K3 T* n. M$ D
if(TI==1&&ACK==1)8 C" T0 H+ m3 {$ y7 a6 Y
{
4 \2 y1 s0 Y* ]' H TI=0;
( J- I) c$ l: K8 L if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率
" p9 o$ X3 e. |$ ]" Y {
6 D3 {* J- u% e1 s, g+ }3 ^7 W ACK=0;
6 F, y! ?2 S8 {6 l. v SBUF=i; //发送数据
1 Q1 N* C! p, l: w }) h- s& L; t4 T1 A* o. D7 J
else if(i==11) //循环发送,发了十一个字符后重新发' K; }) t1 t: e
{ |; n# b, f2 l; U; [0 z7 y
i=1;) _+ t: R/ j7 [& s
SBUF=1;
0 g) X) h, b! Z$ B% v }. ^0 x& f. o* G% o
else
- {6 K+ J# y! Q7 E- r- l {
" B) }6 t7 [2 g i++;
! _* S; ~* u' C ?: f- n$ z SBUF=i; //发送数据
( H4 L& Y3 H$ m- N# N4 w; @ }
* L3 k$ V3 v5 ]; [0 m+ j } D5 U' Z+ X: i N! _5 |% F
else if(RI==1) //接收回应的信号
0 Z c/ a. m" i- ]4 z9 W8 W1 ]+ g {
# N; d* T& X9 B' H$ U( ~ RI=0;- u/ ]8 f6 f! V$ ^ {! O& @5 f. \
ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断
% X# B$ u8 G8 t, ]6 ]" S# a, y: k# ] TI=1;8 P/ L! b" q! L7 B0 ~1 L- ]0 H. O
TH1=TL1=i;
# X1 J8 c, h- ` i=1;5 q5 M& e% ?" Q2 z, }' ~
}- g$ ?! A* t$ u$ W6 ]% q3 @
}3 g3 S" s+ k8 C6 |$ d2 _ @
void main()* a4 R6 K- c4 k0 F& K5 m
{4 h7 t+ _& ~ y' F& Z: _
TMOD=0x20;
' k8 {& u4 k0 R4 b0 [/ \ TH1=0x00;TL1=0x00; //置初值4 f; E% o& E( n
TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断) m% E9 N7 U7 i/ E
SCON=0x50; //使T1工作在工作方式1
6 K% ]( {) ` B SBUF=i;
( O. \- ?7 ]* R5 Z6 k0 E" f while(1)
* U# W. g/ y9 f {
- X9 j) i: c! O5 ^) N while(kbscan())
6 n1 k! y; ~) g ^: y6 s$ @ {* w4 U, W' Z! f* x
switch(kbscan()) //不同的按键对应不同的波特率
3 k9 H7 g+ f; n {
& @1 R8 `: e0 o2 `4 `/ j' w- W$ K case 0xeb:i=0x00;break;
7 _9 K E" x3 H: [7 j6 U5 W; D. a case 0xdb:i=0x22;break;; I' p/ s; J. B V% a' A7 R' X. G& x
case 0xbb:i=0x44;break;
7 M2 d( u: g+ w# e case 0xed:i=0x66;break;% M, c* B$ H9 K: T+ V
case 0xdd:i=0x88;break;
8 V8 Z* D( ~: T' e% A6 ` case 0xbd:i=0xaa;break;
- R& Q5 [& c6 V8 F; ? case 0xee:i=0xcc;break;
) o! k/ U: t. C; M case 0xde:i=0xdd;break; ?# T& i* w/ V Z' v/ l
case 0xbe:i=0xee;break;. S5 c: |: N6 G0 b: }( k
}
( X" d# q5 m4 d7 S: E& Q }3 o7 N% d7 ?* L8 x2 J
}: Y, G3 v1 a0 G( V$ ~1 U
}+ Y$ A# r% V$ F! h7 i
/ A& y) {* S0 [ |. m
丛机程序:
' Q w& B% p: R) c#include<reg51.h>
" X; M9 J* S2 p6 e* q v$ x/ \+ i#define LCD_DATA P0
% D' @9 ~. L2 t+ x) Dsbit LCD_BUSY=LCD_DATA^7;+ ^, K; N! H: r; j' t6 m. D) c
sbit LCD_RW=P3^3;
1 v( r4 L$ g. i+ nsbit LCD_RS=P3^2;
, }2 p" O0 g( i9 o7 m* v5 x# o( s vsbit LCD_EN=P3^4;& s) d1 E/ z# H
sbit P20=P2^0;
& v% `+ _) L& f* d: y+ @sbit P21=P2^1;
% K; l* b, Z- S9 y6 csbit P22=P2^2;
( c, P) y7 L( Y( f- q( bsbit P23=P2^3;0 T8 b1 h9 t; V3 ~: O( \. g
sbit P24=P2^4;
0 o W! w$ u+ W8 H! x$ _sbit P25=P2^5;
2 _ B, f' J! H* T* Gsbit P26=P2^6;
' S4 C0 F3 P+ |, I: h( `5 e3 ^& Usbit P27=P2^7;
* T# {) g8 N% w) csbit P30=P3^0;
5 t6 X( q: @: i8 {$ Z* Lsbit P31=P3^1;
( U$ I. \; J0 s) ~3 `sbit P32=P3^2;
Z+ @, u/ ^! p$ F1 _sbit P33=P3^3;
/ R1 ~& r! k2 t0 L* asbit P34=P3^4;
1 Q! h2 c u. b D; z3 n3 Tsbit P35=P3^5;
, x+ D0 k a. A4 Z. Ysbit P36=P3^6;5 H8 y; i, h& R u4 s& z. [
sbit P37=P3^7;
t) o$ z7 l% L: L$ qunsigned char i=0;7 B) s0 ?: b2 R) G$ s/ P
void LCD_check_busy(void) //检测LCD状态
# r# L0 `: X! J" m/ X2 f7 T. h8 [ z- P% n{: d' p0 w9 U) i! G; K2 {
while(1)
* {: o2 L4 Q& _. K0 i {
; e, j) G0 A+ O* e( Q f& ^
1 r& n8 @0 T& } LCD_RS=0;( }7 D2 R' M1 U* R% h
LCD_RW=1;
* e- `7 q4 U5 [ E3 t/ s LCD_EN=0;& G% X6 x& }- D" s0 F
LCD_DATA=0xff;9 F- M5 a \6 W2 \, D
LCD_EN=1;
4 s" E( g" z7 c) U, w7 R- g if(!LCD_BUSY)break;
6 {+ q* y& ?5 ~/ d; Y' C9 k" { LCD_EN=0;1 i( [# b5 J5 V2 ~" @+ x
}" T; u9 Q. }1 x) c( e
}0 l9 l* A- e( U; F( Z6 b1 c& d6 Y
void LCD_cls(void) //LCD清屏
3 t @- k: u) ]{
4 s' g' L p4 q. K LCD_check_busy();0 E5 C8 P/ {1 h5 M" E9 n9 J
LCD_EN=0;
/ {4 l# w, ^/ L5 g$ [' v# A LCD_RS=0;
% C# x1 Z& V/ ]; x8 f$ O LCD_RW=0;
/ q! t& l$ L) q LCD_DATA=0x01;. q- u) k( `% R" Z; N) b
LCD_EN=1;
1 [1 D2 ^$ y3 D LCD_EN=0;
: ~9 }* }3 M. Q7 p+ V2 c! g; v}
- s. i4 f/ W3 n# k" qvoid LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD
: t5 G" j" T7 `' k& m! a; K{
* C- \) p- |& q9 [* b) X LCD_check_busy();
/ Q& [# {" ]. l+ \" @& N4 E LCD_EN=0;& q* R0 m/ P& r" |9 o
LCD_RS=0;! i. f& W& l) l' h' z8 P
LCD_RW=0;
7 N" q1 B* l r LCD_DATA=LCD_instruction;
9 Q5 a E9 x6 E5 [/ b7 u LCD_EN=1;( S2 `4 f( R9 g6 ^7 n
LCD_EN=0;' [1 @: F/ d1 c
}
& n0 ~# X5 p3 {3 @. ovoid LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD4 ^8 l0 k& ?- A3 a, G
{
0 K' b; ~+ S) z |2 S0 C" h' a LCD_check_busy();
+ Q) [: a# J. E1 J/ e7 G7 |# O% { LCD_EN=0;+ t+ Y# D! o0 x
LCD_RS=1;
) z# P q1 P, q3 {2 ` LCD_RW=0;
. _$ M+ Y4 u+ h" @3 l- j+ i LCD_DATA=LCD_data;
1 ~9 M. m+ r# n LCD_EN=1;
. }2 J8 R1 \7 k. [3 |# p LCD_EN=0;
6 r O8 V* ]7 p2 o}- Z9 l/ u w: x B
void LCD_initial()
& N! M2 }& w7 J9 @{% o7 H9 G4 [2 _7 U5 h2 ^9 s: A7 [. o0 l! L
LCD_write_instruction(0x38); //两行显示
! q r. p" Q" R5 _) m0 ^( ?3 D LCD_write_instruction(0x0C); //显示开
1 O: O" u% f8 i Q! d, A LCD_write_instruction(0x06); //光标加11 E* ^. U" x8 N3 m+ H f
LCD_write_instruction(0x01); //清屏9 e' X9 C* _5 t8 P4 t+ K
}
! k1 l- f+ [ xre() interrupt 4 //串行口通信中断
; s( y6 |! _- ~+ [) E8 G% k{6 P( |* t& \( ^0 l+ L
if(RI==1)
. l! s# ?0 G# y8 l6 ~+ J' i$ N {
1 D6 R8 i5 C; G6 }; ^8 j RI=0;
! | K5 ^6 |! S3 p0 ]6 [ i=SBUF; // 接收数据
) d* e% t( L% F! J. I if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee)) X5 a- _# C9 f( Q1 @& \6 I6 z5 A
{9 J1 r0 ?3 Y, d- n) A( V. H+ Q+ y6 P, t
SBUF=1; //接收发过来 要修改的初值
7 \/ Z9 U( m4 s' z5 W
# L9 B: i; r0 I4 a3 }# S" P }
# ]# r! } \% T else //接收正常通信的数据4 m3 g% B+ X$ J: X
{
2 N; H) l0 V1 G+ n$ P) X* A LCD_write_instruction(0x80+i);/ x% q2 @" G) f# ^) k# O" T C& K7 W& R7 l
LCD_write_data('0'+i);
" m# n& c! e9 r8 |5 S; j) b7 ^ if(i==11)LCD_initial();; D% x7 M" L9 h% D3 V7 }
}
8 A- k- a& A0 ?9 J* {+ F2 M }
) f2 s" Y- [7 I* ^. ` else if(TI==1)" I/ ^6 s/ T9 a1 D# E! C1 R! E4 ]
{
+ Q5 S. d6 C. I4 l. c$ Y% N TI=0;( b: M! y! k* |5 v
TH1=i;TL1=i; //发送确认信号后 修改初值
/ Y2 x$ H. N8 N- y& h4 f+ z9 U }
( \2 D* F* t. N% H: d5 ~7 V}) k/ O9 O9 u# S+ W" t1 A" d
void main()
: V8 }( h9 m/ _4 r3 P: `) w{% S8 Q+ M3 U x. A f
TMOD=0x20;
+ A5 I( ]* K3 W5 a4 y, l7 ?& S TH1=0x00;TL1=0x00; //置初值' k8 t7 P- |5 ~3 \" v/ R8 ^! t
TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断
# f$ [1 w) f$ S+ H SCON=0x50; //使T1工作在工作方式1
) r& @$ o: m, U…………限于本文篇幅 余下代码请从论坛下载附件…………9 @. G4 c: d* a2 L7 f
* Z+ ~2 w8 @! }: Z! Y) E. o& Y) y. S3 `
|
|