ToC

实验内容

通过 E 命令修改内存 3000H 的内容,发送到串口,然后自接受保存到 4000H 起始的内存单元中。

最后通过系统命令查看相应存储空间的数据,验证传输结果。

实验接线

通过 8254 控制波特率,将 TXDRXD 相连以自收发。

代码

DATA8251 EQU 0600H

CON8251 EQU 0602H

C028254 EQU 06C4H

CON8254 EQU 06C6H

SSTACK SEGMENT STACK

DW 64 DUP(?)

SSTACK ENDS

CODE SEGMENT

ASSUME CS:CODE

START PROC

;; INIT 8254

MOV DX, CON8254

MOV AL, 10110110B ;; MODE 3, SQUARE

OUT DX, AL

;; CLK2 CONNECTED TO 1.8432MHz

;; OUT2 CONNECTED TO 8251-TRCLK

;; 1.8432E6/0X000C/16 = 9600BPS

MOV DX, C028254

MOV AL, 0CH

OUT DX, AL

MOV AL, 00H

OUT DX, AL

;; INIT 8251

CALL INIT

MOV DX, CON8251

MOV AL, 01111110B ;; ASYNC METHOD CONTROL WORD

;; 01: ONE BYTE ESD/S1

;; 11: EVEN JUDGE

;; 11: 8 BYTES

;; 10: 16

OUT DX, AL

CALL DELAY

MOV AL, 00110100B ;; ASYNC COMMAND WORD

;; 0: DISALLOW SEARCH

;; 0: NO RESET

;; 1: REQUEST SEND

;; 1: RESET ERROR FLAG

;; 0: NORMAL WORK

;; 1: ALLOW RECEIVE

;; 0: DATA CONSOLE NOT PREPARED

;; 0: DISALLOW SEND

OUT DX, AL

CALL DELAY

MOV DI, 4000H

MOV SI, 3000H

MOV CX, 10

LO:

MOV AL, 00110111B ;; ASYNC COMMAND WORD

;; DIFFERENCE: ALLOW SEND

MOV DX, CON8251

OUT DX, AL ;; PREPARE 8251

MOV DX, DATA8251

MOV AL, [SI]

OUT DX, AL ;; SEND [SI] BYTE

MOV DX, CON8251

LO_SEND:

IN AL, DX ;; WAIT FOR SEND BUFFER TO BE EMPTY

AND AL, 1

JZ LO_SEND

LO_RECV:

IN AL, DX ;; WAIT FOR RECV BUFFER TO HAVE DATA

AND AL, 02H

JZ LO_RECV

MOV DX, DATA8251

IN AL, DX ;; RECEIVE FROM 8251

MOV [DI], AL ;; SAVE TO [DI]

INC DI

INC SI

LOOP LO

FIN:

JMP FIN

MOV AX, 4C00H

INT 21H

START ENDP

INIT PROC

PUSH AX

PUSH DX

MOV AL, 00H

MOV DX, CON8251

OUT DX, AL

CALL DELAY

OUT DX, AL

CALL DELAY

OUT DX, AL

CALL DELAY

MOV AL, 40H

OUT DX, AL

CALL DELAY

POP DX

POP AX

RET

INIT ENDP

DELAY PROC

PUSH CX

MOV CX, 0FFFFH

LOOP $

POP CX

RET

DELAY ENDP

CODE ENDS

END START

实验过程

设置内存

4000H

3000H

选做实验

说明

a-zASCII 码写入 3000H,然后通过 9600 的波特率传输到 4000H

当出现错误时停止传输,并将状态字显示在数据灯 D7-D0 上。

接线

接线有点混沌,反正能用就行(

由于数据线低位不够用了,所以我把 8255 接到了数据线高位(D8-D15),对应的 OUT 也就需要输出 AX 而非 AL 了。

总之就是下面这个样子:

代码

DATA8251 EQU 0600H

CON8251 EQU 0602H

C028254 EQU 06C4H

CON8254 EQU 06C6H

B8255 EQU 0642H

CON8255 EQU 0646H

SSTACK SEGMENT STACK

DW 64 DUP(?)

SSTACK ENDS

CODE SEGMENT

ASSUME CS:CODE

START PROC

;; INIT 8254

MOV DX, CON8254

MOV AL, 10110110B

OUT DX, AL

MOV DX, C028254

MOV AL, 0CH

OUT DX, AL

MOV AL, 00H

OUT DX, AL

;; INIT 8251

CALL INIT

MOV DX, CON8251

MOV AL, 01111110B

OUT DX, AL

CALL DELAY

MOV AL, 00110100B

OUT DX, AL

CALL DELAY

;; INIT 8255

MOV AL, 10010000B

MOV DX, CON8255

OUT DX, AL

;; INIT [3000]

MOV SI, 3000H

MOV AL, 61H ;; a

MOV CX, 26

INIT_CHAR:

MOV [SI], AL ;; SAVE TO [SI]

INC AL

INC SI

LOOP INIT_CHAR

MOV SI, 3000H

MOV DI, 4000H

MOV CX, 26

LO:

MOV AL, 00110111B ;; ASYNC COMMAND WORD

;; DIFFERENCE: ALLOW SEND

MOV DX, CON8251

OUT DX, AL ;; PREPARE 8251

MOV DX, DATA8251

MOV AL, [SI]

OUT DX, AL ;; SEND [SI] BYTE

MOV DX, CON8251

LO_SEND:

IN AL, DX ;; WAIT FOR SEND BUFFER TO BE EMPTY

AND AL, 1

JZ LO_SEND

LO_RECV:

IN AL, DX ;; WAIT FOR RECV BUFFER TO HAVE DATA

TEST AL, 02H

JZ LO_RECV

TEST AL, 00111000B

JNZ ERR_FIN

MOV DX, DATA8251

IN AL, DX ;; RECEIVE FROM 8251

MOV [DI], AL ;; SAVE TO [DI]

INC DI

INC SI

LOOP LO

FIN:

JMP FIN

ERR_FIN:

;; OUTPUT TO 8255

MOV DX, B8255

MOV AH, AL

OUT DX, AX

MOV AX, 4C00H

INT 21H

START ENDP

INIT PROC

PUSH AX

PUSH DX

MOV AL, 00H

MOV DX, CON8251

OUT DX, AL

CALL DELAY

OUT DX, AL

CALL DELAY

OUT DX, AL

CALL DELAY

MOV AL, 40H

OUT DX, AL

CALL DELAY

POP DX

POP AX

RET

INIT ENDP

DELAY PROC

PUSH CX

MOV CX, 0FFFFH

LOOP $

POP CX

RET

DELAY ENDP

CODE ENDS

END START

结果

3000H

4000H

演示:数据灯

由于传输过程中没有出现问题,因此没法检测 8255 的部分是否正确。因此这里强行测试了一下(

修改上述代码的 79 行,把 JNZ 修改为 JZ。这样就能输出正确情况下的状态字了。实际的 LED 输出如下图所示:

通过 LED 我们可以读出当前的状态字:10000111