欢迎光临
我们一直在努力

8086汇编控制CH375实现U盘扇区读取

        要在8086平台上用汇编语言控制CH375读取U盘的指定扇区(物理扇区),核心流程分为:初始化CH375、发送读扇区命令、在中断服务程序中读取数据块,并处理必要的错误状态。

核心代码实现

此程序实现读取U盘的逻辑块地址(LBA)0号扇区,并将512字节数据存放于 DATA_BUFFER。

; 假设硬件连接(可根据实际译码修改)
CH375_CMD_PORT EQU 0A000H ; A0引脚为高电平时的端口地址(写命令)
CH375_DAT_PORT EQU 0A001H ; A0引脚为低电平时的端口地址(写数据)

; 定义CH375关键命令字
CMD_DISK_READ EQU 54H ; 从USB存储器读数据块
CMD_RD_USB_DATA EQU 28H ; 从CH375缓冲区读取数据块
CMD_DISK_RD_GO EQU 55H ; 继续执行USB存储器的读操作

; 定义中断状态
USB_INT_DISK_READ EQU 1DH ; 请求数据读出
USB_INT_SUCCESS EQU 14H ; 操作成功

; 定义缓冲区(至少512字节)
DATA_BUFFER SEGMENT
DB 512 DUP(?)
DATA_BUFFER ENDS

;——————————————————-
; 主调用示例:读取0号扇区
;——————————————————-
READ_SECTOR_EXAMPLE:
MOV BX, 0 ; BX:SI 指向32位LBA地址(低16位在SI,高16位在BX)
MOV SI, 0 ; LBA = 0x00000000
MOV CX, 1 ; 读取扇区数(通常为1)
LEA DX, DATA_BUFFER ; DX指向数据缓冲区
CALL READ_PHYSICAL_SECTOR
RET

;——————————————————-
; 读取物理扇区子程序
; 入口: BX:SI = 32位起始LBA扇区号 (BX高16位,SI低16位)
; CX = 读取扇区数 (1-255)
; DX = 数据缓冲区首地址
; 出口: 成功则缓冲区有数据,失败则返回错误码在AX
;——————————————————-
READ_PHYSICAL_SECTOR PROC
PUSH CX
PUSH DX
PUSH SI
PUSH BX

; 1. 发送 DISK_READ 命令
MOV DX, CH375_CMD_PORT
MOV AL, CMD_DISK_READ
OUT DX, AL

; 2. 发送32位LBA地址(小端模式,低字节在前)
MOV DX, CH375_DAT_PORT
MOV AX, SI ; LBA低16位
OUT DX, AL ; LBA 字节0 (bit7-0)
MOV AL, AH
OUT DX, AL ; LBA 字节1 (bit15-8)

MOV AX, BX ; LBA高16位
OUT DX, AL ; LBA 字节2 (bit23-16)
MOV AL, AH
OUT DX, AL ; LBA 字节3 (bit31-24)

; 3. 发送扇区数 (低字节有效)
MOV AL, CL ; CL存的是扇区数
OUT DX, AL

; 4. 准备读取数据块 (每个扇区对应8个64字节的数据块)
POP BX
POP SI
POP DX
POP CX

MOV DI, DX ; DI指向数据缓冲区
MOV BP, CX ; BP = 扇区数
SHL BP, 3 ; BP = 扇区数 * 8 (数据块数,因为每个扇区512字节=8个64字节块)

READ_BLOCK_LOOP:
PUSH CX
PUSH DX

; 等待中断并获取状态
CALL WAIT_CH375_INT ; 等待CH375中断引脚变低(需根据实际硬件实现)
MOV DX, CH375_CMD_PORT
MOV AL, CMD_GET_STATUS ; 获取中断状态命令(假设为0x22,根据库定义调整)
OUT DX, AL
MOV DX, CH375_DAT_PORT
IN AL, DX ; AL = 中断状态

CMP AL, USB_INT_DISK_READ
JZ READ_DATA_BLOCK

; 非请求数据状态,退出并返回错误
POP DX
POP CX
JMP READ_FAIL

READ_DATA_BLOCK:
; 发送 RD_USB_DATA 命令
MOV DX, CH375_CMD_PORT
MOV AL, CMD_RD_USB_DATA
OUT DX, AL

; 读取数据块长度(通常为64)
MOV DX, CH375_DAT_PORT
IN AL, DX ; AL = 后续数据长度(0-64)
MOV CL, AL
XOR CH, CH

; 根据长度读取数据到缓冲区
MOV SI, DI ; SI指向当前缓冲区位置
READ_DATA_BYTE:
TEST CX, CX
JZ READ_BYTE_DONE
IN AL, DX
MOV [SI], AL
INC SI
LOOP READ_DATA_BYTE
READ_BYTE_DONE:
MOV DI, SI ; 更新缓冲区指针

; 发送 DISK_RD_GO 继续读操作
MOV DX, CH375_CMD_PORT
MOV AL, CMD_DISK_RD_GO
OUT DX, AL

POP DX
POP CX

; 循环处理下一个数据块
DEC BP
JNZ READ_BLOCK_LOOP

; 所有数据块读取完成,等待最终成功中断
CALL WAIT_CH375_INT
MOV DX, CH375_CMD_PORT
MOV AL, CMD_GET_STATUS
OUT DX, AL
MOV DX, CH375_DAT_PORT
IN AL, DX
CMP AL, USB_INT_SUCCESS
JZ READ_SUCCESS

READ_FAIL:
; 处理错误(可根据实际需求添加错误码返回)
MOV AX, 0FFFFH ; 返回错误标志
RET

READ_SUCCESS:
XOR AX, AX ; 返回0表示成功
RET
READ_PHYSICAL_SECTOR ENDP

;——————————————————-
; 等待CH375中断(简易轮询方式)
; 实际使用时可根据中断引脚接法,使用INT引脚触发或轮询
;——————————————————-
WAIT_CH375_INT PROC
; 假设CH375的INT引脚连接到某个GPIO或总线
; 此处为占位,需根据实际硬件实现等待中断引脚变低
; 示例:轮询状态端口
WAIT_LOOP:
; IN AL, CH375_INT_PORT ; 读中断状态
; TEST AL, 01H ; 测试中断引脚
; JNZ WAIT_LOOP
RET
WAIT_CH375_INT ENDP

关键步骤解析

步骤操作说明
1. 发送读命令 OUT CMD_PORT, DISK_READ 命令码 0x54 表示准备读取U盘物理扇区
2. 发送LBA地址 连续输出4字节(小端模式) LBA是逻辑块地址,0表示U盘的第一个物理扇区(MBR)
3. 发送扇区数 输出1字节 表示要连续读取的扇区数量(通常为1)
4. 等待中断 WAIT_CH375_INT 等待CH375的INT引脚变低,表示操作有进展
5. 获取中断状态 GET_STATUS → 读数据口 判断中断类型,0x1D表示请求数据读出
6. 读取数据块 RD_USB_DATA → 读长度 → 循环读数据 先读1字节长度(通常64),再读取该长度的数据
7. 继续读操作 DISK_RD_GO 通知CH375继续下一块数据的传输
8. 重复4-7 循环 扇区数 × 8 次 每个扇区512字节,分8次64字节块读取
9. 等待完成 最终等待 0x14 成功状态 所有块读取完毕后,CH375会返回成功状态

常见调试要点

  • 检查基础通信:在调用读扇区前,务必先执行CH375的初始化序列(SET_USB_MODE、DISK_INIT等),确保U盘已就绪。

  • 中断等待的实现:上述代码中的 WAIT_CH375_INT 使用了轮询占位,实际开发中建议连接CH375的INT引脚到8086的外部中断(如INTR),通过中断服务程序提高效率。若采用轮询方式,需注意在等待期间关闭中断以避免干扰。

  • 缓冲区对齐:CH375每块数据固定为64字节,但总长度可能不是64的倍数(如最后一块可能不足),代码中已按实际返回长度读取,具有通用性。

  • 错误处理扩展:若 WAIT_CH375_INT 返回的状态不是 0x1D 也不是最终 0x14,应根据CH375数据手册查询错误码含义(如 0x23 等)。

  • LBA范围:对于普通U盘(容量小于2TB),LBA 0扇区通常是主引导记录(MBR),包含分区表信息。用户数据一般从 LBA 63 或更大扇区开始,具体需解析MBR得到。

  • 赞(0)
    未经允许不得转载:171主机测评 » 8086汇编控制CH375实现U盘扇区读取
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址