📄 ch375hmp.asm
字号:
; /* 2004.06.05
; ****************************************
; ** Copyright (C) W.ch 1999-2007 **
; ** Web: http://www.winchiphead.com **
; ****************************************
; ** USB Host File Module @CH375 **
; ****************************************
; */
; /* U盘文件读写模块, 连接方式: 并口+查询 */
; /* MCS-51单片机ASM语言示例程序, 仅适用于V3.0A及以上版本的模块 */
; /* 因为使用U盘文件读写模块而不是使用U盘文件级子程序库,所以占用较少的单片机资源,可以使用89C51单片机测试 */
;
;$include (REG51.INC)
$include (..\CH375HM.INC)
; 电路连接方式
; 单片机 模块
; P0 = D0-D7
; RD = RD#
; WR = WR#
; ? = CS# 如果没有外部RAM,那么CS#=P26,如果有超过16KB的外部RAM,那么CS#=P27 & ! P26 & ...,所以CS#的片选地址为BXXXH
; P20 = A0
; INT0 = INT# 虽然连接到INT0,但是本程序只是查询模块的INT#的状态,所以可以用P1口等普通I/O引脚代替INT0
CH375HM_INDEX XDATA 0BCF0H ;CH375模块的索引端口的I/O地址
CH375HM_DATA XDATA 0BDF1H ;CH375模块的数据端口的I/O地址
CH375HM_INT BIT INT0 ;假定CH375模块的INT#引脚连接到单片机的INT0引脚
LED_OUT BIT P1.4 ;P1.4 低电平驱动LED显示,用于监控演示程序的进度
; 假定文件数据缓冲区: ExtRAM: 0000H-7FFFH
DATA_BUF XDATA 00000H ;外部RAM的文件数据缓冲区,从该单元开始的缓冲区长度不小于一次读写的数据长度,最少为512字节
; 命令参数结构, 长度为20到60字节
mCmdParam DATA 20H ;默认情况下该结构将占用64字节的RAM,可以修改MAX_PATH_LEN常量,当修改为32时,只占用32字节的RAM
SECTOR_COUNT DATA 1DH ;文件占用扇区数
NEW_SIZE_HIGH DATA 1EH ;文件长度的高字节
NEW_SIZE_LOW DATA 1FH ;文件长度的低字节
ORG 0000H
LJMP MAIN
;
; 程序数据起始地址
ORG 0100H
STR_FILE_NAME1: DB '\C51\CH375HFT.C',00H ;文件名,该文件在C51子目录下
STR_FILE_DATA: DB 'Note: ',0DH,0AH
DB '原本是打算将/C51/CH375HFT.C文件中的小写字母转成大写后写入新的文件,但是找不到这个文件',0DH,0AH,00H
STR_FILE_NAME2: DB '\双击我吧.TXT',00H ;新文件名,在根目录下
; 从程序空间复制字符串到内部RAM缓冲区,源字符串必须以00H作为结束标志,长度不能超过255
; 入口: DPTR 指向源字符串的起始地址, R0 目标缓冲区的起始地址
; 出口: R7 返回字符串的长度(含字符串结束符00H)
; 使用: DPTR, R0, R7
CopyString: MOV R7,#00H
CopyStringChar: MOV A,R7
INC R7
MOVC A,@A+DPTR
MOV @R0,A
INC R0
JNZ CopyStringChar ;不是字符串结束符00H,继续复制
RET
;
; 延时100毫秒,不精确
; 使用: R6, R7
mDelay100mS: MOV R7,#0C8H
mDelay100mS_1: MOV R6,#0C8H
mDelay100mS_2: NOP
NOP
NOP
DJNZ R6,mDelay100mS_2
DJNZ R7,mDelay100mS_1
RET
; 执行命令
; 输入命令码和输入参数长度,返回操作状态码,输入参数和返回参数都在CMD_PARAM结构中
; 入口: R7 命令码, R5 参数长度, 对于读写文件数据命令, DPTR 为外部RAM缓冲区起始地址
; 出口: R7 状态码, 对于读写文件数据命令, DPTR 为数据终止地址
; 使用: R0, R4, R5, R6, R7
ExecCommand: MOV R6,DPH ;对于读写文件数据命令,保存外部RAM缓冲区起始地址
MOV R4,DPL
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_COMMAND_ADDR
MOVX @DPTR,A ;索引地址为PARA_COMMAND_ADDR
MOV DPTR,#CH375HM_DATA
MOV A,R7
MOVX @DPTR,A ;向索引地址PARA_COMMAND_ADDR写入命令码
MOV A,R5
MOV R7,A ;后续参数的长度
JZ ExecCommand_W0 ;没有参数
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_BUFFER_ADDR
MOVX @DPTR,A ;指向缓冲区
MOV R0,#mCmdParam ;指向输入参数的起始地址
MOV DPTR,#CH375HM_DATA
ExecCommand_WP: MOV A,@R0
MOVX @DPTR,A ;从索引地址PARA_BUFFER_ADDR开始,写入参数
INC R0
DJNZ R7,ExecCommand_WP
ExecCommand_W0: MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_CMD_LEN_ADDR
MOVX @DPTR,A ;索引地址PARA_CMD_LEN_ADDR
MOV DPTR,#CH375HM_DATA
MOV A,R5
ORL A,#PARA_CMD_BIT_ACT ;最高位通知模块,说明命令包已经写入,请求开始执行命令
MOVX @DPTR,A ;向索引地址PARA_CMD_LEN_ADDR写入后续参数的长度
ExecCommand_Wait:
$IF 1
JB CH375HM_INT,$ ;等待模块完成操作产生低电平中断,并返回操作状态
$ELSE
MOV DPTR,#CH375HM_INDEX ;如果不需要扇区方式读写,那么可以查询模块的命令码单元代替查询模块INT#引脚
MOV A,#PARA_COMMAND_ADDR
MOVX @DPTR,A
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;模块操作完成时该值会清0,仅适用于非扇区方式读写
JNZ ExecCommand_Wait ;等待中断
$ENDIF
;最佳检测方式是对模块的INT#信号进行下降沿边沿检测
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_STATUS_ADDR
MOVX @DPTR,A ;写入索引地址PARA_STATUS_ADDR
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;从索引地址PARA_STATUS_ADDR读取中断状态
MOV R7,A ;操作状态码
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_CMD_LEN_ADDR
MOVX @DPTR,A ;启动操作的单元地址
MOV DPTR,#CH375HM_DATA
MOV A,#PARA_CMD_BIT_INACT
MOVX @DPTR,A ;中断应答,取消来自模块的中断请求
;因为模块在收到中断应答后3uS之内才撤消中断请求,所以,如果是查询INT#信号的低电平,那么在发出中断应答后3uS之内不应该再查询INT#信号的状态
;但是由于51单片机较慢,下面的处理时间已经超过3uS,所以不必另加延时等待模块撤消中断请求
CJNE R7,#ERR_SUCCESS,ExecCommand_J0 ;不是操作成功的状态码
MOV DPTR,#CH375HM_INDEX ;操作成功
MOV A,#PARA_STS_LEN_ADDR
MOVX @DPTR,A
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;从索引地址PARA_STS_LEN_ADDR读取返回结果数据的长度
MOV R7,A
JZ ExecCommand_R0 ;没有结果数据
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_BUFFER_ADDR
MOVX @DPTR,A ;指向缓冲区
MOV R0,#mCmdParam ;指向输出参数的起始地址
MOV DPTR,#CH375HM_DATA ;从索引地址PARA_BUFFER_ADDR开始,读取结果
ExecCommand_RP: MOVX A,@DPTR
MOV @R0,A
INC R0
DJNZ R7,ExecCommand_RP
ExecCommand_R0: LJMP ExecCommand_Ret
ExecCommand_J0: CJNE R7,#USB_INT_DISK_READ,ExecCommand_J1
MOV DPTR,#CH375HM_INDEX ;正在从U盘读数据块,请求数据读出
MOV A,#PARA_BUFFER_ADDR
MOVX @DPTR,A ;指向缓冲区
MOV R7,#040H ;一次读取64个字节
RD_SEC_BYTE: MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;依次输入64字节的数据
MOV DPH,R6
MOV DPL,R4 ;缓冲区地址
MOVX @DPTR,A ;读取的数据保存到外部缓冲区
INC DPTR
MOV R6,DPH
MOV R4,DPL
DJNZ R7,RD_SEC_BYTE ;从索引地址0到63依次读出64字节的数据
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_CMD_LEN_ADDR
MOVX @DPTR,A ;启动操作的单元地址
MOV DPTR,#CH375HM_DATA
MOV A,#PARA_CMD_BIT_ACT
MOVX @DPTR,A ;通知模块继续,说明64字节数据已经读取完成
LJMP ExecCommand_Wait
ExecCommand_J1: CJNE R7,#USB_INT_DISK_WRITE,ExecCommand_J2
MOV DPTR,#CH375HM_INDEX ;正在向U盘写数据块,请求数据写入
MOV A,#PARA_BUFFER_ADDR
MOVX @DPTR,A ;指向缓冲区
MOV R7,#040H ;一次写入64个字节
WR_SEC_BYTE: MOV DPH,R6
MOV DPL,R4 ;缓冲区地址
MOVX A,@DPTR ;写入的数据来自外部缓冲区
INC DPTR
MOV R6,DPH
MOV R4,DPL
MOV DPTR,#CH375HM_DATA
MOVX @DPTR,A ;依次输出64字节的数据
DJNZ R7,WR_SEC_BYTE ;向索引地址0到63依次写入64字节的数据
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_CMD_LEN_ADDR
MOVX @DPTR,A ;启动操作的单元地址
MOV DPTR,#CH375HM_DATA
MOV A,#PARA_CMD_BIT_ACT
MOVX @DPTR,A ;通知模块继续,说明64字节数据已经写入完成
LJMP ExecCommand_Wait
ExecCommand_J2: CJNE R7,#USB_INT_DISK_RETRY,ExecCommand_J3
MOV DPTR,#CH375HM_INDEX ;读写数据块失败重试,应该向回修改缓冲区指针
MOV A,#PARA_BUFFER_ADDR
MOVX @DPTR,A ;指向缓冲区
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;大端模式下为回改指针字节数的高8位,如果是小端模式那么接收到的是回改指针字节数的低8位
MOV R7,A
MOVX A,@DPTR ;大端模式下为回改指针字节数的低8位,如果是小端模式那么接收到的是回改指针字节数的高8位
CLR C
XCH A,R4
SUBB A,R4
MOV R4,A ;这是大端模式下的回改指针
MOV A,R6
SUBB A,R7
MOV R6,A
MOV DPTR,#CH375HM_INDEX
MOV A,#PARA_CMD_LEN_ADDR
MOVX @DPTR,A ;启动操作的单元地址
MOV DPTR,#CH375HM_DATA
MOV A,#PARA_CMD_BIT_ACT
MOVX @DPTR,A ;通知模块继续,说明重试状态码已经处理完成
LJMP ExecCommand_Wait
ExecCommand_J3: ;R7为操作完成状态,操作出现错误
CJNE R7,#ERR_DISK_DISCON,ExecCommand_J4 ;检查U盘断开事件
SJMP ExecCommandEv
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -