📄 ch375hmp.asm
字号:
; /* 2004.06.05
; ****************************************
; ** Copyright (C) W.ch 1999-2004 **
; ** Web: http://www.winchiphead.com **
; ****************************************
; ** USB Host File Module @CH375 **
; ****************************************
; */
; /* U盘文件读写模块, 连接方式: 并口+查询 */
; /* MCS-51单片机ASM语言示例程序, 仅适用于V2.5及以上版本的模块 */
; /* 因为使用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
; P15 = STA#
; 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引脚
CH375HM_STA BIT P1.5 ;假定CH375模块的STA#引脚连接到单片机的P15引脚
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,并口最大值62
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
CLR A
MOVX @DPTR,A ;索引地址为0
MOV DPTR,#CH375HM_DATA
MOV A,R7
MOVX @DPTR,A ;向索引地址0写入命令码
; MOV DPTR,#CH375HM_DATA
MOV A,R5
MOVX @DPTR,A ;向索引地址1写入后续参数的长度
JZ ExecCommand_W0 ;没有参数
MOV R0,#mCmdParam; ;指向输入参数的起始地址
; MOV DPTR,#CH375HM_DATA
ExecCommand_WP: MOV A,@R0
MOVX @DPTR,A ;从索引地址2开始,写入参数
INC R0
DJNZ R5,ExecCommand_WP
ExecCommand_W0: CLR CH375HM_STA ;产生下降沿通知模块,说明命令包已经写入,请求开始执行命令
ExecCommand_Wait:
JB CH375HM_INT,$ ;等待模块完成操作产生低电平中断,并返回操作状态
;最佳检测方式是对模块的INT#信号进行下降沿边沿检测
MOV DPTR,#CH375HM_INDEX
MOV A,#03FH
MOVX @DPTR,A ;写入索引地址63
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;从索引地址63读取中断状态
MOV R7,A ;操作状态码
SETB CH375HM_STA ;中断应答,取消来自模块的中断请求
;因为模块在收到中断应答后3uS之内才撤消中断请求,所以,如果是查询INT#信号的低电平,那么在发出中断应答后3uS之内不应该再查询INT#信号的状态
;但是由于51单片机较慢,下面的处理时间已经超过3uS,所以不必另加延时等待模块撤消中断请求
CJNE R7,#ERR_SUCCESS,ExecCommand_J0 ;不是操作成功的状态码
MOV DPTR,#CH375HM_INDEX ;操作成功
MOV A,#01H
MOVX @DPTR,A ;索引地址为1
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;从索引地址1读取返回结果数据的长度
MOV R7,A
JZ ExecCommand_R0 ;没有结果数据
MOV R0,#mCmdParam; ;指向输出参数的起始地址
MOV R5,#02H ;从索引地址2开始,读取结果
ExecCommand_RP: MOV DPTR,#CH375HM_INDEX
MOV A,R5
MOVX @DPTR,A ;索引地址
INC R5
MOV DPTR,#CH375HM_DATA
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 R5,#00H ;正在从U盘读数据块,请求数据读出
MOV R7,#040H ;一次读取64个字节
MOV P2,#HIGH (CH375HM_DATA)
MOV R0,#LOW (CH375HM_DATA)
MOV DPH,R6
MOV DPL,R4 ;缓冲区地址
RD_SEC_BYTE: PUSH DPH
PUSH DPL
MOV DPTR,#CH375HM_INDEX
MOV A,R5
MOVX @DPTR,A ;索引地址
POP DPL
POP DPH
MOVX A,@R0 ;依次输入64字节的数据
INC R5
MOVX @DPTR,A ;读取的数据保存到外部缓冲区
INC DPTR
DJNZ R7,RD_SEC_BYTE ;从索引地址0到63依次读出64字节的数据
MOV P2,#0FFH
MOV R6,DPH
MOV R4,DPL
CLR CH375HM_STA ;产生下降沿通知模块继续,说明64字节数据已经读取完成
LJMP ExecCommand_Wait
ExecCommand_J1: CJNE R7,#USB_INT_DISK_WRITE,ExecCommand_J2
MOV DPTR,#CH375HM_INDEX ;正在向U盘写数据块,请求数据写入
CLR A
MOVX @DPTR,A ;索引地址为0
MOV R7,#040H ;一次写入64个字节
MOV P2,#HIGH (CH375HM_DATA)
MOV R0,#LOW (CH375HM_DATA)
MOV DPH,R6
MOV DPL,R4 ;缓冲区地址
WR_SEC_BYTE: MOVX A,@DPTR ;写入的数据来自外部缓冲区
INC DPTR
MOVX @R0,A ;依次输出64字节的数据
DJNZ R7,WR_SEC_BYTE ;向索引地址0到63依次写入64字节的数据
MOV P2,#0FFH
MOV R6,DPH
MOV R4,DPL
CLR CH375HM_STA ;产生下降沿通知模块继续,说明64字节数据已经写入完成
LJMP ExecCommand_Wait
ExecCommand_J2: CJNE R7,#USB_INT_DISK_RETRY,ExecCommand_J3
MOV DPTR,#CH375HM_INDEX ;读写数据块失败重试,应该向回修改缓冲区指针
CLR A
MOVX @DPTR,A ;索引地址为0
MOV DPTR,#CH375HM_DATA
MOVX A,@DPTR ;大端模式下为回改指针字节数的高8位,如果是小端模式那么接收到的是回改指针字节数的低8位
MOV R7,A
MOV DPTR,#CH375HM_INDEX
MOV A,#01H
MOVX @DPTR,A ;索引地址为1
MOV DPTR,#CH375HM_DATA
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
CLR CH375HM_STA ;产生下降沿通知模块继续,说明重试状态码已经处理完成
LJMP ExecCommand_Wait
ExecCommand_J3: ;R7为操作完成状态,操作出现错误
NOP ;等待模块将INT#引脚恢复为高电平,撤消中断
NOP
ExecCommand_Ret:
; JNB CH375HM_INT,$ ;等待模块的中断撤消
MOV DPH,R6 ;对于读写文件数据命令
MOV DPL,R4 ;从DPTR返回新的缓冲区地址
RET
; END OF ExecCommand
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -