|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机双机串口通信原理图,proteus仿真以及程序
2 A) n# _3 N6 D5 o" h0 T6 b2 Q1 h1 I
& Y2 L4 E3 c) u* d2 n
- T% A/ S1 J4 r$ P
给大家分享一个51单片机双机通信,用串口实现,有单片机主机程序和丛机程序的源代码。
$ a+ ^1 }; }9 T+ x4 t9 t下面是proteus仿真原理图:. R, |, M, \- u, _# Z* L
5 c! b y% [2 l7 ?
! ^( r8 ], q6 N( ]5 t& N$ ?+ c6 {: L, D& s* H
主机程序:
% |' f, a9 y H q#include<reg51.h>3 u, i1 G7 H) A& i$ T
unsigned char i=1;
/ o; @1 G* o6 e1 M3 a9 qunsigned char ACK=1;8 k" v# |5 ] E3 N, q
void delay() //延时函数
4 a& @ o& k0 V6 e, p, Y9 L! M) t{/ \7 W8 L4 }. E- `. u+ d
unsigned char i,j;
' @0 |! U6 I$ p+ [ for(i=255;i>0;i--)
5 H% `; i# j( x for(j=100;j>0;j--){}
; O& f+ e" c2 S+ } Q}/ t2 o m& \- X' i, B% M) s9 [$ Q
unsigned char kbscan() //键盘扫描函数
- f2 _8 l0 f, i- Y ]; M{ `4 @) }- d, F0 n* D5 J! D
unsigned char sccode,recode; //定义行、列
" G8 u- R p; X. p P1=0xf0; //高四位作为输入先写1
7 l Z l( v: z. a& R if((P1&0xf0)!=0xf0) //判断是否按键按下5 c0 q7 E3 A X, s
{ ! Y9 Z6 b4 d% W" I$ n1 ~( L& V
delay(); //延时消抖
' S2 [* F1 ~9 Q' c* e' R. t! h if((P1&0xf0)!=0xf0) //再次判断判断有没有按键按下
1 D. e' ~% }5 r( N {$ O2 e4 V2 k9 Z" m6 o9 c5 b
sccode=0xfe;' \# L/ |+ D7 |* q w% o8 H
while((sccode&0x10)!=0)3 K: |( E$ \% i& d' h- _" R
{
8 s) p9 c2 U9 J- O7 y' [ P1=sccode;; T t) w) J7 y! v$ n
if((P1&0xf0)!=0xf0) //判断当前行是否有按键按下
0 J: R; {/ L& I {
" l; U: L# a: p7 E6 M: P. f recode=P1&0xf0; //保留高四位输入值+ o( `1 X2 V0 O# M# c# w. t m) E
sccode=sccode&0x0f; //保留第低四位的值
7 H$ `2 k- y/ l4 } p5 M$ R return(recode+sccode);4 V! b, p; u }- P0 n2 A! }
}
0 t# S% [" Z0 P% t else
4 u4 `- a/ h9 W. g" Q! r& Z$ Z sccode=(sccode<<1)|0x01;& R, ?% B1 g, Y( I5 W* ~$ ?6 [; }/ X
}
! y$ p, U/ a2 W5 T1 U }6 `$ w6 E8 J3 U: n, g$ l d3 \
}' P1 D3 M# C, L; a* E( ?% a
return 0;
9 ]* Z* _0 C/ j" R, M}
: J: M* e% H0 L+ j$ @send()interrupt 4 //串行口通信中断( W& x1 E' w/ Z6 [6 M
{
4 F! e3 Y1 V, H, h p F if(TI==1&&ACK==1)+ @5 ^. e/ x0 K. C
{
" g0 P; j* U3 E$ N TI=0;6 L7 t+ [5 N% [! Q
if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee) //有按键按下,需要修改波特率4 ~: { Z, h: L: k4 H
{
- |3 K" L. G$ I ^: }# Z ACK=0;
% P; R C: M% ~, M5 ]) V8 t4 p SBUF=i; //发送数据; u; D- y$ N, ]+ \5 o8 ?
}
# `, ^0 f" a# b. n* ] else if(i==11) //循环发送,发了十一个字符后重新发! ]1 Z* Q) T! S& s4 J2 @
{9 J: [1 W( S. C2 Y
i=1;- B! V6 v5 K9 {) d8 P# p" c2 c
SBUF=1;! u. \* H, q* D8 K# l. I* u- l
}
m' h0 m5 A* r( Z, P0 N else" |. z( ~; h( K
{* v! v* ?" W+ C7 N/ g' l. H" B
i++;% C" U3 F( P4 Q0 Y+ O4 L R
SBUF=i; //发送数据
1 j1 Q8 L" c/ U1 u) Z( o- D; M+ _ }
) ^$ r- W7 D+ Y3 w0 j) t; x( R# G }
2 ]# V& @! Z+ S else if(RI==1) //接收回应的信号
! m( r+ n- F0 p% K2 \, _+ i5 I {
! x4 p z* \; | RI=0;* |8 B I, T- C, E5 {4 ]
ACK=SBUF; //接收回应信号 修改初值 触发串口通信中断9 y; j% c" r& k- [7 r; H, z
TI=1;
2 G) ^* _ `4 g) I k+ I S. l TH1=TL1=i;
8 u8 I6 T/ n# p& t9 O; T i=1;2 O/ Z9 `8 u' T) b$ J5 N+ I, Y
}3 b& n6 ]/ w/ R U, |' J0 g
}
& J9 X' @5 K1 V9 }; |: qvoid main()
, M- S: y. b$ Y& t3 n{
) r; i7 }& ]1 E4 c4 v; d, y TMOD=0x20;9 ^0 ~9 _6 g1 o$ j7 V) G
TH1=0x00;TL1=0x00; //置初值
% Q: ]. J4 _' R TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断7 f8 {4 x6 v, E+ B5 g3 T; E' {) d
SCON=0x50; //使T1工作在工作方式19 ~) l& z5 ^0 H+ A# \' A$ z+ h
SBUF=i; * k0 V4 O3 F( o5 b5 \
while(1)
" f( J; H4 U" x3 V {
! C* B# A0 x* ^ while(kbscan())6 q! r/ ~5 l. Q6 j7 P- B8 t
{
: @4 m$ }; ?* u8 R switch(kbscan()) //不同的按键对应不同的波特率
+ i( a- v+ a' o {
, l4 I+ j% i7 ~' C8 S0 J V case 0xeb:i=0x00;break;
4 c4 b4 a0 V9 }) ~9 B% C2 G+ e case 0xdb:i=0x22;break;
" d& D# l8 V. o2 { |) d; m case 0xbb:i=0x44;break;6 n1 W4 o: @5 Q; O: P- j+ T
case 0xed:i=0x66;break;
$ m K) r. q) k: R case 0xdd:i=0x88;break;
4 E" i2 O, P0 o. d3 O u case 0xbd:i=0xaa;break;
+ F8 Q4 U D2 D$ R& u! s) t case 0xee:i=0xcc;break;
& Z) [) h( Y; g+ d' N case 0xde:i=0xdd;break;; l0 v, J: m- ?% e8 _% I! w
case 0xbe:i=0xee;break;% k' C6 ~/ s: ^, n: p
}. D/ H6 e e: U+ b! L
}
, X0 w! F+ u* I0 b2 R) b, y }
9 [4 U# i9 C) V/ Q* }" w( ~. e8 t}
- i+ J2 M7 d2 f5 S$ D# J% k, `$ ^' S2 t! d8 D) u4 @
丛机程序:% E5 q! A: v, O: ~
#include<reg51.h># B3 P/ w; \$ F! e9 x9 S
#define LCD_DATA P0
7 B+ ?6 u, W9 W. G. a5 j6 T5 K, w. Asbit LCD_BUSY=LCD_DATA^7;
+ m3 r/ u: m( |- M7 bsbit LCD_RW=P3^3;! J( v7 Y; T" _
sbit LCD_RS=P3^2;, G/ t' P( x+ I. C" C
sbit LCD_EN=P3^4;
0 U' ^* Y8 z. {- V5 q# e% V" c! Xsbit P20=P2^0;
/ r: g8 a! z8 \9 B! osbit P21=P2^1;
8 i" z/ P; J. o) L ^sbit P22=P2^2;* B2 H+ o& K# q. ]7 N2 F
sbit P23=P2^3;( m' H/ Q. n) ]/ z; t4 _5 O
sbit P24=P2^4;4 O' E. t$ l4 _ b$ g7 i
sbit P25=P2^5;
' }# Y7 v$ Y: `3 Q& v4 Lsbit P26=P2^6;
) \( ?( S& R# ?2 `+ r3 xsbit P27=P2^7;; R- l. I" m: Z+ e. r8 B2 ~" t4 B: [
sbit P30=P3^0;& V. U4 N+ `" D! c8 y$ Q. b7 t
sbit P31=P3^1;
& O* y0 R8 v% S [( Xsbit P32=P3^2;
# Q- o% k4 [: s# \sbit P33=P3^3;
3 x3 ~, b0 T$ w7 ^sbit P34=P3^4;
0 ?' G" V7 D9 a8 tsbit P35=P3^5;* @, y0 y: A6 j
sbit P36=P3^6;- p1 s% l! ?7 `
sbit P37=P3^7;
& M* B$ l5 N) x1 N7 nunsigned char i=0;
/ g& h" [/ ?! s7 ]void LCD_check_busy(void) //检测LCD状态4 f. w# p, s+ B7 o
{4 U" ^$ Y: `# { v+ j' q0 J
while(1)
3 c$ H8 g b# l2 h! g( t: q9 n {' e, N5 R! M5 B+ i7 @
+ ~5 h4 {. D1 b R0 v9 }
LCD_RS=0;
1 ~0 R1 ^9 V' J. u5 }2 g, M3 Y5 Y LCD_RW=1;' G& b6 G2 v( {5 E: F$ c9 R2 x
LCD_EN=0;
; ^" ?" v1 c" l LCD_DATA=0xff;, M- a: v4 O+ P/ W) u D2 ]
LCD_EN=1;0 c; X! U: G1 m9 T
if(!LCD_BUSY)break;1 C! a3 \2 C7 Z9 z
LCD_EN=0;; o ~* y7 V1 Z, {! X0 }$ t
}
5 o1 h: \8 n! a0 u9 J2 Q- M}
% ~5 \$ y) U* Z$ i& ]* xvoid LCD_cls(void) //LCD清屏( Z5 O; ?+ E6 D6 c" ^+ A( z
{
$ b9 g: T* ^3 z/ n LCD_check_busy();
+ k: ^2 p3 ~# J LCD_EN=0;' O- H& e2 w0 u7 j
LCD_RS=0;, x- ~$ `$ x1 A( d! O5 \
LCD_RW=0;' h$ M$ R' y. R2 T* [
LCD_DATA=0x01;
y- K4 X3 ]( u4 v$ ` f LCD_EN=1;$ }& t0 E% s+ N( L. B
LCD_EN=0;
5 a3 e0 @- i7 \; r: Z+ @% V' C- ^( }. W}) G+ [8 q* B( r$ j& z8 ]
void LCD_write_instruction(unsigned char LCD_instruction)//写指令到LCD
+ P/ G) C4 U- _) _{
7 O9 m" x# P- l LCD_check_busy();# E/ Q5 j/ t+ m5 H$ r% h
LCD_EN=0;
1 ~$ m5 O! o0 ~8 { LCD_RS=0;
& N6 V L4 Y5 w, Q, l+ i LCD_RW=0;' ^) T4 Z- _0 d9 S7 b" T8 h
LCD_DATA=LCD_instruction;8 A% a- p A# s3 ]; p/ N
LCD_EN=1;7 }( p) b) P' x3 @. n. f
LCD_EN=0;
3 v3 ?. d, N+ W2 M+ n}
: g( b2 A3 P0 x5 B7 v- w8 jvoid LCD_write_data(unsigned char LCD_data)//输出一个字节数据到LCD+ {% V u! f2 H" W* h
{, G( I$ t3 H P$ V
LCD_check_busy();
3 Y6 M _$ e2 m) f) q# G LCD_EN=0;# |" J0 C2 z! E1 J& t5 p
LCD_RS=1;* D5 O& ~2 U$ S" o
LCD_RW=0;
+ d( q5 m6 K+ n6 h1 R% N7 l( m LCD_DATA=LCD_data;
( s; A9 u7 N0 U6 ]& g% C LCD_EN=1;
$ ~+ I1 F0 C6 h" A8 D LCD_EN=0;2 q, [, O- v! c$ t, I) A' c
}) [: u% z/ l8 {% G- v( N: O- u9 Y
void LCD_initial()
2 u) ? P. M& [% p. A! o{
" z! P1 q7 a, [# o* ` LCD_write_instruction(0x38); //两行显示
+ S* ]" M& P8 ~+ {! g LCD_write_instruction(0x0C); //显示开
$ w3 h6 u3 A; G- v( D: M LCD_write_instruction(0x06); //光标加11 z- }+ N! W$ v& M# B1 M
LCD_write_instruction(0x01); //清屏1 n9 N* f1 F' A( }2 m! r
}
8 {: z! ^3 C, L# I& F9 l2 kre() interrupt 4 //串行口通信中断# z$ [( y, w9 r$ A3 A+ K: b7 Q+ f
{& O U" N/ A" @0 a6 j: q+ V
if(RI==1)
9 Z1 J# p8 F# p9 _$ q$ E) \8 Z {
( T7 c9 r6 _" j, |* T: n" q" J& R( u3 A RI=0;
5 r# j7 R1 ?% |% M- ?2 } i=SBUF; // 接收数据# z8 c, M2 V- N$ n3 J# v) {; @
if(i==0||i==0x22||i==0x44||i==0x66||i==0x88||i==0xaa||i==0xcc||i==0xdd||i==0xee)
' \0 \* ^$ U, t) r0 ~+ p9 H/ j8 A {8 X6 K; k% [* z4 a7 b; \: o
SBUF=1; //接收发过来 要修改的初值
! X3 ]+ e, n; R0 L# n / z8 T% G" a1 m
}
" n: w8 g: E. v1 i else //接收正常通信的数据
) G9 r) z7 v# j! I# Z {$ X7 W* I1 w' B! `# Q, ]
LCD_write_instruction(0x80+i);4 C8 v- y! u; k& @+ l% ?! M& N
LCD_write_data('0'+i);
2 I; c4 c' T' T4 a9 o$ \+ o% m if(i==11)LCD_initial();7 ]5 o& E) c3 D$ Z
}
1 W" P' h" v5 V) `. { }2 |* X* T- w+ E6 Q# V8 u
else if(TI==1)1 w1 D" ]1 Y+ V" F# z
{
! u _9 l1 Z, V8 r/ J; m TI=0;, Y6 Q# X: ]# F* P
TH1=i;TL1=i; //发送确认信号后 修改初值
0 u4 n! {: ~& U. c" d, i! } }
1 f) N1 {6 v( ]% v- m! B. M}
+ I8 X+ i7 m: W: vvoid main()) D7 }! Q+ k1 p' Z$ _+ Y
{
3 M. n- K- u( m% N& V; X TMOD=0x20;% a4 f9 u4 h# s3 D
TH1=0x00;TL1=0x00; //置初值
7 A5 Y8 [# k1 w8 c" W6 s TR1=1;EA=1;ES=1; //使T1开始工作;开总中断、串行中断
: V/ _, E' \5 c9 W" q, _- _+ L/ w SCON=0x50; //使T1工作在工作方式1
* h3 `, {4 q- Y, g' P/ j5 N0 K…………限于本文篇幅 余下代码请从论坛下载附件…………4 d4 m5 Q. b% Q6 l
n/ p0 h! M. J7 f) [0 ?, R( N
' J) R& }! R8 {; @' @, U6 e |
|