看看我写的U盘汇编源程序(已完成inquiry指令),有完整的符号表对新手及汇编爱好者才是有用处的.
;古老牌U盘汇编版 ;CH372+STC89C54单片机 ;作者邮箱:xg_2004_sy@126.com
$INCLUDE (CH375INC.ASM)
STACK EQU 80H ;堆栈区栈顶(向上延伸) ; ; 需要主程序定义的参数 CH375_CMD_PORT EQU 0xB100 ;CH375命令口的地址,地址译码后自动片选 CH375_DAT_PORT EQU 0xB000 ;CH375命令口的地址,地址译码后自动片选 ;
CH375_CON_ACT BIT P1.2
VAR_NeedTransBlockCount Data 30h VAR_TransCompleteBlockCount Data 31H VAR_MainRXDataPackCount Data 32h
VAR_ExtSRAMDataLocationPoint_L Data 33H VAR_ExtSRAMDataLocationPoint_H Data 34H
VAR_CSW_BYTE_4 DATA 35H VAR_CSW_BYTE_5 DATA 36H VAR_CSW_BYTE_6 DATA 37H VAR_CSW_BYTE_7 DATA 38H
var_EP2_UP_STATUS DATA 39H ;上传数据状态切换变量
CMD_BUFFER DATA 3FH ;命令包缓冲区,本程序约定命令包长度为CONST_CMD_LEN CBW_Buffer DATA 10H ;cbW占用数据长度为12
VAR_SETUP_REQUEST EQU 72H ;USB请求码 VAR_SETUP_LENGTH EQU 73H ;后续数据长度 VAR_SETUP_DESCR EQU 74H ;描述符偏移地址 VAR_SN_STRING EQU 75H ;产品序列号字符串缓冲区,ANSI字符串 VAR_USB_ADDRESS EQU 76H
Reload_Count EQU 0F3H
c_Char_0 EQU 30H c_Char_1 EQU 31H c_Char_2 EQU 32H c_Char_3 EQU 33H c_Char_4 EQU 34H c_Char_5 EQU 35H c_Char_6 EQU 36H c_Char_7 EQU 37H c_Char_8 EQU 38H c_Char_9 EQU 39H
; 定义位标志 CH375_CON_FLAG BIT 2FH.0 ;375芯片配置完成标志 VAR_MainRXDataStatusMac Bit 2FH.1 ;主端点数据接收状态机标志 ; ;**************************************************************************** ;主程序 ORG 0000H ;复位后单片机入口 LJMP START ORG 0013H ;CH375中断 LJMP CH375_INTER
ORG 0100H ;---------------------------------------------------------------------------------
Initial_UART: Mov SCON,#50h Mov TMOD,#21h Mov TH1,#Reload_Count Mov TL1,#Reload_Count ORL PCON,#80h SETB TR1 ;启动定时器 Ret
UART_Send_Char: ;通过串口发送字符,待发送的字符在ACC中 CLR TI Mov SBUF,A Uart_Wait_Send_Finish: JNB TI,UART_Wait_Send_Finish CLR TI Ret ;--------------------------------------------------------------------------------- START: ; 以下初始化指令不是必要的,将单片机恢复为默认状态 CLR EA ;关中断 MOV SP,#STACK ;置堆栈初值 MOV A,#0FFH MOV P0,A MOV P1,A ;清端口状态 MOV P2,A MOV P3,A CLR A MOV IE,A ;清中断允许控制寄存器 MOV IP,A ;清中断优先级控制寄存器 MOV PSW,A ;清程序状态字 MOV TCON,A ;清定时器/计数器控制寄存器 MOV TMOD,A ;清定时器/计数器工作方式寄存器 MOV PCON,A ;清电源控制寄存器 MOV R7,#0FFH CALL DELAY_MS ;延时等待CH375初始化完成 ; 初始化 Call Initial_UART UART_SendTestChar: Mov a,#c_Char_0 call UART_Send_Char Mov a,#0DH call UART_Send_Char Mov a,#0AH call UART_Send_Char
Mov a,#c_Char_8 call UART_Send_Char Mov a,#0DH call UART_Send_Char Mov a,#0AH call UART_Send_Char
; AJMP UART_SendTestChar
CALL CH375_DisConnect ;配置为断开USB连接的状态 CALL CH375_INIT ;初始化 call Init_EP2_FUNC_VAlRegister setb EA ljmp $ ;主程序 ; ; 输出命令码给CH375 ; 输入: ACC 为命令码 ; 输出: DPTR 为数据口 ; USE: ACC, DPTR WR_CMD_TO_375: MOV DPTR,#CH375_CMD_PORT ;命令口地址 MOVX @DPTR,A ;设置USB工作模式 NOP ;如果时钟频率低于20MHz则无需该指令延时,高于30MHz要多加2条指令 MOV DPTR,#CH375_DAT_PORT ;数据口地址 RET ; ; 初始化子程序 ; USE: ACC, R7, DPTR CH375_INIT: MOV A,#CMD_SET_USB_MODE ;设置USB工作模式 CALL WR_CMD_TO_375 ;输出命令码 ; MOV A,#02H ;设置为内置固件模式 MOV A,#01H ;设置为外置固件模式 MOVX @DPTR,A ;设置为使用内置固件的USB设备方式 NOP ;如果时钟频率低于16MHz则无需该指令延时 NOP CH375_INIT_WT: MOVX A,@DPTR ;返回操作状态,也可以等待20uS XRL A,#CMD_RET_SUCCESS JNZ CH375_INIT_WT ;等待操作成功,通常需要等待10uS-20uS ; 下述三条指令用于启用中断 CLR IT1 ;置外部信号为低电平触发 SETB PX1 ;置高优先级 CLR IE1 ;清中断标志 SETB EX1 ;允许CH375中断 RET ;************************************************************************************** CH375_DisConnect: MOV A,#CMD_SET_USB_MODE ;设置USB工作模式 CALL WR_CMD_TO_375 ;输出命令码 MOV A,#00H ;设置为未配置模式 MOVX @DPTR,A ;设置为使用内置固件的USB设备方式 NOP ;如果时钟频率低于16MHz则无需该指令延时 NOP CH375_DisConnect_WT: MOVX A,@DPTR ;返回操作状态,也可以等待20uS XRL A,#CMD_RET_SUCCESS JNZ CH375_DisConnect_WT ;等待操作成功,通常需要等待10uS-20uS ; 下述三条指令用于启用中断 CLR IT1 ;置外部信号为低电平触发 SETB PX1 ;置高优先级 CLR IE1 ;清中断标志 SETB EX1 ;允许CH375中断 RET
;写代码定间的数据到EP2的端点 ;数据长度在R4中,数据缓冲区指针在DPTR中,采用MOVC取数 CH375_EP2_WRITE_CODEDATA: MOV R6,DPL MOV R7,DPH ; SAVE DATA POINT
MOV A,#CMD_WR_USB_DATA7 ;发出写上传端点命令 CALL WR_CMD_TO_375 MOV A,R4 MOVX @DPTR,A ;写数据长度
JZ CH375_EP2_WRITE_CODE_FINISH ;长度为0
EP2_WRITE_CODE_LOOP1: MOV DPL,R6 ;Get Data Point from backup DPTR Image MOV DPH,R7
CLR A MOVC A,@A+DPTR
INC DPTR MOV R6,DPL MOV R7,DPH ; SAVE DATA POINT MOV DPTR,#CH375_DAT_PORT MOVX @DPTR,A DJNZ R4,EP2_WRITE_CODE_LOOP1 CH375_EP2_WRITE_CODE_FINISH: RET ;---------------------------------------------------------------------------------------
c_EP2_UPSTATUS_TRANSMIT_IDLE EQU 00H c_EP2_UPSTATUS_TRANSMIT_CSW EQU 01H c_EP2_UPSTATUS_TRANSMIT_STANDPAGE EQU 02H c_EP2_UPSTATUS_TRANSMIT_SHORTPAGE EQU 03H
FUNC_SCSI_CMD10_INQUIRY: MOV DPTR,#USB_InquiryData_TAB MOV R4,#36 CALL CH375_EP2_WRITE_CODEDATA MOV var_EP2_UP_STATUS,#c_EP2_UPSTATUS_TRANSMIT_CSW ;发送完数据发状态 RET
CMD12_INQUIRY EQU 12H CMD1A_MODE_SENSE EQU 1AH CMD28_READ10 EQU 28H CMD25_READ_CAPACITY EQU 25H CMD23_READ_FORMAT_CAPACITIES EQU 23H CMD00_TEST_UNIT_READY EQU 00H CMD2F_VERIRY EQU 2FH CMD2A_WRITE10 EQU 2AH CMD1E_MEDIUM_REMOVAL EQU 1EH ;对EP2接收到的CBW进行解析和处理 ;R4为数据长度 ;数据内容在公共缓冲区中 EP2CMDProcess: MOV R0,#CMD_BUFFER+4 ;拷贝CSW内容 MOV A,@R0 MOV VAR_CSW_BYTE_4,A iNC R0 MOV A,@R0 MOV VAR_CSW_BYTE_5,A iNC R0 MOV A,@R0 MOV VAR_CSW_BYTE_6,A iNC R0 MOV A,@R0 MOV VAR_CSW_BYTE_7,A
MOv R4,#12 MOV R0,#CMD_BUFFER+15 ;拷贝UFI内容 MOV R1,#CBW_Buffer COPY_CBW_LOOP_1: MOV A,@R0 MOV @R1,A INC R0 INC R1 DJNZ R4,COPY_CBW_LOOP_1 Mov a,#c_Char_1 call UART_Send_Char Mov a,#c_Char_1 call UART_Send_Char MOV A,CBW_Buffer call UART_Send_Char
Mov a,#0DH call UART_Send_Char Mov a,#0AH call UART_Send_Char
MOV A,CBW_Buffer
CJNE A,#CMD12_INQUIRY,NO_CMD10_SEGMENT CALL FUNC_SCSI_CMD10_INQUIRY AJMP EP2_CMD_END NO_CMD10_SEGMENT: EP2_CMD_END: RET
; Mov a,#c_Char_1 ; call UART_Send_Char ; Mov a,#c_Char_0 ; call UART_Send_Char ; Mov a,#0DH ; call UART_Send_Char ; Mov a,#0AH ; call UART_Send_Char ; ; Ret
DataFlash_WriteSector: Mov a,#c_Char_1 call UART_Send_Char Mov a,#c_Char_1 call UART_Send_Char Mov a,#0DH call UART_Send_Char Mov a,#0AH call UART_Send_Char Ret
;------------------------------------------------------------------------------------------------- TransitCSW: ; Mov a,#c_Char_1 ; call UART_Send_Char ; Mov a,#c_Char_2 ; call UART_Send_Char ; Mov a,#0DH ; call UART_Send_Char ; Mov a,#0AH ; call UART_Send_Char ; MOV R6,DPL ; MOV R7,DPH ; SAVE DATA POINT
MOV A,#CMD_WR_USB_DATA7 ;发出写上传端点命令 CALL WR_CMD_TO_375 MOV A,#13 MOVX @DPTR,A ;写数据长度
MOV A,#0x55 MOVX @DPTR,A ;写数据长度 MOV A,#0x53 MOVX @DPTR,A ;写数据长度 MOV A,#0x42 MOVX @DPTR,A ;写数据长度 MOV A,#0x53 MOVX @DPTR,A ;写数据长度 MOV A,VAR_CSW_BYTE_4 MOVX @DPTR,A MOV A,VAR_CSW_BYTE_5 MOVX @DPTR,A MOV A,VAR_CSW_BYTE_6 MOVX @DPTR,A MOV A,VAR_CSW_BYTE_7 MOVX @DPTR,A
CLR A MOVX @DPTR,A MOVX @DPTR,A MOVX @DPTR,A MOVX @DPTR,A MOVX @DPTR,A
Ret ;--------------------------------------------------------------------------------------------
Init_EP2_FUNC_VAlRegister: clr VAR_MainRXDataStatusMac MOV var_EP2_UP_STATUS,#c_EP2_UPSTATUS_TRANSMIT_IDLE ;空闲态 ret ;------------------------------------------------------------------------------------------- EP2_TransitDataPage:
ret
CH375_EP2_UP: MOV A,var_EP2_UP_STATUS
CJNE A,#c_EP2_UPSTATUS_TRANSMIT_IDLE,UPSTATUS_NO_IDEL AJMP CH375EP2_END UPSTATUS_NO_IDEL: CJNE A,#c_EP2_UPSTATUS_TRANSMIT_CSW,UPSTATUS_NO_TRANSCSW CALL TransitCSW MOV var_EP2_UP_STATUS,#c_EP2_UPSTATUS_TRANSMIT_IDLE AJMP CH375EP2_END UPSTATUS_NO_TRANSCSW: CJNE A,#c_EP2_UPSTATUS_TRANSMIT_STANDPAGE,UPSTATUS_OTHER CALL EP2_TransitDataPage AJMP CH375EP2_END UPSTATUS_OTHER: CH375EP2_END: RET ;-------------------------------------------------------------------------------------------- CH375_EP2_DOWN: MOV A,#CMD_RD_USB_DATA ;将下传的数据读出,释放端点 CALL WR_CMD_TO_375 ;读命令发向CH375 MOVX A,@DPTR ;取出后续数据长度 MOV R4,A ;保存长度 JZ EP2ProcessEnd ;长度为0返回
;开始循环读取EP2的数据 MOV R5,A MOV R0,#CMD_BUFFER ;缓冲区首地址送R0 CH375_EP2_LOOP: MOVX A,@DPTR MOV @R0,A INC R0 DJNZ R5,CH375_EP2_LOOP JB VAR_MainRXDataStatusMac,EP2_ReceiveData ;为1是转入数据接收态 Call EP2CMDProcess AJMP EP2ProcessEnd EP2_ReceiveData: ;拷贝数据到扇区数据缓冲区 Mov DPL,VAR_ExtSRAMDataLocationPoint_L Mov DPH,VAR_ExtSRAMDataLocationPoint_H mov A,R4 Mov r5,A Mov R0,#CMD_BUFFER ;缓冲区首地址送R0 CopyData_Loop_1: Mov a,@R0 Movx @DPTR,a INC R0 INC DPTR DJNZ R5,CopyData_Loop_1 Mov VAR_ExtSRAMDataLocationPoint_L,DPL Mov VAR_ExtSRAMDataLocationPoint_H,DPH
INC VAR_MainRXDataPackCount MOV A,VAR_MainRXDataPackCount CLR c SUBB A,#08h JNC Contin_Receive_Pack Call DataFlash_WriteSector
ANL VAR_MainRXDataPackCount,#00h ANL VAR_ExtSRAMDataLocationPoint_L,#00h ANL VAR_ExtSRAMDataLocationPoint_H,#00h
INC VAR_TransCompleteBlockCount DEC VAR_NeedTransBlockCount MOV A,VAR_NeedTransBlockCount JNZ EP2ProcessEnd Call TransitCSW CLR VAR_MainRXDataStatusMac Contin_Receive_Pack: EP2ProcessEnd: ; AJMP CH375_EP2_UP_RET RET ;*************************************************************************************** ; 中断服务子程序 ; USE: 堆栈6字节, 工作寄存器组1的R0,R5,R6,R7 CH375_INTER: PUSH PSW ;现场保护 PUSH ACC PUSH DPL PUSH DPH SETB RS0 ;PSW.3,切换至工作寄存器组1 MOV A,#CMD_GET_STATUS CALL WR_CMD_TO_375 ;获取中断状态并取消中断请求 MOVX A,@DPTR ;返回操作状态 ANL A,#0FH ;屏蔽高4位 CLR IE1 ;清中断标志,对应于INT0中断 ;根据中断状态进行分析处理 CJNE A,#USB_INT_EP2_OUT,CH375_INT_06 ;批量端点下传成功 LCALL CH375_EP2_DOWN ;接收下传的数据 LJMP CH375_INT_RET ; USB批量数据接收成功 CH375_INT_06: CJNE A,#USB_INT_EP2_IN,CH375_INT_07 ;批量端点上传成功 ;USB批量数据发送成功 LCALL CH375_EP2_UP ;上传数据成功后的处理
LJMP CH375_INT_ULOCK ;解锁后中断返回 CH375_INT_07: CJNE A,#USB_INT_EP0_SETUP,CH375_INT_01 LJMP CH375_SETUP_OK ;USB控制传输建立事务 CH375_INT_01: CJNE A,#USB_INT_EP0_OUT,CH375_INT_02 LJMP CH375_INT_ULOCK ;端点0下传,解锁后中断返回 CH375_INT_02: CJNE A,#USB_INT_EP0_IN,CH375_INT_03 ;端点0数据上传 MOV A,VAR_SETUP_REQUEST CJNE A,#DEF_USB_GET_DESCR,CH375_EP0_IN_01 ;描述符上传 LCALL CH375_DES_UPLOAD ;调用描述符上传
LJMP CH375_INT_ULOCK ;解锁后中断返回
CH375_EP0_IN_01: CJNE A,#DEF_USB_SET_ADDRESS,CH375_EP0_IN_02 MOV A,#CMD_SET_USB_ADDR ;设置地址,以便下一次事务用新的地址 CALL WR_CMD_TO_375 MOV A,VAR_USB_ADDRESS ;取出地址 MOVX @DPTR,A LJMP CH375_INT_ULOCK CH375_EP0_IN_02: LJMP CH375_INT_ULOCK ;解锁后中断返回 CH375_INT_03: CJNE A,#USB_INT_EP1_IN,CH375_INT_04 ;端点1数据上传,请在此加上处理代码 LJMP CH375_INT_ULOCK ;解锁后中断返回
CH375_INT_04: CJNE A,#USB_INT_EP1_OUT,CH375_INT_05 ;端点1数据下传 MOV A,#CMD_RD_USB_DATA ;将下传的数据读出,释放端点 CALL WR_CMD_TO_375 ;读命令发向CH375 MOVX A,@DPTR ; JZ CH375_INT_RET ;长度为0返回 MOV R5,A CH375_USB_OUT1_LOOP: MOVX A,@DPTR ;读出数据释放缓冲区 NOP ;保存到缓冲区中 DJNZ R5,CH375_USB_OUT1_LOOP ;数据未读完继续 LJMP CH375_INT_RET ;中断返回 CH375_INT_05: ANL A,#03H CJNE A,#03H,CH375_INT_09 LJMP CH375_USB_REST ;跳转到USB复位 CH375_INT_09: SJMP CH375_INT_ULOCK ;命令不支持错误返回
CH375_INT_ULOCK: ;解锁后中断返回 MOV A,#CMD_UNLOCK_USB ;解锁端点 CALL WR_CMD_TO_375 CH375_INT_RET: POP DPH POP DPL POP ACC POP PSW ;恢复寄存器 RETI
CH375_USB_REST: ;USB总线复位 SETB CH375_CON_ACT ;清配置值等,CH372 会自动清USB 地址和同步触发标志 CLR CH375_CON_FLAG ;清单片机中各种标志 MOV VAR_SETUP_REQUEST,#0FFH LJMP CH375_INT_ULOCK ;***************************************************************************************** ;***********************************USB SETUP*********************************************** CH375_SETUP_RET_ERR: MOV A,#CMD_SET_ENDP3 ;设置端点1 CALL WR_CMD_TO_375 MOV A,#0FH ;设置状态为STALL MOVX @DPTR,A LJMP CH375_INT_RET&nb |