Skip to content

[微机实验/TD-PITE] 8251 串行接口实验

Published: at 16:11

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


Previous Post
Node.js child_process.fork 与 env 污染 RCE
Next Post
X-NUCA 2020 - hellowasm 题解