H_Prj06_02 8088单板机串口读取内存块

发布于:2025-06-09 ⋅ 阅读:(15) ⋅ 点赞:(0)

1.程序

通过查询方式检测串口接收字符'r',然后从内存地址0000:2000H开始发送512字节数据。程序使用18.432MHz时钟的16550 UART,波特率9600:

; 串口查询接收'r'后发送内存数据程序
; 硬件配置:
;   PC16550 基地址: 100H
;   时钟频率: 18.432MHz
;   波特率: 9600 bps
;   数据源: 0000:2000H 开始的512字节内存

ORG 100H
JMP START

; 数据段
WAIT_MSG DB 'Waiting for "r"...', 0Dh, 0Ah, 0
SENDING_MSG DB 'Sending 512 bytes...', 0Dh, 0Ah, 0
DONE_MSG DB 'Transfer complete!', 0Dh, 0Ah, 0

; 16550寄存器偏移地址
UART_BASE EQU 100H
RBR_THR EQU UART_BASE + 0  ; 接收/发送寄存器
LSR     EQU UART_BASE + 5  ; 线路状态寄存器
LCR     EQU UART_BASE + 3  ; 线路控制寄存器
DLL     EQU UART_BASE + 0  ; 除数锁存低字节 (DLAB=1)
DLM     EQU UART_BASE + 1  ; 除数锁存高字节 (DLAB=1)

; 初始化UART (波特率9600, 18.432MHz时钟)
INIT_UART:
    ; 设置波特率除数(9600 @ 18.432MHz)
    MOV DX, LCR
    MOV AL, 80H       ; 设置DLAB=1
    OUT DX, AL
    
    MOV DX, DLL       ; 除数锁存低字节
    MOV AL, 78H       ; 120 = 78H
    OUT DX, AL
    
    MOV DX, DLM       ; 除数锁存高字节
    MOV AL, 00H       ; 高位为0
    OUT DX, AL
    
    ; 设置线路参数: 8位数据, 1停止位, 无校验
    MOV DX, LCR
    MOV AL, 03H       ; 8N1, DLAB=0
    OUT DX, AL
    
    ; 禁用中断
    MOV DX, UART_BASE + 1 ; IER
    MOV AL, 00H
    OUT DX, AL
    RET

; 发送单个字符
; 输入: AL = 要发送的字符
SEND_CHAR:
    PUSH DX
    PUSH AX
    
    ; 保存字符
    MOV AH, AL
    
SEND_WAIT:
    ; 检查发送保持寄存器是否为空
    MOV DX, LSR
    IN AL, DX
    TEST AL, 20H      ; 检查THRE位(bit5)
    JZ SEND_WAIT      ; 不为空则等待
    
    ; 发送字符
    MOV DX, RBR_THR
    MOV AL, AH
    OUT DX, AL
    
    POP AX
    POP DX
    RET

; 接收单个字符
; 输出: AL = 接收到的字符
RECV_CHAR:
    PUSH DX
    
RECV_WAIT:
    ; 检查接收数据就绪
    MOV DX, LSR
    IN AL, DX
    TEST AL, 01H      ; 检查DR位(bit0)
    JZ RECV_WAIT      ; 无数据则等待
    
    ; 读取字符
    MOV DX, RBR_THR
    IN AL, DX
    
    POP DX
    RET

; 发送字符串
; 输入: DS:SI = 字符串地址(以0结尾)
SEND_STRING:
    PUSH SI
    PUSH AX
    
SEND_STR_LOOP:
    LODSB             ; 从[DS:SI]加载字符到AL, SI++
    OR AL, AL         ; 检查是否结束(AL=0)
    JZ SEND_STR_DONE  ; 是则结束
    
    CALL SEND_CHAR    ; 发送当前字符
    JMP SEND_STR_LOOP ; 继续发送
    
SEND_STR_DONE:
    POP AX
    POP SI
    RET

; 发送内存块
; 输入: ES:BX = 数据起始地址
;       CX = 数据长度(字节数)
SEND_MEMORY:
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX
    
    ; 发送状态消息
    MOV SI, OFFSET SENDING_MSG
    CALL SEND_STRING
    
    ; 设置计数器
    MOV CX, 512
    
SEND_MEM_LOOP:
    ; 读取内存字节
    MOV AL, ES:[BX]
    
    ; 发送字节
    CALL SEND_CHAR
    
    ; 更新指针和计数器
    INC BX
    LOOP SEND_MEM_LOOP
    
    ; 发送完成消息
    MOV SI, OFFSET DONE_MSG
    CALL SEND_STRING
    
    POP DX
    POP CX
    POP BX
    POP AX
    RET

; 主程序
START:
    ; 初始化UART
    CALL INIT_UART
 
AGAIN:   
    ; 显示等待消息
    MOV SI, OFFSET WAIT_MSG
    CALL SEND_STRING
    
    ; 等待接收字符'r'
WAIT_FOR_R:
    CALL RECV_CHAR
    CMP AL, 'r'       ; 检查是否收到'r'
    JNE WAIT_FOR_R    ; 不是则继续等待
    
    ; 收到'r'后发送内存数据
    MOV AX, 0000H     ; 设置段地址0000H
    MOV ES, AX
    MOV BX, 2000H     ; 设置偏移地址2000H
    
    CALL SEND_MEMORY  ; 发送512字节数据                
    
    JMP  AGAIN
    
    ; 程序结束
    MOV AH, 4CH
    INT 21H    
    
   DB  55H,55H,55H,55H,55H

END START

2.验证