单片机原理和开发应用(13) 第十二讲 学习与实验(八)

🏠 首页 《无线电》杂志 1991年 🔗 第8期 🔗 第24页 分类:无线电技术自学经验交流 🔗 周振安 🔗

(周振安)8031单片机内都包含有一个全双工串行通信接口。利用该口可以同时发送和接收数据,实现双机或多机通信。本讲将着重介绍8031串行口工作原理及单片机与单片机、单片机与IBM-PC系统机之间的通信实验。

8031单片机串行口简介

8031单片机片内RAM(见1990年12期《无线电》)中有一个串行数据缓冲器SBUF,地址为99H,它用来暂存要接收或发送的数据。它实际上对应着两个寄存器:发送寄存器和接收寄存器。发送寄存器只能写入而不能读出,接收寄存器只能读出而不能写入。所以通过读、写指令可以很方便地访问这两个地址相同的专用寄存器,而不致混乱。

1.串行口的控制寄存器SCON(片内RAM的98H单元)

利用指令写入特定的控制字可以实现对串行口工作方式的控制。SCON可以直接字节寻址,也可以直接位寻址,其各位定义如下:

7D 6D 5D 4D 3D 2D 1D 0D

SMO SM1 SM2 REN TB8 RB8 TI RI

SM0、SM1为串行口工作方式选择位,定义见下表:

图1
图1 🔍原图 (874×463)

其中,波特率是指串行口每秒所发送或接收数据的位数。SM2:当串行口工作于方式2或方式3时,此位有其特定含义;当工作于方式0或方式1时,此位置0。REN为允许接收位,当REN为1时,允许接收;当REN为0时,禁止接收。TB8是发送数据位8,当串行口工作于方式2或方式3时,该位是要发送数据的第9位。在许多通信协议中,该位定义为奇偶校验位,或作为所发送信息的特征位,用来表示是地址帧还是数据帧。 RB8为接收数据位8,当串行口工作于方式2或方式3时,与TB8有相似的意义。在方式1中,若SM2为0,则RB8是已接收的停止位。TI是发送中断标志。当一帧信息发送完毕,由硬件自动置1,申请中断。当CPU响应中断后,首先由指令清除TI,然后发送下一帧信息。RI是接收中断标志,当接收完一帧信息后,由硬件自动置1,申请中断,请求CPU取走数据,并用指令清除RI。

2.工作方式简介:

1)方式0:在方式0状态下,串行口用作同步移位寄存器,其波特率是固定的(fosc/12),即波特率为晶振频率的1/12。数据由RXD(0P3)端输入、输出,同步移位时钟由TXD(1P3)端输出,发送、接收的均是8位数据,且低位在先,高位在后。利用方式0可以很方便地将串行口变成并行口使用。

2)方式1:在方式1中,串行口为8位异步通信接口,每帧信息为10位,其中有一位为起始位(低电平0)、8位数据位(低位在先)、一位停止位(1)。TXD为发送端,RXD为接收端,波特率可变,它取决于定时器1的溢出速率。

方式1发送和接收过程见图1时序图所示。在发送过程中,见图1(a),CPU每执行一条写入SBUF指令(MOV SBUF,A)使启动串行口发送;当发送完一帧信息时,发送中断标志位TI自动置1。在接收过程中,见图1(b),当允许接收标志让REN置1后,接收器便以波特率的16倍速率不断采样RXD端电平;当采样到1至0跳变时(起始位到来)便启动接收器接收8位数据。当接收到第10位的停止位(1)后,将停止位送RB8,8位数据进入接收缓冲寄存器SBUF,同时置位中断标志RI。实际上,在接收每一位数据过程中,将每一位的接收时间等分成16个计数状态,并在第7、8、9三个计数状态时采样接收端RXD,即每一位数据被采样三次,至少两次采样值相同才被确认。

图2
图2 🔍原图 (934×513)

3)方式2和方式3:方式2和方式3发送或接收的每一帧信息均由11位组成,一个起站位(0)、8个数据位(低位在先),一个可定义位(即第9位数据位)和一个停止位(1)。二者区别在于,方式2中波特率不变,方式3中波特率可变。过两种方式的接收和发送过程与方式1的相似。

3.波特率的设定

方式0和方式2中,波特率都是固定不变的;方式1和方式3中,波特率可变,这时波特率由定时器1的溢出速率决定:

(SMOD)

波特率=(定时器1的溢出速率)/32/2

其中SMOD是专用寄存器PCON(87H)的第7位,在此用来使波特率加倍,SMOD位不能位寻址,但可用字节操作指令进行置1或清0操作。

当定时器1工作在自动装载方式(方式2)时,TL1作计数用,TH1内放自动装载的值(计数初值),则溢出速率为:溢出速率=\(\frac{fosc/12}{256-(TH1)}\)。例如,当晶振频率fosc=6MHz,定时器1工作在方式2(自动装载方式),若要求波特率为1200位/秒,则TH1中应装入的定时初值计算如下:

(SMOD)

(SMOD)

(TH1)= 256-\(\frac{fosc*2}{32*12*波特率}\)=256-13.02*2

当(SMOD)=0时,(TH1)=242.98≈243=F3H,当(SMOD)=1时,(TH1)=229.96≈230=E6H。SMOD的取值可以任选,以误差最小为宜。例如,本例中取(SMOD)=0。

8031之间的双机通信实验

1.实验硬件:

本实验利用TD-I型机和TDII型机进行相互通信。当两个机器相距在1米以内时,可按图2将它们之间的有关连线直接相连,以实现全双工通信。

图3
图3 🔍原图 (571×283)

2.软件编写要点:

约定TD-Ⅰ型机发送,TD-Ⅱ型机接收,晶振频率均为6MHz,波特率为1200位/秒,串行口均工作在方式1,定时器1工作在方式2,计数初值取(TH1)=F3H。

发送程序编写要点(详见程序1):

1)设置一个待发送数据的数据存储区,首地址为0150H,存储区块长为80H。

2)串行口及定时器1进行初始化。

3)设置地址指针:

(3FH)←40H;设置接收端数据存放地址4000H的

(3EH)←00H;地址指针3FH、3EH

(3DH)←01H;设置发送端数据存放地址0150H的

(3CH)←50H;地址指针3DH、3CH

(3BH)←80H;块长指针3BH

4)呼叫信号为FFH,应答信号为00H。当应答成功后,先发送数据存放地址和长度。

5)数据发送采用中断方式。

接收程序编写要点(详见程序2):

1)串行口及定时器1初始化。

2)应答成功后等待接收。

3)地址与数据的接收均采用查询方式。

4)接收完毕,显示“good”。

3.实验步骤:

1)将TD-Ⅰ型机与TD-Ⅱ型机按图2连接。

2)通电后,将发送程序输入到TD-Ⅰ型机,控收程序输入到TD-Ⅱ型机。仔细检查,确认无误。

3)运行时,先运行TD-Ⅱ的接收程序,后运行TD-Ⅰ的发送程序。若TD-Ⅱ显示“good”,则通信成功,否则停止运行,仔细检查程序机器码。

4)通信成功后,按TD-Ⅱ的MON键使之停机,检查以4000H为首地址的80H个单元内容,看是否与发送端数据相一致。

5)改变波特率(两机要一致),例如都改为110(或者4800),对应的TH1初值为72H(或者FDH),再运行。

8031单片机与IBM-PC系统机的通信实验

1.实验硬件:

单片机与PC机通信时,必须要加电平转换电路。最典型的电平转换电路有1488、1489集成电路。图3是TD-Ⅰ型机(TD-Ⅱ型机)与PC机通信的接口电路图。对于拥有TD-Ⅲ型机的读者,由于该机已接有1488、1489芯片,实验时可参考图3右半部分1488、1489与PC机连线方法。实验时请注意,1488芯片需按+12V、-12V电源,无论采用那种机型,都别忘记加上这组电源。

图4
图4 🔍原图 (828×543)

2.实验软件:

本实验用TD-Ⅲ型机作为发送机,IBM-PC机作为接收机,本实验的发送程序与前一实验中的发送程序稍有差别:待发送的数据首先须变换成ASCII码才能发送;每发送完一个数据后,再送一个回车符的ASCII码(ODH)。

接收程序用高级语言Turbo BASIC编写,它在完成以下功能:按一定格式打开串行口,设置串行口数据的长度;建立一个数据文件,将接收的数据装入该文件。

发送、接收程序清单见程序3、程序4。

3.实验步骤:

1)按图3连接线路,加上+5V电源(±12V先不要加)。

2)输入发送程序到TD-Ⅲ型机中。

3)用Turbo BASIC编译系统启动IBM-PC机,输入接收程序,并在A驱动器中插入数据软盘。

4)先运行发送程序,再运行接收程序。A驱动器指示灯亮表示正在往A盘中写入数据,指示灯熄灭后表示通信结束,用“AIt+X”键退回到操作系统。

5)检查数据文件:键入“TYPEA:Z”并回车,屏幕显示00~98共100个两位十进制数。这里需要补充说明的是,有了数据文件,可利用高级语言对它进行进一步处理,因此本实验很有实际意义。如果手头没有Turbo BASIC编译系统,可改用其它系统软件,接收程序中的一些语句要作相应修改。
夿

程序1:发送程序(I型机通过);

1: ORG 0000H

2:0000 020040; LJMP MAIN

3: ORG 0023H

4:0023 020100; LJMP TRINT

5: ORG 0040H

6:D040 00 ; MAIN:NOP

7:0041 900150; MOV DPTR,#0150H,

写数据块内容

8:0044 7A80; MOV R2,#80H

9:0046 7400; MOV A,#00H

10:0048 F0; LOOPO: MOVX @DPTR,A

11:0049 04; INC A

12:004A A3; INC DPTR

13:004B DAFB; DJNZ R2,LOOPo

14:004D 758920; MOV TMOD,#20H;

T1,初始化

15:0050 758DF3; MOV TH1,#OF3H

16:0053 758BF3; MOV TL1, #OF3H

17:0056 D2AF; SETB EA

18:0058 D28E; SETB TR1

19:005A C2AC ; CLR ES

20:005C 753F40; MOV 3FH,#40H;

接收端数据块地址→3FH、3EH

21:005F 753E00; MOV 3EH,#00H

22:0062 753D01; MOV 3DH,#01H;

发送端数据块地址→3DH、3CH

23:0065 753C50; MOV 3CH,#50H

24:0068 753B80; MOV 3BH,#80H

块长→3BH

25:006B 759850; MOV SCON,#50H;

串行口初始化

26:006E 7599BB;START: MOV SBUF,#OBBH;

发送呼叫信号(BBH)

27:0071 3099FD;WAIT1: JNB TI, WAIT1

28:0074 0299; CLR TI

29:0076 3098FD;WAIT2: JNB R1, WAIT2;

等待接收回答信号(00H)

30:0079 C298; CLR RI

31:007B E599; MOV A, SBUF

32:007D 70EF ; JNZ START;

若未接收到回答信号,则继续呼叫

33:007F 853F99; MOV SBUF 3FH;发送地址

34:0082 3099FD;WAIT3: JNB TI,WAIT 3

35:0085 C299; CLR TI

36:0087 853E99; MOV SBUF,3EH

37:008A 3099FD;WAIT4: JNB TI,WAIT4

38:008D C299; CLR TI

39:008F 853B99; MOV SBUF,3BH;发送块长

40:0092 D2AC; SETB ES

41:0094 80FE; LOOP: SJMP LOOP;开中断(数据发送用中断方式)

42: ORG 0100H

43:0100 C299; TRINT: CLR TI

44:0102 C083; PUSH DPH

45:0104 C082; PUSH DPL

46: 0106 COEO; PUSH ACC

47:0108 853D83; MOV DPH, 3DH;

取数据地址

48:010B 853C82; MOV DPL,3CH

49:010E EO; MOVX A,@DPTR;

取待发送数据

50:010F F599 ; MOV SBUF,A;发送

51:0111 153B; DEC 3BH

52:0113 AA3B; MOV R2,3BH

53:0115 BA0002; CJNE R2,#00H,TRIN1;

发送完毕?

54:0118 8004; SJMP STOP

55:01lA 053C; TRIN1: INC 3 CH;未完,继续下一

字节

56:0llC 8004; SJMP RETUNE

57:0l1E C2AC; STOP: CLR ES

58:0120 C28E; CLR TR1

59: 0122 DOEO; RETUNE: POP ACC

60:0124 D082; POP DPL

61:0126 D083; POP DPH

62:0128 32; RETI

63:END

程序2:接收程序(II型机上通过):

1: ORG 3A00H

200 023AA40; LJMP RECE

3: ORG 3A23H

4:3A23 023A80; LJMP REINT

5: ORG 3A40 H

6: 3A40 758920;RECE: MOV TMOD,#20H;

T1k串行口初始化

7:3A43 758DF3; MOV TH1,#OF3H

8:3A46 758BF3; MOV TL1,#OF3H

9:3A49 D28E; SETB TR1

10:3A4B D2AF; SETB EA

11:3A4D C2AC; CLR ES

12:3A4F 759850; MOV SCON,#50H

13:3A52 3098FD;WAIT1: JNB RI,WAIT1;

等待接收标志

14:3A55 C298; CLR RI

15:3A57 E599: MOV A,SBUF

16:3A59 64BB; XRL A,#0BBH;

是呼叫信号(BBH)

17:3A5B 70F5; JNZ WAIT1

18:3A5D 759900; MOV SNUF,#00H;

发应答信号(00H)

19:3A60 3099FD:WAIT2: JNB TI,WAIT2

20:3A63 C299; CLR TI

21:3A65 3098FD;WAIT3: JNB RI,WAIT3;

接收地址高八位→3FH

22:3A68 C298 ; CLR RI

23:3A6A E599 ; MOV A,SBUF

24:3A6C F53F; MOV 3FH,A

25:3A6E 3098FD;WAIT4: JNB RI,WAIT4;

接收地址低8位→3EH

26:3A71 C298; CLR RI

27:3A73 E599; MOV A,SBUF

28:3A75 F53E; MOV 3EH A

29:3A77 3098FD;WAIT5: JNB RI,WAIT5;

接收数据块长度→3BH

30:3A7A C298; CLR RI

31:3A7C E599; MOV A, SBUF

32:3A7E F53B; MOV 3BH,A

33:3A80 3098FD;REINT: JNB RI, REINT;接收数据

34:3A83 C298; CLR RI

35:3A85 E599; MOV A, SBUF

36:3A87 853F83; MOV DPH, 3FH;

取数据存放地址

37:3A8A 853E82; MOV DPL, 3EH

38:3A8D FO ; MOVX @DPTR

39:3A8E 053E; INC 3EH;修正地址

40:3A90 153B; DEC 3BH

41:3A92 AA3B; MOV R2,3BH

42:3A94 BA00E9; CJNE R2, #00H,REINT;

接数完毕?

43:3A97 90381E; MOV DPTR,#381EH;

显示9000

44:3A9A 7410 ; MOV A,#10H

45:3A9C F0; MOVX @DPTR,A

46:3A9D A3 ; INC DPTR

47:3A9E F0; MOVX @DPTR,A

48:3A9F 7413 ; MOV A,#13H

49:3AA1 A3; INC DPTR

50:3AA2 F0; MOVX @DPTR,A

5l:3AA3 7412; MOV A,#12H

52:3AA5 A3; INC DPTR

53:3AA6 F0; MOVX @DPTR,A

54:3AA7 A3; INC DPTR

55:3AA8 F0; MOVX @DPTR,A

56:3AA9 740D ; MOV A,#0DH

57:3AAB A3; INC DPDR

58:3AAC F0; MOVX @DPTR,A

59:3AAD123AB3;LEDI: LCALL DIS

60:3AB0 023AAD; LIMP LEDI

61:3AB3 22; DIS: RET

62 : END

程序3(TD-Ⅲ发送程序):

ORG A000H

A000 909000; MOV DPTR,#9000H;在以9000H为首地址的连续100个单元

A003 7400 ; MOV A,#00H

A005 7A64 ; MOV R2,#64h

内存入0~100数据的BCD码

A007 F0 ;DAT:MOVX @DPTR

A008 2401 ; ADD A,#01H

A00A D4 ; DA A

A00B A3 ; INC DPTR

A00C DAF9 ; DJNZ R2,DAT

A00E 758920; MOV TMOD,#20H

定时器1初始化

A011 758DF3: MOV TH1,#OF3H

A014 758BF3; MOV TL1,#OF3H

A017 C2AF ; CLR EA

A019 D28E ; SETB TRl;启动定时器1

A01B 909000; MOV DPTR,#9000H;

DPTR指向数据源地址

A01E 759850 ; MOV SCON,#50H;

串行口初始化

A021 3098FD;T1: JNB RI, T1;等待发送

A024 C298 ; CLR RI

A026 E0 ;T2: MOVX A,@DPTR ;取数据

A027 F5F0 ; MOV B,A

A029 54FO ; ANL A,#OFOH;先发送高半字节

A02B C4 ; SWAP A

A02C 2430 ; ADD A,#30H;变成ASCll码

A02E F599 ; MOV SBUF,A ;发送

A030 3099FD;T3: JNB T1,T3

A033 C299 ; CLR TI;等待发送结束

A035 E5FO ; MOV A B;取低半字节发送

A037 540F ; ANL A,#OFH

A039 2430 ; ADD A,#30H

A03B F599 ; MOV SBUF,A

A03D 3099FD; T4: JNB TI, T4

A040 C299 ; CLR TI

A042 740D ; MOV A,#ODH;发送回本符

A044 F599 ; MOV SBUF

A046 3099FD;T5: JNB TI,T5

A049 C299 ; CLR TI

A04B A3 ; INC DPTR;取下一字节数据

A04C A882 ; MOV RO, DPL

A04E B864D5; CJNE RO, #64H, T2;

判100字节发送完毕否?

A051 75790F; MOV 79H, #0FH;

发送结束,显示器最低

A064 75780F; MOV 78H, #OFH

A057 12045O; LCALL DIS;二位显示“FF”

A05A 80FE ;T6: SJMP T6

程序4 (IBM-PC接收程序):

10 open“coml:1200,n,8,1,rs,cs,ds,cd:lf as#1;打

开串行口,并初始化

20 ¥coml 4096;设置串行口数据缓冲区长度

30 open“a: z”for output as#2;在a盘打开一个名为

z的数据文件

40 print#1,n;通知对方发送

50 close#2

60 for i=1to 200

70 oped“a: z”for append as#2;将串行口接收到的数

据存到z文件中

80 input #1, a¥

85 a=val(a¥)

90 print#2, usins“####”; a;每个数据占4位

100 close# 2

110 next i

120 close #1;传送结束,关闭串行口

130 end