📄 ch375451.asm
字号:
; MOV R7,#0A0H ;160*256uS=40mS
;CH375_INIT_D2: CLR A
;CH375_INIT_D1: DJNZ ACC,CH375_INIT_D1 ;延时1uS
; DJNZ R7,CH375_INIT_D2 ;延时256uS
; SJMP CH375_INIT ;再次测试
;CH375_INIT_OK:
; 设置外部自定义的USB设备VID和PID,可选操作,不执行该命令则使用默认的VID和PID
; MOV DPTR,#CH375_CMD_PORT ;命令口地址
; MOV A,#CMD_SET_USB_ID
; MOVX @DPTR,A ;设置外部自定义的USB设备VID和PID,可选操作
; NOP ;如果时钟频率低于16MHz则无需该指令延时
; MOV DPTR,#CH375_DAT_PORT ;数据口地址
; MOV A,#USB_VENDOR_ID_L
; MOVX @DPTR,A ;写入厂商ID的低字节
; MOV A,#USB_VENDOR_ID_H
; MOVX @DPTR,A ;写入厂商ID的高字节
; MOV A,#USB_DEVICE_ID_L
; MOVX @DPTR,A ;写入设备ID的低字节
; MOV A,#USB_DEVICE_ID_H
; MOVX @DPTR,A ;写入设备ID的高字节
; NOP
; 设置USB工作模式
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_SET_USB_MODE
MOVX @DPTR,A ;设置USB工作模式
NOP ;如果时钟频率低于16MHz则无需该指令延时
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOV A,#02H
MOVX @DPTR,A ;设置为使用内置固件的USB设备方式
NOP ;如果时钟频率低于16MHz则无需该指令延时
CH375_INIT_WT: MOVX A,@DPTR ;返回操作状态
XRL A,#CMD_RET_SUCCESS
JNZ CH375_INIT_WT ;等待操作成功,通常需要等待10uS-20uS
; 下述三条指令用于启用中断
CLR IT0 ;置外部信号为低电平触发
SETB PX0 ;置高优先级
CLR IE0 ;清中断标志
SETB EX0 ;允许CH375中断
RET
;
; 上传数据块子程序(通过批量端点上传)
; ENTRY: R0 指向存放了准备上传数据的缓冲区, R7 准备上传的数据长度, 有效数值是0到64
; USE: ACC, R0, R7, DPTR
;CH375_UPLOAD: JB FLAG_SEND_WAIT,CH375_UPLOAD ;如果正在等待发送(前次发送尚未完成)则继续等待
; CLR EX0 ;为了防止中途被中断而乱了顺序,必须先禁止中断
; MOV DPTR,#CH375_CMD_PORT ;命令口地址
; MOV A,#CMD_WR_USB_DATA7
; MOVX @DPTR,A ;向USB端点2的发送缓冲区写入数据块
; NOP ;如果时钟频率低于16MHz则无需该指令延时
; MOV DPTR,#CH375_DAT_PORT ;数据口地址
; MOV A,R7
; MOVX @DPTR,A ;首先写入后续数据长度
;CH375_UPLOAD_1: MOV A,@R0
; INC R0
; MOVX @DPTR,A ;发送数据
; DJNZ R7,CH375_UPLOAD_1 ;继续发送数据直至结束
; SETB FLAG_SEND_WAIT ;置等待发送标志
; SETB EX0 ;允许中断
; RET
;
; 上传中断数据子程序(通过中断端点上传),可选子程序
; 虽然每次可以上传8个字节, 但是本程序中用于键盘中断, 所以每次只需要传输两个字节
; ENTRY: R0 中断数据首字节, R7 中断数据首字节
; USE: ACC, R0, R7, DPTR
CH375_UP_INT2: MOV A,#0FFH
CH375_UP_INT2W: JNB FLAG_INT_WAIT,CH375_UP_INT2G ;前次中断数据已经被PC机取走则继续
NOP ;等待发送中断数据
NOP
NOP ;最多等待1毫秒,以24MHz时钟计算
NOP
DJNZ ACC,CH375_UP_INT2W ;继续等待,满1毫秒后超时
; 如果未与计算机相连,或者计算机中的应用程序未运行,则会出现超时,否则不超过1毫秒中断数据就应该被PC机取走
CH375_UP_INT2G: CLR EX0 ;为了防止中途被中断而乱了顺序,必须先禁止中断
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_WR_USB_DATA5
MOVX @DPTR,A ;向USB端点1的发送缓冲区写入数据块
NOP ;如果时钟频率低于16MHz则无需该指令延时
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOV A,#02H
MOVX @DPTR,A ;首先写入后续数据长度
MOV A,R0
MOVX @DPTR,A ;发送中断数据1
MOV A,R7
MOVX @DPTR,A ;发送中断数据2
SETB FLAG_INT_WAIT ;置中断等待标志
SETB EX0 ;允许中断
RET
;
; 上传中断数据子程序(通过中断端点上传),可选子程序
; ENTRY: R0 指向存放了准备上传数据的缓冲区, R7 准备上传的数据长度, 有效数值是0到8
; USE: ACC, R0, R7, DPTR
;CH375_UP_INT: CLR EX0 ;为了防止中途被中断而乱了顺序,必须先禁止中断
; MOV DPTR,#CH375_CMD_PORT ;命令口地址
; MOV A,#CMD_WR_USB_DATA5
; MOVX @DPTR,A ;向USB端点1的发送缓冲区写入数据块
; NOP ;如果时钟频率低于16MHz则无需该指令延时
; MOV DPTR,#CH375_DAT_PORT ;数据口地址
; MOV A,R7
; MOVX @DPTR,A ;首先写入后续数据长度
;CH375_UP_INT_1: MOV A,@R0
; INC R0
; MOVX @DPTR,A ;发送中断数据
; DJNZ R7,CH375_UP_INT_1 ;继续发送数据直至结束
; SETB EX0 ;允许中断
; RET
;
; 中断服务子程序
; USE: 堆栈6字节, 工作寄存器组1的R0,R5,R6,R7
CH375_INTER: PUSH PSW ;现场保护
PUSH ACC
PUSH DPL
PUSH DPH
SETB RS0 ;PSW.3,切换至工作寄存器组1
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_GET_STATUS
MOVX @DPTR,A ;获取中断状态并取消中断请求
NOP ;如果时钟频率低于16MHz则无需该指令延时,高于30MHz要多加2条指令
NOP
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOVX A,@DPTR ;返回操作状态
CLR IE0 ;清中断标志,对应于INT0中断
CJNE A,#USB_INT_EP2_OUT,CH375_INT_1 ;批量端点下传成功
LJMP CH375_DOWN_OK ; USB批量数据接收成功
CH375_INT_1: CJNE A,#USB_INT_EP2_IN,CH375_INT_2 ;批量端点上传成功
LJMP CH375_UP_OK ; USB批量数据发送成功
CH375_INT_2: CJNE A,#USB_INT_EP1_IN,CH375_INT_3 ;中断端点
LJMP CH375_UP_INT_OK ; USB中断数据发送成功
CH375_INT_3: SJMP CH375_INT_RET
CH375_INT_RET: POP DPH
POP DPL
POP ACC
POP PSW ;恢复寄存器
RETI ;中断返回
; USB批量数据接收成功
CH375_DOWN_OK: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_RD_USB_DATA
MOVX @DPTR,A ;从当前USB中断的端点缓冲区读取数据块,并释放缓冲区
NOP ;如果时钟频率低于16MHz则无需该指令延时,高于30MHz要多加2条指令
NOP
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOVX A,@DPTR ;首先读取后续数据长度
MOV R7,A
JZ CH375_INT_RET ;长度为0,没有数据则直接退出,在某些应用中也可以将长度0定义为一种特殊命令
CJNE A,#CONST_CMD_LEN,CH375_INT_DOWN ;不是命令包
LJMP CH375_INT_CMD ;命令块长度总是CONST_CMD_LEN
; 接收下传的数据块,每组数据的长度不超过64字节,例如总长度150个字节,则第1组和第2组各是64字节,第3组是剩余长度22字节
; 为了将数据块与命令包区分开来,剩余长度不能等于CONST_CMD_LEN,可以用填充数据的办法避免相同
CH375_INT_DOWN: LJMP CH375_INT_DN1 ;接收数据块
; 分析通过USB接收到的命令块,长度总是CONST_CMD_LEN,首字节为命令,其余为可选的参数
CH375_INT_CMD: MOV R0,#CMD_BUFFER ;命令包缓冲区
CH375_INT_CMD0: MOVX A,@DPTR ;接收命令包的数据
MOV @R0,A
INC R0
DJNZ R7,CH375_INT_CMD0 ;继续接收命令包数据直至结束
; 分析通过USB接收到的命令块,长度总是CONST_CMD_LEN,首字节为命令,其余为可选的参数
; 这种首字节为命令的结构是由单片机和计算机应用层之间自行定义的
MOV A,CMD_BUFFER ;取命令码分析
CPL A
XRL A,CMD_BUFFER_NOT
JNZ CH375_INT_RET ;命令包反码校验错误
MOV A,CMD_BUFFER ;命令码
CJNE A,#DEMO_UP_CLEAR,CH375_INT_CMD1
; 连续上传数据块之前进行同步,实际是让单片机清除上传缓冲区的已有内容
; 如果上一次进行数据上传时,计算机提前结束上传,那么有可能在上传缓冲区中遗留有数据,所以在第二次上传前需要清除上传缓冲区
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_SET_ENDP7
MOVX @DPTR,A ;设置USB端点2的IN,也就是批量上传端点
NOP ;如果时钟频率低于16MHz则无需该指令延时
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOV A,#0EH ;同步触发位不变
MOVX @DPTR,A ;设置USB端点2的IN正忙,返回NAK,也就是缓冲区中没有数据
LJMP CH375_INT_RET
CH375_INT_CMD1: CJNE A,#DEMO_DOWN_DATA,CH375_INT_CMD2
; 连续下传数据块
; 假定事先约定, 该命令在第3字节和第4字节指定下面将下传的数据应该存放在外部RAM的起始地址
MOV A,CMD_BUFFER_ADRL
MOV BUF_ADDR_L,A ;保存用于下传的外部RAM缓冲区的地址
MOV A,CMD_BUFFER_ADRH
MOV BUF_ADDR_H,A
MOV A,CMD_BUFFER_LENL
MOV BUF_LEN_L,A ;假定事先约定第5和第6字节是将要下传的数据长度
MOV A,CMD_BUFFER_LENH
MOV BUF_LEN_H,A
LJMP CH375_INT_RET
CH375_INT_CMD2: CJNE A,#DEMO_UP_DATA,CH375_INT_CMD3
; 连续上传数据块
; 假定事先约定, 该命令在第3字节和第4字节指定下面将上传的数据应该来自外部RAM的起始地址
MOV A,CMD_BUFFER_ADRL
MOV BUF_ADDR_L,A ;保存用于上传的外部RAM缓冲区的地址
MOV A,CMD_BUFFER_ADRH
MOV BUF_ADDR_H,A
MOV A,CMD_BUFFER_LENL
MOV BUF_LEN_L,A ;假定事先约定第5和第6字节是将要下传的数据长度
MOV A,CMD_BUFFER_LENH
MOV BUF_LEN_H,A
; 数据上传,准备第一组数据,每组数据的长度不超过64字节
CLR C
MOV A,BUF_LEN_L
SUBB A,#40H ;检查剩余长度
MOV R5,A
MOV A,BUF_LEN_H
SUBB A,#00H
MOV R6,A
JC CH375_UP_SHORT ;剩余长度不足一个数据包的最大长度64
MOV R7,#40H
MOV BUF_LEN_L,R5
MOV BUF_LEN_H,R6
SJMP CH375_UP_FIRST
CH375_UP_SHORT: MOV R7,BUF_LEN_L
MOV BUF_LEN_L,#00H
MOV BUF_LEN_H,#00H
CH375_UP_FIRST: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_WR_USB_DATA7
MOVX @DPTR,A ;向USB端点2的发送缓冲区写入数据块
NOP ;如果时钟频率低于16MHz则无需该指令延时
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOV A,R7 ;每次最多上传64个字节的数据
MOVX @DPTR,A ;首先写入后续数据长度
; 下面是从MCS51单片机的内部RAM读取数据并上传,速度是外部RAM快3倍
MOV R0,BUF_ADDR_L ;由于演示板中没有外部RAM,并且外部RAM的效率很低,所以用内部RAM示范
CH375_INT_UP0: MOV A,@R0 ;从内部RAM缓冲区取出准备上传的数据
INC R0 ;在12MHz时钟是这种方法每复制1字节大概需要6uS
MOVX @DPTR,A ;将数据写入批量端点的发送缓冲区
DJNZ R7,CH375_INT_UP0 ;继续写入数据直至结束
LJMP CH375_INT_RET
; 下面从MCS51单片机的外部RAM读取数据并上传,如果采用较高时钟并且具有双DPTR的单片机则速度可以快些
;CH375_INT_UP0: MOV DPL,BUF_ADDR_L ;由于MCS51单片机读取外部RAM的效率很低
; MOV DPH,BUF_ADDR_H ;所以在12MHz时钟是这种方法每复制1字节大概需要18uS
; MOVX A,@DPTR ;从外部RAM缓冲区取出准备上传的数据
; INC DPTR ;缓冲区地址增量
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -