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

串口多机通讯及实例

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
在多机通信过程中,所有设备的 RS232接口是并在通信线上的,其中只能有一个设备为主机,其他为从机,通信由主机发起。数据帧一般采用1位起始位、9位数据位,其中第9位(RXB8)被用作为表征该帧是地址帧还是数据帧。当帧类型表征位为“1”时,表示该帧数据为一个地址帧;当帧类型表征位为“0”时,表示这个帧为一个数据帧。
      在AVR中,通过设置从机的UCSRA寄存器中标志位MPCM,可以使能USART接收器对接收的数据帧进行过滤的功能。如果使能了过滤功能,从机接收器对接收到的那些不是地址信息帧的数据帧将进行过滤,不将其放入接收缓冲器中,这在多机通信中有效的方便了从机mcu处理数据帧程序的编写(同标准51 结构相比)。而发送器则不受MPCM位设置的影响。
# i* C1 t' D5 {6 Y  T* |      多机通信模式允许多个从机并在通信线路上,接收一个主机发出的数据。通过对接收到的地址帧中的地址进行解码,确定哪个从机被主机寻址。如果某个从机被主机寻址,它将接收接下来主机发出的数据帧,而其它的从机将忽略数据帧,直到再次接收到一个地址帧。(从机地址是由各个从机自己的软件决定的)。* X8 p" |1 z" ~+ l3 ~* W* Y
      对于在多机通信系统中的主机MCU,可以设置使用9位数据帧结构(UCSZ=7)。当发送地址帧时,置第9位为“1”;发送数据帧时,置第9位为 “0”。在这种情况下,从机也必须设置成接收9位数据帧结构。
0 Y/ A6 i) Q# ~1 |8 C' a     多机通信方式的数据交换过程如下:
4 U' M/ D) }5 a1)设置所有从机工作在多机通信模式(MPCM=1)。
; q  Z+ M! z6 N- n2) 通信开始是由主机先发送一个地址帧,如8位数据为0X01(1号从机地址),第9位=“1”,呼叫1号从机。
& n9 v8 a! m$ f" k$ r3 `9 q0 a3)所有从机都接收和读取该主机发出的地址帧。在所有从机的MCU中,RXC标志位被置位,表示接收到地址帧。
' }7 I) A7 K9 \4 p4)每一个从机MCU读UDR寄存器,并判断自己是否被主机寻址。如果被寻址,清UCSAR寄存器中的MPCM位,等待接收数据;否则保持MPCM为 “1”,等待下一个地址帧的接收(该步应由用户软件处理实现):
( K$ a% U+ h# Q( H( D! xA)作为1号从机的MCU处理过程为:收到地址帧后,判定读取UDR数据0X01为自己的地址,将MPCM位置“0”,接收之后所有主机下发的数据帧,直到下一个地址帧为止。
8 }; T& `. R1 {4 m/ j  p* _( ~B)其它从机MCU的处理过程:收到地址帧后,判定读取UDR数据0X01不是自己的地址,将MPCM位置“1”,这样他们将忽略主机随后发送的数据帧,直到主机再次发送地址帧。
) }5 g+ ]1 @7 A5)当被寻址的从机MCU接收完最后一个数据帧后,将MPCM位置位,等待下一个地址帧的出现(该步也应由用户软件处理实现),然后从步骤2开始重复。
[转]例子;
通讯规则:# f, p  J" L) b& V9 q, t. {1 t. a
1:时钟7.3728 MHz/波特率9600/9个数据位/奇 校验/1个停止位/硬件多机通讯功能/3 E+ r, u* f5 N/ j/ |( |0 }% U
2:通讯连接采用硬件MAX485,双向单工- I$ Y9 v0 M; B
3:每个上行/下行的数据包的字节个数都是一样的(通讯数据量)
: L- Z5 `* d4 T- Y3 w4:每个上行/下行的数据包都采用CRC8校验
3 \% ?& a0 Z* l5 i- T0 s7 ?5:数据接收采用中断+查询的方式
9 j, m. L+ p5 s" T* n" [- k; l6:总是由主机向从机发送一个数据包,从机收到数据包后向主机回复一个数据包' h7 l% N; z4 Y/ \) B: ?" l
7:不管是主机还是从机,如果收到的数据包有任何错误,都将丢弃该数据包,等 效于没有接收% K' ?5 q# X( V/ Z! i: X$ m
8:从机之间不能相互通讯,必须通过主机才能交换数据1 j9 H! F/ Y9 t0 J$ _+ B! I8 s* y
9:无效地址是0,主机地址是1,从机地址是2.3.4......广 播地址是255. ^7 V& l/ Q3 T0 z
*/8 @3 |# u: u( T, ~' r+ c$ ^
#include
* D! q3 b/ M5 [6 W2 z# |! B0 g: W#include
; W7 V2 X( u# t7 G& r2 N; v% p3 {#include * O( d, H" o7 p
#include //CRC校验函数就在这个文件里面4 M" B$ B' m( r0 z1 J: h( k

$ _8 ]. G+ u( C9 C6 W2 _9 r#define amount 10 //设定通讯数据量(包括1个 地址帧,n个数据帧,1个校验帧), A/ n$ ?- H7 Z1 P# ~
" b, w% j* D+ \1 Q
unsigned char send[amount]; //发件箱
) ~4 W" j9 M! ^) eunsigned char inbox[amount]; //收件箱
7 H$ y) H' j& O: E) M/ ?0 V) runsigned char n=0; //记忆中断次数8 x9 Q1 i) R& k; G0 ^6 \3 V8 X

; k; l8 j5 Y: E" Y/ G5 [//--------------------------------------------------------------------
0 E- n. P# b. einterrupt[12] Rxd_isr(void) //接收中断) F- P4 E  a( B7 S: E
{
' O5 r! W: E8 L8 e3 Iunsigned char ERROR=0;; g$ [% c! p) }! K% r7 l
if( UCSRA&4 || UCSRA&16 ) ERROR=1; //奇偶效验错误或者帧错误就记录下来( a) V; D; l4 n* r
inbox[n]=UDR; //保存到收件箱& U9 b) i5 z0 _+ O
n++; //记忆中断次数: ^! p) S: [) @; X
if(ERROR) inbox[0]=0; //如果通讯有错,收 件箱的地址帧就标记成无效地址0
1 R; l2 k- W/ N, T0 U: z}
. X4 V3 ]7 O: ~# R  D# E; j
3 ^; \! k8 R: I2 O5 c/ C; M! l//---------------------------------------------------------------------: E) f# o) |7 ]
void main(void)
! Z6 P- @, e" v7 A, ~3 W# ~8 A& }{
7 Y5 ~. a5 i5 a9 lusart_init(); //串口初始化5 U  M2 X% q7 H7 Z' B
UCSRA=0; //主机关闭地址筛选功能(多 机通讯功能)
; E$ C( p9 K$ N& X' X#asm("sei") //打开全局中断0 X& z' e3 A. r5 J
while(1)
3 E1 P7 e; e( y{
5 I. M3 W' m1 v  {//-------------与从机2对话,与其他从机对话与下面的 程序类似-------------------' I9 v0 O- E9 ?- {) m
n=0; //中断次数清0
9 y/ Q! Y$ \3 I$ ?6 cinbox[0]=0; //收件箱地址清04 I- p2 V, L: y5 o8 Y
//请更新准备发送的数据
4 Y1 R$ H% \; E  B//send[1]=?% f& d5 b/ o, t# L2 R+ v' l
//......
0 A+ ]% f5 J* M9 w//send[n]=?
  n" m4 I' m0 C  k9 `& j9 Rsend[0]=2; //改变这个地址就可以实现与某个从机对话
/ m8 c- |5 U# L* O3 g; v6 P' Ysend[amount-1]=crc8(send,amount-1); //计算发件箱的crc8校 验码
6 J. f' y" m6 `usart_out(send,amount); //将发件箱的数据send[]发 送出去;
+ m& |7 @- K+ l( \: b
9 j; x: c( y% ]+ l//等待,从机接收到数据后会回复数据的,如果是10个 字节数据量,不能少于13ms!!!9 `* R) D# l. |/ ^- Y$ y& n3 q
//这个时间由人工计算,要考虑从机由于各种中断延长回复时间的可能
, ^) @5 _7 M1 m% v; G, f! w9 x9 B- D: {2 E7 y  k
delay_ms(15);, Q- Y  X" l' P4 ]
  |1 Q2 `1 \( Y) p7 `0 C6 {* V$ q
//if(n<3)如果接收到的数据还不到3个,那么就是通讯线路故障
* B  j5 p- @# ~, u6 K4 {
) v2 T' Y- G/ e$ r8 m//如果收件箱已经收到amount个数据,并且crc8校 验成功就...* d' ~; C7 L% q' K, _' x8 R
if(n==amount && inbox[amount-1]==crc8(inbox,amount-1))- j+ z; I1 k8 Y. ]& ?4 P+ Z
{+ F; S( U- h0 o; `! d6 }$ i, a% L8 `
if(inbox[0]==1) //如果收件箱地址帧属于本机就运行下面的测试 代码
/ E: _: a8 {$ W, s{
. W/ Z: @, S* j; Q' }# G+ iDDRD.3=1;
; G* U! m/ _- e5 }: m( z# WPORTD.3=1; delay_ms(10);
! s6 X9 s# `1 D  {  OPORTD.3=0; delay_ms(990);9 }7 v" T/ M7 z" }/ t5 [3 X
}: s, \" Y! q2 R" J4 X

; }# V% x0 ]; F: \: |% [, Gif(inbox[0]==255)4 L9 }' ~2 ?" I
{
, d) j; [1 C# l5 H2 T% v7 z2 y! z- v//请在这里添加收到广播数据的处理程序
, j' C) V8 l- A! A7 v7 k7 `( F7 `}
% R4 ~4 A. L' p  c" m! w}
+ _3 \, T- \9 h}- o1 d/ p. @- c" b2 k0 B
} //end
  {3 q0 ]2 P3 |6 @, K8 {7 Z2 C8 @" T3 _; i+ Q" e6 |0 O" {+ q5 g
---------------------------------------------------------------------------------- {& I5 f# W3 W3 \) ^7 N
从机, G% }& G; c3 b: Z( [, Q% k/ j* K
---------------------------------------------------------------------------------
2 N8 z5 i' C9 X, |' u#include
7 a- H5 N; S) x4 p#include ; Q1 a: f3 l& m, B4 \  k+ k
#include $ T+ D* I3 B' ^$ c

+ N+ N0 O4 b' ?. b/ Q#define amount 10 //设定通讯数据量(包括1个 地址帧,n个数据帧,1个校验帧)
% L- q2 b% \: {6 F#define address 2 //请在这里设定本机地址; @2 l9 o+ @* J9 M+ g

" }  `- }3 O1 w0 ]unsigned char send[amount]; //发件箱7 S. C, i# [4 b/ C
unsigned char inbox[amount]; //收件箱
4 t% Y- G4 q/ Funsigned char n=0; //记忆中断次数
% p) _. ~! t" u6 o8 H. F2 W& N7 k- V0 s8 g$ Q0 t% j
interrupt[12] Rxd_isr(void) //接收中断
6 u3 U# P5 ]. B& M) m0 V{# }" |& y& v" @
unsigned char ERROR=0;2 r8 T$ L  Q$ o6 Y
if( UCSRA&4 || UCSRA&16 ) ERROR=1; //记录 奇偶效验错误或者帧错误
' N1 M7 K* a5 q+ j1 r2 w; Sinbox[n]=UDR; //把接收到的数据保存到 收件箱1 ~- C5 H3 D& X6 |( m" e. S0 {
n++; //记忆接收的次数0 T* w7 {; Y( Q0 U" F( q, o# l$ t
if(ERROR) //如果通讯有错....5 X7 R+ `) R9 N% q' ?: l5 C
{6 S. g$ D. [/ Z6 T0 K
n=0; //接收计数清0
8 @0 N; S6 f! D3 y% Hinbox[0]=0; //把地址改为无效地址0
  F- U( w" m0 B  c( {9 o4 l* NUCSRA|=0x01; //重新打开接收器的地址 帧筛选功能5 `0 a& _5 m; f; Q; K- n* p4 r$ a
}8 `2 L( J; B% t) k2 M3 C

  |# [3 r" g( J4 {- [//如果地址匹配本机或者是广播地址就关闭地址筛选(多机通讯)功能
. E1 S9 A8 ^: Y! m( M2 Kif(inbox[0]==address ||inbox[0]==255) UCSRA&=254;
5 E; U$ n9 y; p! R
/ S0 X3 D7 Z0 F% }8 Q/ Z0 Bif(n==amount) //接收到amount个 数据以后...$ D& R( }) L, m. h! u2 g- z5 X
{) t2 J, p( q- Z  Q; c5 a0 U; h
n=0; //接收计数清0
( Z. x) _; E/ B! iUCSRA|=0x01; //重新打开接收器的地址 帧筛选功能
7 o) h' J0 x/ yif(inbox[amount-1]==crc8(inbox,amount-1)) //如果crc8校 验正确就...) u7 i7 }+ c4 @3 [! v& K
{; l$ U$ X& {. {* o0 Y: F# j  T' W
if(inbox[0]==address) //如果地址匹配本机就回 复数据
* w* u* j$ a/ A* V{. o* g6 b  |0 {& H
send[0]=1; //发件箱地址指向主机
/ H, P( C0 V; {- C2 H# o3 Lsend[amount-1]=crc8(send,amount-1);//产生发件箱的crc8校 验码
0 y: [2 K- A- h, I) Z% z# ?& M2 Eusart_out(send,amount); //发送发件箱的数据包send[]
2 F6 M) [! N2 y- S//请在这里备份你的收件箱信息( p& S" H. a+ ]$ p- i+ X) v7 w
}4 ^# R$ t5 B5 g% ~6 H
if(inbox[0]==255) //如果是广播地址就...
; v# h$ ]9 e- x5 y8 P  i! s{
8 r  q) ~( Z" ?9 z) w) V% y' K# k2 _//请在这里添加你的代码+ U. J# i+ |# n% K1 T" F
//收到广播数据请不要回复
  ?/ |) D& F; L+ c}
5 W4 H/ i' _, @# B% C}/ V4 x. K; h6 h2 k9 h' B4 b
}
1 T$ V( F/ W4 N5 }+ V3 l}
5 i+ c# E4 b2 {6 t1 q0 u
, F4 [7 G4 {5 C$ V; ?void main(void)
( J5 @. t. x5 a- S3 K# b0 ~{# d# s! y. c4 x: Y1 r+ r! [. x
usart_init();0 x5 k8 `/ Y- E+ m6 l$ `, Y
#asm("sei"). w$ T: m% a3 h( B
" _2 U& h$ Q5 X0 J2 O  A
while (1)
# L* g4 H8 @+ k  X{
! f( R& r* D9 p# Y5 [9 f. F//send[1]=?+ ~' c! I8 F, L, V
//......
( [( q! A; `' Q8 A3 C//send[n]=?! c; P9 X9 a1 }0 j  g9 O
};
9 V/ M" C! O' \2 y2 y}
, n" e; `) K, L. p( M, Z# [0 {- ?$ N# B& l, c

: e2 {0 {  e. k. R# I9 R---------------------------------------------------------------------------------. y: J& g& O& P7 I
usart.h文件6 |2 o- N3 z7 D4 \$ Z* q
---------------------------------------------------------------------------------; x3 C. A8 W+ ?$ s( o
//波特率9600/9个数据位/1个停止位/奇校验/收 发开启/接收中断  o4 b' Q8 h; x/ c# j! }
void usart_init(void)2 `* f" j! L8 I* J  F1 N. L
{
! P) v( F7 |, R) j! ^8 KUCSRA=0x01;
# t+ d. m/ ~0 ]2 Y- a$ t! ^UCSRB=0x9C;4 ]& l. n, i% ^0 L8 j7 X8 z
UCSRC=0xB6;" L) m/ D$ ~, F
UBRRH=0x00;" R; C. b+ g2 \+ s5 h/ K$ V; R
UBRRL=47;
. s" e+ v1 [$ `' ~$ ?
6 ~0 ?5 D. Q  u2 y$ i9 wPORTD.4=0; //MAX485平时工作在接收状态; d) ?8 y6 t! l* w
DDRD.4=1;9 M. S5 g* z+ }' Z
}: f/ |8 `( S' f
2 Z( R' u- `+ x& P8 }* ]
//-----------------------------------------------------------7 j$ w' b; k. ?2 y, ]% x/ h1 U7 g
//从数组datas[]的首地址开始发送amount个数据,其 中第0个数据是地址帧,其他是数据帧  s5 n0 _9 B, A9 e/ S8 J
void usart_out(unsigned char *datas,unsigned char n)" J6 ^3 h- z" m) b1 j; P! \
{
4 I9 d7 \% q$ J0 D9 }unsigned char i=0;% P: ?+ U0 C! S. U6 k+ m
PORTD.4=1; //使MAX485处 于发送状态5 L$ {) {7 `& e3 m( V$ d7 L
while(i {- Y. S7 U* e" S- t
if(i==0) UCSRB|=1; else UCSRB&=254;
: J  F! c" ]+ D- E/ lUDR=*(datas+i); //装载数据开始发送7 ]0 m( h( w' p
while((UCSRA&64)==0); //等待发送结束
( ?. K! [; v" OUCSRA|=64; //清除发送结束标志
* W1 o% b& R" C! }" J+ z4 Li++; //发送次数统计
% b$ T  x7 q- d0 u}
, {5 ^, ^) d; A* IPORTD.4=0; //使MAX485处 于接收状态0 P4 H  F: l3 f5 l. S; l+ a
}/ F1 Z7 L4 A* d; V; Z9 Z

5 d0 p% N+ w2 P6 V, g---------------------------------------------------------------------------------3 S  m  v! a8 x, {7 a
crc8校验程序
& a' Z* P' v$ U3 I: J. r# D! j---------------------------------------------------------------------------------
9 o7 Q% n5 K* Q, V# Funsigned char crc8(unsigned char *ptr, unsigned char len)3 J6 R# V7 _' d5 L- J! p
{7 x; Q7 L4 K0 ^. f4 N
unsigned char i;1 l1 Y/ W9 O0 R' r( `7 s' ]
unsigned char crc=0;
! t. g8 N( G6 k; o% N4 u  nwhile(len--!=0)
! b# r1 U' j* v3 v{
" F  K3 m4 T1 r+ }4 ^8 z1 ^4 G6 \for(i=1; i!=0; i*=2)
4 }& Z: Y& u) u/ C& Y{
9 b& ^3 p" c' Z# \8 y$ p2 Jif((crc&1)!=0) {crc/=2; crc^=0x8C;}
9 i: S5 P/ ]3 [! w) b0 w# j; Jelse crc/=2;. g- F/ z. _; {/ U. I
if((*ptr&i)!=0) crc^=0x8C;/ j% S& m8 [- {- Q' X9 P! d
}. @% L; r. e; E) _1 Z  ?( ]* v/ d
ptr++;; ^1 `: g6 _" T% W/ ]
}
: O; t) n& x2 |' D: C; `1 \! Kreturn(crc);
3 Y# z7 E6 Y( y4 T8 C+ x0 h8 x- B}
' e2 r5 m! Q- c( U+ \2 R
  • TA的每日心情
    开心
    2019-11-21 15:51
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2020-10-12 15:45 | 只看该作者
    多机通信模式允许多个从机并在通信线路上,接收一个主机发出的数据。通过对接收到的地址帧中的地址进行解码,确定哪个从机被主机寻址。如果某个从机被主机寻址,它将接收接下来主机发出的数据帧,而其它的从机将忽略数据帧,直到再次接收到一个地址帧。(从机地址是由各个从机自己的软件决定的)。
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

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

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

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

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