找回密码
 注册
关于网站域名变更的通知
查看: 314|回复: 2
打印 上一主题 下一主题

串口多机通讯及实例

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-10-12 14:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
在多机通信过程中,所有设备的 RS232接口是并在通信线上的,其中只能有一个设备为主机,其他为从机,通信由主机发起。数据帧一般采用1位起始位、9位数据位,其中第9位(RXB8)被用作为表征该帧是地址帧还是数据帧。当帧类型表征位为“1”时,表示该帧数据为一个地址帧;当帧类型表征位为“0”时,表示这个帧为一个数据帧。
      在AVR中,通过设置从机的UCSRA寄存器中标志位MPCM,可以使能USART接收器对接收的数据帧进行过滤的功能。如果使能了过滤功能,从机接收器对接收到的那些不是地址信息帧的数据帧将进行过滤,不将其放入接收缓冲器中,这在多机通信中有效的方便了从机mcu处理数据帧程序的编写(同标准51 结构相比)。而发送器则不受MPCM位设置的影响。" G" f+ I  x0 B1 ^9 ?
      多机通信模式允许多个从机并在通信线路上,接收一个主机发出的数据。通过对接收到的地址帧中的地址进行解码,确定哪个从机被主机寻址。如果某个从机被主机寻址,它将接收接下来主机发出的数据帧,而其它的从机将忽略数据帧,直到再次接收到一个地址帧。(从机地址是由各个从机自己的软件决定的)。
4 Q6 Q3 Q* A! M2 ^      对于在多机通信系统中的主机MCU,可以设置使用9位数据帧结构(UCSZ=7)。当发送地址帧时,置第9位为“1”;发送数据帧时,置第9位为 “0”。在这种情况下,从机也必须设置成接收9位数据帧结构。0 I. o, n5 U% ^0 |
     多机通信方式的数据交换过程如下:2 H# r9 X1 S' D4 d
1)设置所有从机工作在多机通信模式(MPCM=1)。
! v* k" v0 z% V0 }5 r$ e: b0 l2) 通信开始是由主机先发送一个地址帧,如8位数据为0X01(1号从机地址),第9位=“1”,呼叫1号从机。- D: u$ \7 Z) T+ ~8 u$ Y
3)所有从机都接收和读取该主机发出的地址帧。在所有从机的MCU中,RXC标志位被置位,表示接收到地址帧。
3 l. e! a* F# b8 D4)每一个从机MCU读UDR寄存器,并判断自己是否被主机寻址。如果被寻址,清UCSAR寄存器中的MPCM位,等待接收数据;否则保持MPCM为 “1”,等待下一个地址帧的接收(该步应由用户软件处理实现):
- [2 h9 u( B. Q: l: ]6 B7 hA)作为1号从机的MCU处理过程为:收到地址帧后,判定读取UDR数据0X01为自己的地址,将MPCM位置“0”,接收之后所有主机下发的数据帧,直到下一个地址帧为止。0 X4 b$ p; J8 p2 ~
B)其它从机MCU的处理过程:收到地址帧后,判定读取UDR数据0X01不是自己的地址,将MPCM位置“1”,这样他们将忽略主机随后发送的数据帧,直到主机再次发送地址帧。
' |( e3 h; r) ~  L: p5 T! @( \5)当被寻址的从机MCU接收完最后一个数据帧后,将MPCM位置位,等待下一个地址帧的出现(该步也应由用户软件处理实现),然后从步骤2开始重复。
[转]例子;
通讯规则:" [0 w; m$ Z0 G/ X+ Y+ I
1:时钟7.3728 MHz/波特率9600/9个数据位/奇 校验/1个停止位/硬件多机通讯功能/. }5 q. l4 g# p! }: z
2:通讯连接采用硬件MAX485,双向单工6 a# [7 Y. F6 ?3 H. S: K
3:每个上行/下行的数据包的字节个数都是一样的(通讯数据量)+ D  n! s7 \3 j4 ^
4:每个上行/下行的数据包都采用CRC8校验
4 @4 ?7 T+ @" t1 p5:数据接收采用中断+查询的方式$ L( D. X0 `* V0 M2 f* X, P% U
6:总是由主机向从机发送一个数据包,从机收到数据包后向主机回复一个数据包
* X5 M3 o0 X; A7:不管是主机还是从机,如果收到的数据包有任何错误,都将丢弃该数据包,等 效于没有接收
; T: A: O5 C9 }3 M! d& h$ I1 B8:从机之间不能相互通讯,必须通过主机才能交换数据: h% A7 q& y: A
9:无效地址是0,主机地址是1,从机地址是2.3.4......广 播地址是255
0 r) R- f# Q  a; k*/
+ V! h' ?. b6 c( _6 Y#include . `& O1 `* C5 H
#include , t. P0 w& r+ B9 O6 Y
#include 6 o. v3 k2 A' ?+ n0 F0 Q
#include //CRC校验函数就在这个文件里面
6 e: Y, F: p8 w& ~( y, ~* k, v" m+ u  ?) h. i" L' j
#define amount 10 //设定通讯数据量(包括1个 地址帧,n个数据帧,1个校验帧)
" {: ?/ w5 Z) P* o* M, E- Y4 Z3 ^( L8 P% S, E7 Z
unsigned char send[amount]; //发件箱
/ C8 R, `- o# i- A9 a( J0 Vunsigned char inbox[amount]; //收件箱7 ~$ O1 C* _& W' T* P1 T
unsigned char n=0; //记忆中断次数- Z) i1 X, o/ i0 _) v
8 _) R( V. j/ o: ^+ N" r5 r
//--------------------------------------------------------------------
1 l& [5 i2 x2 Winterrupt[12] Rxd_isr(void) //接收中断
% i; U6 m4 q; `. a{, F( m8 X$ S  B. ~" y
unsigned char ERROR=0;
6 P$ ?- N+ v, C- _1 ?4 Bif( UCSRA&4 || UCSRA&16 ) ERROR=1; //奇偶效验错误或者帧错误就记录下来
9 q* g$ X+ \  T- L: ginbox[n]=UDR; //保存到收件箱. Z" L+ l  j4 t$ c
n++; //记忆中断次数
+ V/ R. G: P( Q- Q# L. Y& O. j" ~2 A# mif(ERROR) inbox[0]=0; //如果通讯有错,收 件箱的地址帧就标记成无效地址0/ T$ P& W1 E' t, x  d5 P
}
5 X' d/ d' M2 d' ^& d- l9 q3 e+ c4 v( Z6 B' B  U
//---------------------------------------------------------------------2 `: x  r' ~: M2 C! I2 m
void main(void)
8 e7 F6 i7 S0 l+ E{. ~/ Y" N* L  I
usart_init(); //串口初始化3 l; O9 F8 ?, c' a
UCSRA=0; //主机关闭地址筛选功能(多 机通讯功能)' H6 G' ?" t& J  E2 K; m! F
#asm("sei") //打开全局中断
$ s9 N- s, A. q6 gwhile(1)( t1 B0 q8 B7 r- @0 S& s
{4 N$ D3 Z  Z) ^' T% s/ V  u
//-------------与从机2对话,与其他从机对话与下面的 程序类似-------------------7 K7 y8 Q$ Z8 o$ `3 I: ~
n=0; //中断次数清0
7 }9 H, ^# [3 }& L7 T/ @, _inbox[0]=0; //收件箱地址清0$ ?' R" y' r6 z% J
//请更新准备发送的数据
. x6 H; Y7 L3 l9 U# }% ]//send[1]=?
$ p+ O: J6 Q, j- d. g% J" @//......
' @" _' \% H: n2 S: v' ~* S  q  E//send[n]=?' K: |& P$ R: G2 i: L
send[0]=2; //改变这个地址就可以实现与某个从机对话* Q/ O' R6 s" \
send[amount-1]=crc8(send,amount-1); //计算发件箱的crc8校 验码
  I/ z- ?0 a/ o$ Y; i0 K( _usart_out(send,amount); //将发件箱的数据send[]发 送出去;
' {( c/ c9 P) C% v6 F* I
2 R! u1 y/ L- `' K' Q9 U4 v" ^//等待,从机接收到数据后会回复数据的,如果是10个 字节数据量,不能少于13ms!!!) x$ [; V& O2 m1 r  q3 l
//这个时间由人工计算,要考虑从机由于各种中断延长回复时间的可能. q! G+ v3 p, L- z2 h  l

5 E% ?; ?: n# n& Idelay_ms(15);
  q( q( ^, N9 S# g/ [. T
+ s. R3 n8 t4 C7 W" u2 u//if(n<3)如果接收到的数据还不到3个,那么就是通讯线路故障
: {6 k4 u& d3 c' k
  k6 B* `% v6 K7 n//如果收件箱已经收到amount个数据,并且crc8校 验成功就...
9 \+ C3 @, b" C4 v- s$ _if(n==amount && inbox[amount-1]==crc8(inbox,amount-1))
# G* Z0 i  E5 `" S$ y) _6 Y{
) N% N+ L/ W2 {  {! i- s5 pif(inbox[0]==1) //如果收件箱地址帧属于本机就运行下面的测试 代码5 T# O' X, Q4 U6 H
{0 ?0 x% m6 t, h" z% j& [8 ?- D
DDRD.3=1;! ?$ j/ _: p) G5 J8 e
PORTD.3=1; delay_ms(10);" w- k( a7 ?; q* ?
PORTD.3=0; delay_ms(990);2 j- j$ f7 h+ W$ p  F& U
}
9 ~6 v2 d! F! D  @9 P1 `/ t) p, W- {  {  T) |
if(inbox[0]==255)0 {0 S' E; A% M
{: c/ d5 A4 D7 B, [: J0 Q- x! a
//请在这里添加收到广播数据的处理程序- P, Z9 c; k3 M, H9 k9 {
}+ x4 R5 A* c4 c8 A; o
}
! Q! ]3 ~( v9 O0 N+ F}/ b$ [/ W9 \$ d& ], u2 s
} //end: _" W! {8 y% o' E, b, F6 B' m
: N4 Y) Q) B( x
---------------------------------------------------------------------------------, z& p# e, }# e$ j) i. W7 u4 {
从机
0 S8 |7 @( i1 l1 ^/ K6 s, \---------------------------------------------------------------------------------3 v  [9 D/ R8 S, l# L8 M- H9 w
#include
8 k! Q( K' E( A/ j) h) Y#include & K0 d% w/ J" s0 ]' {- D# d
#include 7 @7 p4 Z) _2 M  q  r$ b7 t

+ Y6 I0 _7 A' h( H#define amount 10 //设定通讯数据量(包括1个 地址帧,n个数据帧,1个校验帧)
- S9 S+ w1 J& G#define address 2 //请在这里设定本机地址
1 n) _3 Q+ @8 X. M8 S+ E/ x3 O) B
  [0 e  L. P  j3 `unsigned char send[amount]; //发件箱
5 ?$ W! n" |( C+ X7 d6 W& s! _unsigned char inbox[amount]; //收件箱1 y/ G- ^( v! A1 I' [
unsigned char n=0; //记忆中断次数
7 b  A, u  H. ^) `" p
) n' _2 |. C+ C; Z1 ]% A5 pinterrupt[12] Rxd_isr(void) //接收中断
. ^9 e4 k0 d' Y6 d{1 y6 p) |& i( F0 Q# Q
unsigned char ERROR=0;
/ d' j1 n( H7 w3 z2 m% B  t+ dif( UCSRA&4 || UCSRA&16 ) ERROR=1; //记录 奇偶效验错误或者帧错误- B, I- Z; A  v5 v: z% z
inbox[n]=UDR; //把接收到的数据保存到 收件箱
. j) K$ x: q/ U0 x+ Mn++; //记忆接收的次数
4 `3 p! z0 }; S: s  X3 |2 ?if(ERROR) //如果通讯有错....+ F0 [$ b. s0 K; i  `5 A
{
; |2 t- ]2 ]3 }4 c8 fn=0; //接收计数清0
1 d  N1 {+ Y+ K( l( Yinbox[0]=0; //把地址改为无效地址0$ J) j! }; E9 u' _
UCSRA|=0x01; //重新打开接收器的地址 帧筛选功能2 r+ s" D! W/ o1 g0 `$ m
}) t7 e! a  M5 n& p2 o
% d  ~6 O1 @6 n$ c& w3 Q" f
//如果地址匹配本机或者是广播地址就关闭地址筛选(多机通讯)功能6 |4 f2 \5 _, F
if(inbox[0]==address ||inbox[0]==255) UCSRA&=254;
& c/ z6 D8 K+ \( Y
4 x# y6 |3 s0 n! T/ c; f% X6 Lif(n==amount) //接收到amount个 数据以后...) j2 V9 V( T% h/ S; [, l- t2 s
{; e, E6 A; S$ R5 d. M# z  }* |
n=0; //接收计数清0% g! K5 R& }- J, {1 W
UCSRA|=0x01; //重新打开接收器的地址 帧筛选功能
# I8 [3 g! {, D9 d$ I6 Xif(inbox[amount-1]==crc8(inbox,amount-1)) //如果crc8校 验正确就...
; D+ N2 w( @# e' s& n" U, F1 O$ Z{: Q- O5 Q, I' o2 C! j7 t, \
if(inbox[0]==address) //如果地址匹配本机就回 复数据
% M+ n1 o% c7 d2 z  T7 Q{7 C: `5 l# @  R3 d5 {) D5 r
send[0]=1; //发件箱地址指向主机8 l% \% y- ~1 g2 t" k
send[amount-1]=crc8(send,amount-1);//产生发件箱的crc8校 验码
' a1 @1 V4 z- Q7 ^* b; r1 X4 z4 Dusart_out(send,amount); //发送发件箱的数据包send[]
6 V# g# Y; c! v0 v2 q) T//请在这里备份你的收件箱信息
0 E" n2 M7 z  G6 J$ ~- e}5 F: @7 Q' q9 q8 U/ [, k
if(inbox[0]==255) //如果是广播地址就...
" m* O1 i2 h" v& Y8 }) J5 [{+ ?* o7 d+ [" f
//请在这里添加你的代码
% J! X0 ~9 |8 \, U- v- s. M% a//收到广播数据请不要回复% Q+ E, h7 b2 s6 \1 Q0 \
}
" t8 Z4 k3 H+ x5 ]9 e+ a& X3 H}
& N" G2 \. h9 K8 g6 M}5 D2 {* W4 w$ X; t
}, ~. V) Q7 t  X8 p( T
2 x) I) U. X: ^# F1 @
void main(void)
- L8 Y9 {' M. Z, w6 o; P{1 Y( j( q( S. o; b7 Q
usart_init();, w; A: ?( }/ u- m% h8 d2 p) E
#asm("sei")
# e  Z! V. u# z' S  Q& B6 y: n! d2 B3 d4 t0 Z
while (1): D, ^9 r" R6 L! K% R; s
{
8 m; V; W! c: r2 }' b//send[1]=?  I" A* u) ?. J5 T" D' q2 c* S! T; Q& I) M
//......1 w9 P+ r8 ~7 ]& P' l: G5 F7 U" g
//send[n]=?
/ U9 ?5 o4 P0 l' L0 X( h$ q5 N};2 c! X# i5 i3 G# r
}* Z1 S+ U* s4 F* E

, `( U& t. i  J% A& H% B( V- D5 }* w' W# I' ~" f
---------------------------------------------------------------------------------2 R  b  B9 ~- v6 N
usart.h文件6 l+ U% S6 @8 [. M4 i+ m' |/ m
---------------------------------------------------------------------------------
, o) a7 a% y: h//波特率9600/9个数据位/1个停止位/奇校验/收 发开启/接收中断
* ^% _! V2 Z, E/ t  ?6 L! }2 f' Hvoid usart_init(void)
' R# Q: o4 [$ Y4 A, `0 J{# c- v$ E5 }7 J' D6 l8 ^3 g: g& n
UCSRA=0x01;
# o. |9 b+ Q/ `6 M6 yUCSRB=0x9C;/ M( F) ^8 ]0 j! j8 u- o& v2 _
UCSRC=0xB6;# N% g4 B/ M8 L0 b  r0 v* y
UBRRH=0x00;( G( _' |. G- n  x
UBRRL=47;! z0 Y5 B7 l5 x

( k! O/ ~# W/ k# e+ g% uPORTD.4=0; //MAX485平时工作在接收状态
" R  E" t) V8 f1 KDDRD.4=1;- u0 F; U4 O- F. N- y( N$ y; i
}
! g2 B9 v6 B1 T: F5 _9 ~( t/ a$ p% N, ^" U
//-----------------------------------------------------------8 ~6 R) x# ]' U1 i  L# v9 `( M
//从数组datas[]的首地址开始发送amount个数据,其 中第0个数据是地址帧,其他是数据帧
5 e6 z7 I: a7 ^void usart_out(unsigned char *datas,unsigned char n), h3 _1 T; D9 J4 Y
{
3 {7 M# _4 L0 s6 k& g3 Zunsigned char i=0;
0 V% }; G3 q2 Q7 A2 R3 @PORTD.4=1; //使MAX485处 于发送状态) k/ ^. `/ w  }6 w; E
while(i {) O6 }, n$ D# N/ w
if(i==0) UCSRB|=1; else UCSRB&=254;: m) r6 e7 B9 L+ A* `6 |
UDR=*(datas+i); //装载数据开始发送7 N$ K# [/ A5 q: g1 E2 [) p
while((UCSRA&64)==0); //等待发送结束
. f/ {1 C9 h4 s$ X# Z7 oUCSRA|=64; //清除发送结束标志. ?' K8 q% {% ?( k
i++; //发送次数统计
7 R3 o8 N/ U9 N8 o$ \3 A}. E2 g- {8 v4 Y1 F. ?* N
PORTD.4=0; //使MAX485处 于接收状态
7 R2 C: G& y( h/ w, S}; A/ |2 Z, I- H- L; W2 o
% [; Y* {5 l" N6 x- l
---------------------------------------------------------------------------------
4 b  E$ {0 Y) J, c( M. |crc8校验程序
0 e0 c$ ~+ N) X" Q  P* r---------------------------------------------------------------------------------  w  @& Q5 u, Y: [
unsigned char crc8(unsigned char *ptr, unsigned char len)
0 q9 y' }* P/ J! z/ G1 z3 \{. Z  ]6 l3 N/ w# n, f
unsigned char i;2 O+ O. ~$ \& `+ n& z- i" n
unsigned char crc=0;
) |" |# ^% m; P* ^& f9 t, L& ?while(len--!=0)
4 B/ x* \1 @9 u{
0 Z# J' o  ]& N# I: S5 ?for(i=1; i!=0; i*=2)( X6 p6 a7 q# G% t5 {( }
{
# c, |9 @4 e) A! B6 g* qif((crc&1)!=0) {crc/=2; crc^=0x8C;}8 h" S. n3 h1 S/ k# |
else crc/=2;
9 Q/ d. I! F6 P- A4 Rif((*ptr&i)!=0) crc^=0x8C;
$ t# H) i8 y/ m" \! e}
- Q/ D3 r0 h0 ?+ ?6 C, }2 ]/ Bptr++;
  w/ b7 j- u3 `3 V- L. D}
3 [& y' H+ Q6 |4 o& Sreturn(crc);
8 a/ i; b8 j" |  X# u  L3 W}

  C7 F! U. }. _: p6 k# Q" j
  • TA的每日心情
    开心
    2019-11-21 15:51
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2020-10-12 15:45 | 只看该作者
    多机通信模式允许多个从机并在通信线路上,接收一个主机发出的数据。通过对接收到的地址帧中的地址进行解码,确定哪个从机被主机寻址。如果某个从机被主机寻址,它将接收接下来主机发出的数据帧,而其它的从机将忽略数据帧,直到再次接收到一个地址帧。(从机地址是由各个从机自己的软件决定的)。
  • TA的每日心情
    开心
    2025-11-24 15:05
  • 签到天数: 1278 天

    [LV.10]以坛为家III

    3#
    发表于 2020-10-14 06:36 | 只看该作者
    谢谢分享

    “来自电巢APP”

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-24 22:05 , Processed in 0.156250 second(s), 23 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表