★7.3.5  单片机与微机的串行通信

★7.3.5 单片机与微机的串行通信

1 单片机与PC的串行多机通信

主从式通信系统:一主机+多从机;每个从机都被赋予唯一的地址。一般还要预留1~2个“广播地址”。主机与各从机之间能实现双向通信,而各从机之间不能直接通信,只能通过主机才能沟通。

978-7-111-54295-7-Chapter07-49.jpg

图7-25 多机通信系统示意图(1)

(1)单片机与PC多机通信原理

串行接口控制寄存器SCON中的SM2为多机通信接口控制位,串行接口以方式2或3接收时,若SM2=1,表示置多机通信功能位,这时出现两种可能情况。多机通信系统示意图如图7-25所示。①接收到的第9位数据RB8为1时,数据才装入SBUF,并置位RI=1,向CPU发中断请求;②接收到的第9位数据RB8为0时,则不产生中断,信息抛弃。

各从机初始化:MOV SCON,#0B0H;或#0F0H

主机发送信息:其中第9位数据TB8作为区分地址/数据的标识。TB8=1表示地址,TB8=0表示数据。例如,主机发送地址帧信息02H,02H是从机2的地址。多机通信系统示意图如图7-26所示。

978-7-111-54295-7-Chapter07-50.jpg

图7-26 多机通信系统示意图(2)

各从机响应中断,在中断程序中判断接收到的地址与本机是否相符,相符则SM2=0,不符则保持SM2=1不变。发送的数据帧,因RB8=0,只有SM2=0的从机可接收,进入中断处理。多机通信系统示意图如图7-27所示。

(2)多机通信关键

主机第1次发出的地址信息要能被所有的从机响应,而第2次的数据信息只能被n#从机所响应——多机通信控制位SM2对接收中断请求的管理功能。

978-7-111-54295-7-Chapter07-51.jpg

图7-27 多机通信系统示意图(3)

例7-6:设一主机与多台从机进行通信,通信各方的晶振频率为11.0592MHz,波特率发生器采用定时器2实现。

解:假定各从机地址号分别为01、02、03,主机循环选定各从机进行通信。发送前,在P2口显示所呼叫的从机机号,主机发送的数据包格式为:从机以中断方式接收主机发送的首字节,然后在中断服务程序里用查询方式接收数据包的后续字节。收到完整数据包后,判别数据包里的从机机号与本机机号是否匹配,并校验和是否正确。若两条件均成立,则回送应答信息0xA0与本机机号之和,同时将本机机号送P2口显示,表示主机正在与该从机通信;若两条件不同时成立,则将0xFF送P2口显示,表示本机空闲。主机收到应答后,在P2口显示应答信息。

初始化:串行接口工作在方式3,允许接收,则SCON=0xF0。T2CON格式如下所示:

978-7-111-54295-7-Chapter07-52.jpg

T2作为波特率发生器,则T2CON=00110100B=0x34。

可得T2计数初值:波特率为9600bit/s,则(RCAP2H,RCAP2L)为0FFDCH。

2 PC与单片机的点对点通信设计

(1)硬件接口电路

在功能比较复杂的控制系统和数据采集系统中,一般常用PC作为主机,单片机作为从机,如图7-28所示。单片机通过串行接口与PC的串行接口相连,将采集到的数据传送至PC,再在PC上进行数据处理。由于单片机的输入/输出是TTL电平,而PC配置的都是RS-232标准串行接口。由于两者的电平不匹配,必须将单片机输出的TTL电平转换为RS-232电平。

978-7-111-54295-7-Chapter07-53.jpg

图7-28 PC与单片机的点对点通信

(2)PC与多个单片机的串行通信接口程序设计

在工控系统(尤其是多点现场工控系统)设计实践中,单片机与PC组合构成分布式测控系统是一个重要的发展方向。PC与单片机间的通信采用主从方式,PC为主机,单片机为从机,由PC确定与哪个单片机进行通信,如图7-29所示。

978-7-111-54295-7-Chapter07-54.jpg

图7-29 PC与多个单片机的串行通信接口

例7-7:甲机键盘输入,波特率为1200bit/s,乙机LED数码管显示输出,接发双机数据分别完成双机串行通信。

解:(1)甲机程序(键盘输入、发送,接收乙机发来数据)

ORG 0000H

SJMP STAR

ORG 0030H

STAR:MOV SCON,#50H;设置串行接口方式1,允许接收

MOV TMOD,#20H;设计定时器1工作方式2

MOV PCON,#0H;波特率不加倍

MOV TH1,#0E6H;12MHz晶振频率,波特率1200bit/s

MOV TL1,#0E6H

SETB TR1;启动定时器1

CLR ES;禁止串行接口中断

MOV SP,#5FH;设置堆栈指针

MOV P2,#0H;数码管显示“8”,P1.0~P1.3为列,P1.4~P1.7为行

KEYS:MOV R0,#4;键盘扫描和数码管显示子程序

MOV R1,#11101111B;行扫描,从0行开始扫描

MOV R2,#11111111B;(R2)=0FFH,假设未按键

SNEXT:MOV A,R1;送出行扫描码

MOV P1,A

MOV A,P1;读键状态

ORL A,#0F0H

CJNE A,#0FFH,KEYIN;判断是否按键

MOV A,R1;未按键盘继续扫描下一行

RL A;修改行扫描数

MOV R1,A;保存行键扫描数

DJNZ R0,SNEXT;4行未扫描完,循环

LJMP KEYS;循环查键

KEYIN:MOV R2,A;键盘状态保存在R2

ACALL DLY;除按键抖动并等待按键弹起

NOPEN:MOV A,P1;读入键盘状态

ORL A,#0F0H

CJNE A,#0FFH,NOPEN;键未弹起,转NOPEN等待弹起

LCALL DLY;延时消键弹起抖动

LCALL KEYV;将扫描码转成按键码

MOV SBUF,A;发送

JNB TI,$;等待一帧发送完毕

CLR TI;清发送中断标志

CLR RI;清接收中断标志

ACALL DLY;调用延时

MOV A,SBUF;接收乙机的数据

JNB RI,$;等待接收完一帧数据

CLR RI ;清接收中断标志

LCALL SEG7;乙机的数据转成显示码

CPL A;取反为共阳段码

MOV P2,A;显示按键值

LJMP KEYS;重新扫描按键

DLY:MOV R7,#30;延时15ms(12MHz晶振频率时)

MOV R6,#0

S1:DJNZ R6,$

DJNZ R7,S1

RET;延时子程序返回,求键值子程序KEYV,P1.0~P1.3为列,P1.4~P1.7为行

KEYV:MOV B,#0;(B)=按键码,预设为0

MOV A,R2;判断目前是哪一列?

C1:RRC A

JNC C2;按键在当前列,转C2

INC B;按键不在本列,(B)+4,因为每一列按键码相差4

INC B

INC B

INC B

LJMP C1;返回继续判断按键在哪一列

C2:MOV A,R1;(A)=(R1),行扫描码

RR A;右移4位,将高4位移到低4位,以便后续的判断

RR A

RR A

RR A

C3:RRC A;判断哪一行被按下

JNC C4;在当前行,转C4

INC B;非当前行,键值+1(每一行每个按键差1)

LJMP C3

C4:MOV A,B;(A)=(B)按键码给A

RET;键值判断子程序返回

SEG7:INC A;将键值转换为共阴显示码

MOVC A,@A+PC

RET

DB 03FH,06H,5BH,4FH,66H,6DH,7DH,07H;共阴数码管显示0~7

DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H,03FH;共阴数码管显示8~F,0

END;程序结束

(2)乙机程序(接收由甲机发来的数据并显示在数码管上,加1后再发送到甲机)

ORG 0000H

SJMP STAR

ORG 0023H

LJMP LOOP;通信中断服务程序入口

ORG 30H

STAR:MOV R7,#50H

MOV SP,#5FH;设置堆栈指针

MOV P2,#0H;开始,显示“8”

MOV SCON,#50H;设置串行接口方式,REN=1允许接收

MOV TMOD,#20H;定时器1方式2

MOV PCON,#0H;波特率不加倍

MOV TL1,#0E6H;晶振频率12MHz时的初装值

MOV TH1,#0E6H

SETB TR1;启动定时器1

SETB EA;中断总允许

SETB ES;开串行中断

SJMP $

LOOP:LCALL S_R

LCALL S_T

RETI

S_T:CLR TI;清发送中断标志

MOV SBUF,10H

JNB TI,$

CLR TI

RET

S_R:MOV A,SBUF;接收数据

JNB RI,$;等待接收完一帧数据

CLR RI;清接收中断标志

MOV 10H,A

INC 10H;将接收到的数据加1后再回发到甲机

ACALL SEG7;调显示子程序

CPL A

MOV P2,A

RET

SEG7:INC A

MOVC A,@A+PC

RET

DB 03FH,06H,5BH,4FH,66H,6DH,7DH,07H;共阴数码管显示0~7

DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H;共阴数码管显示8~F

END;程序结束