ToC
实验内容
通过 E
命令修改内存 3000H
的内容,发送到串口,然后自接受保存到 4000H
起始的内存单元中。
最后通过系统命令查看相应存储空间的数据,验证传输结果。
实验接线
通过 8254
控制波特率,将 TXD
和 RXD
相连以自收发。
代码
DATA8251 EQU 0600HCON8251 EQU 0602H
C028254 EQU 06C4HCON8254 EQU 06C6H
SSTACK SEGMENT STACK DW 64 DUP(?)SSTACK ENDS
CODE SEGMENTASSUME 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, CON8251LO_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 21HSTART 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 RETINIT ENDP
DELAY PROC PUSH CX MOV CX, 0FFFFH LOOP $ POP CX RETDELAY ENDP
CODE ENDSEND START
实验过程
设置内存
4000H
3000H
选做实验
说明
将 a-z
的 ASCII
码写入 3000H
,然后通过 9600
的波特率传输到 4000H
。
当出现错误时停止传输,并将状态字显示在数据灯 D7-D0
上。
接线
接线有点混沌,反正能用就行(
由于数据线低位不够用了,所以我把 8255
接到了数据线高位(D8-D15
),对应的 OUT
也就需要输出 AX
而非 AL
了。
总之就是下面这个样子:
代码
DATA8251 EQU 0600HCON8251 EQU 0602H
C028254 EQU 06C4HCON8254 EQU 06C6H
B8255 EQU 0642HCON8255 EQU 0646H
SSTACK SEGMENT STACK DW 64 DUP(?)SSTACK ENDS
CODE SEGMENTASSUME 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, 26INIT_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, CON8251LO_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 21HSTART 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 RETINIT ENDP
DELAY PROC PUSH CX MOV CX, 0FFFFH LOOP $ POP CX RETDELAY ENDP
CODE ENDSEND START
结果
3000H
4000H
演示:数据灯
由于传输过程中没有出现问题,因此没法检测 8255
的部分是否正确。因此这里强行测试了一下(
修改上述代码的 79
行,把 JNZ
修改为 JZ
。这样就能输出正确情况下的状态字了。实际的 LED
输出如下图所示:
通过 LED
我们可以读出当前的状态字:10000111
。