📄 ch375451.asm
字号:
; MOV BUF_ADDR_L,DPL
; MOV BUF_ADDR_H,DPH
; MOV DPTR,#CH375_DAT_PORT ;数据口地址
; MOVX @DPTR,A ;将数据写入批量端点的发送缓冲区
; DJNZ R7,CH375_INT_UP0 ;继续写入数据直至结束
; LJMP CH375_INT_RET
CH375_INT_CMD3: CJNE A,#DEMO_TEST_DATA,CH375_INT_CMD4
; 测试数据传输命令,将PC机发来的当前命令包的所有数据按位取反后返回
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_WR_USB_DATA7
MOVX @DPTR,A ;向批量端点的发送缓冲区写入数据块
NOP ;如果时钟频率低于16MHz则无需该指令延时
MOV DPTR,#CH375_DAT_PORT ;数据口地址
MOV A,#CONST_CMD_LEN
MOV R7,A
MOVX @DPTR,A ;首先写入后续数据长度,也就是命令包的长度
MOV R0,#CMD_BUFFER ;命令包缓冲区
CH375_TEST_DAT: MOV A,@R0
CPL A ;数据按位取反
MOVX @DPTR,A
INC R0
DJNZ R7,CH375_TEST_DAT ;将命令包数据按位取反写入批量端点的发送缓冲区
MOV BUF_LEN_L,#00H ;剩余数据长度为0,只发送一组数据
MOV BUF_LEN_H,#00H
LJMP CH375_INT_RET
CH375_INT_CMD4: CJNE A,#DEMO_CH451_CMD,CH375_INT_CMD5
; PC发送命令给CH451
MOV A,CMD_BUFFER_ADRH
MOV CH451_CMD_H,A ;高4位命令
MOV A,CMD_BUFFER_ADRL ;低8位命令
MOV CH451_CMD_L,A
; 为了防止在CH375中断服务程序打断主程序中的CH451_READ而执行CH451_WRITE产生错误
; 所以在此保存CH451的命令码由主程序在空闲时发给CH451
LJMP CH375_INT_RET
CH375_INT_CMD5: NOP ;未定义的命令码,不支持,放弃
LJMP CH375_INT_RET
; 接收下传的数据块,每组数据的长度不超过64字节
CH375_INT_DN1:
; 下面是向MCS51单片机的内部RAM保存下传的数据,速度是外部RAM快3倍
MOV R0,BUF_ADDR_L ;由于演示板中没有外部RAM,并且外部RAM的效率很低,所以用内部RAM示范
MOV R0,#40H ;为了防止做测试时误操作到数据区域00H-3FH,临时指定专用缓冲区
CH375_INT_DN0: MOVX A,@DPTR ;从批量端点的接收缓冲区读取数据
MOV @R0,A ;向内部RAM缓冲区保存接收到的下传数据
INC R0 ;在12MHz时钟是这种方法每复制1字节大概需要6uS
DJNZ R7,CH375_INT_DN0 ;继续取出数据直至结束
LJMP CH375_INT_RET
; 下面从MCS51单片机的外部RAM读取数据并上传,如果采用较高时钟并且具有双DPTR的单片机则速度可以快些
;CH375_INT_DN0: MOV DPTR,#CH375_DAT_PORT ;数据口地址
; MOVX A,@DPTR ;从批量端点的接收缓冲区读取数据
; MOV DPL,BUF_ADDR_L ;由于MCS51单片机读取外部RAM的效率很低
; MOV DPH,BUF_ADDR_H ;所以在12MHz时钟是这种方法每复制1字节大概需要18uS
; MOVX @DPTR,A ;向外部RAM缓冲区保存接收到的下传数据
; INC DPTR ;缓冲区地址增量
; MOV BUF_ADDR_L,DPL
; MOV BUF_ADDR_H,DPH
; DJNZ R7,CH375_INT_DN0 ;继续取出数据直至结束
; LJMP CH375_INT_RET
; USB批量数据发送成功
CH375_UP_OK:
; 假定在命令包中指定了总共需要上传的数据长度,则根据该长度上传数据
MOV A,BUF_LEN_L ;检查剩余长度
ORL A,BUF_LEN_H
JZ CH375_INT_UNLK ;剩余数据长度为0,没有数据需要发送,解锁后直接退出
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_END ;剩余长度不足一个数据包的最大长度64
MOV R7,#40H
MOV BUF_LEN_L,R5
MOV BUF_LEN_H,R6
SJMP CH375_UP_NEXT
CH375_UP_END: MOV R7,BUF_LEN_L
MOV BUF_LEN_L,#00H
MOV BUF_LEN_H,#00H
CH375_UP_NEXT: 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_UP1: MOV A,@R0 ;从内部RAM缓冲区取出准备上传的数据
INC R0 ;在12MHz时钟是这种方法每复制1字节大概需要6uS
MOVX @DPTR,A ;将数据写入批量端点的发送缓冲区
DJNZ R7,CH375_INT_UP1 ;继续写入数据直至结束
LJMP CH375_INT_UNLK
; 下面从MCS51单片机的外部RAM读取数据并上传,如果采用较高时钟并且具有双DPTR的单片机则速度可以快些
;CH375_INT_UP1: MOV DPL,BUF_ADDR_L ;由于MCS51单片机读取外部RAM的效率很低
; MOV DPH,BUF_ADDR_H ;所以在12MHz时钟是这种方法每复制1字节大概需要18uS
; MOVX A,@DPTR ;从外部RAM缓冲区取出准备上传的数据
; INC DPTR ;缓冲区地址增量
; MOV BUF_ADDR_L,DPL
; MOV BUF_ADDR_H,DPH
; MOV DPTR,#CH375_DAT_PORT ;数据口地址
; MOVX @DPTR,A ;将数据写入批量端点的发送缓冲区
; DJNZ R7,CH375_INT_UP1 ;继续写入数据直至结束
; LJMP CH375_INT_UNLK
; 收到上传成功中断后,在退出之前必须解锁USB缓冲区,以便继续收发数据
CH375_INT_UNLK: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;释放当前USB缓冲区
LJMP CH375_INT_RET
; USB中断数据发送成功
CH375_UP_INT_OK: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;释放当前USB缓冲区
CLR FLAG_INT_WAIT ;清中断等待标志,通知应用程序可以继续发送中断数据
LJMP CH375_INT_RET
;
;****************************************************************************
;
; 初始化子程序
CH451_INIT: CLR CH451_DIN ;先低后高,输出上升沿通知CH451选择4线串行接口
SETB CH451_DCLK ;置为默认的高电平
SETB CH451_DIN
SETB CH451_LOAD
SETB CH451_DOUT ;置为输入
; 下述三条指令用于键盘中断
CLR IT1 ;置外部信号为低电平触发
CLR IE1 ;清中断标志
CLR PX1 ;置低优先级
SETB EX1 ;允许键盘中断
RET
;
;
; 输出命令子程序
; ENTRY: B-ACC 待写的12位数据, 低8位在ACC中, 高4位在B的低4位中
; USE: ACC, B, R7
CH451_WRITE: CLR EX1 ;禁止键盘中断
CLR CH451_LOAD ;命令开始,此命令可以放在后面
MOV R7,#08H ;将ACC中8位送出
CH451_WRITE_8: RRC A ;低位在前,高位在后
CLR CH451_DCLK
MOV CH451_DIN,C ;送出一位数据
SETB CH451_DCLK ;产生时钟上升沿通知CH451输入位数据
DJNZ R7,CH451_WRITE_8 ;位数据未完继续
MOV A,B
MOV R7,#04H ;将B中4位送出
CH451_WRITE_4: RRC A ;低位在前,高位在后
CLR CH451_DCLK
MOV CH451_DIN,C ;送出一位数据
SETB CH451_DCLK ;产生时钟上升沿通知CH451输入位数据
DJNZ R7,CH451_WRITE_4 ;位数据未完继续
SETB CH451_LOAD ;产生加载上升沿通知CH451处理命令数据
SETB EX1 ;允许键盘中断
RET
;
;
; 输入键值子程序
; EXIT: ACC 键值数据
; USE: ACC, R7
CH451_READ: CLR EX1 ;禁止键盘中断
CLR CH451_LOAD ;命令开始
MOV A,#07H ;读取键值命令的高4位0111B
MOV R7,#04H ;忽略12位命令的低8位
CH451_READ_4: RRC A ;低位在前,高位在后
CLR CH451_DCLK
MOV CH451_DIN,C ;送出一位数据
SETB CH451_DCLK ;产生时钟上升沿锁通知CH451输入位数据
DJNZ R7,CH451_READ_4 ;位数据未完继续
SETB CH451_LOAD ;产生加载上升沿通知CH451处理命令数据
CLR A ;先清除键值单元以便移位
MOV R7,#07H ;读入7位键值
CH451_READ_7: MOV C,CH451_DOUT ;读入一位数据
CLR CH451_DCLK ;产生时钟下升沿通知CH451输出下一位
RLC A ;数据移入ACC,高位在前,低位在后
SETB CH451_DCLK
DJNZ R7,CH451_READ_7 ;位数据未完继续
CLR IE1 ;清中断标志,读操作过程中有低电平脉冲
SETB EX1 ;允许键盘中断
RET
;
;
; 键盘中断子程序
; USE: 堆栈6字节
CH451_INTER: PUSH PSW ;现场保护
PUSH ACC
CLR CH451_LOAD ;命令开始
MOV A,#0F7H ;读键值命令,忽略12位命令的低8位,高4位用作结束标志
CH451_INTER_4: SETB C ;在高位添0以检测位数据结束
RRC A ;低位在前,高位在后
CLR CH451_DCLK
MOV CH451_DIN,C ;送出一位数据
SETB CH451_DCLK ;产生时钟上升沿锁通知CH451输入位数据
CJNE A,#0FFH,CH451_INTER_4 ;位数据未完继续,共4位,完成后为0FFH
SETB CH451_LOAD ;产生加载上升沿通知CH451处理命令数据
MOV A,#0FCH ;该数据用以检测位数据结束
CH451_INTER_7: MOV C,CH451_DOUT ;读入一位数据
CLR CH451_DCLK ;产生时钟下升沿通知CH451输出下一位
RLC A ;数据移入ACC,高位在前,低位在后
SETB CH451_DCLK
JC CH451_INTER_7 ;位数据未完继续,共7位,完成后才移出0
MOV CH451_KEY,A ;保存键值
POP ACC
POP PSW
CLR IE1 ;清中断标志,该指令需根据实际情况作修改
RETI ;中断返回
;
;*********************************************************************************************************************
;
; 以毫秒为单位延时
; ENTRY: R7 延时毫秒数
; USE: ACC, R7
DELAY_MS: MOV A,#0FAH ;250*(1*6+2)*0.5=1000uS
DELAY_1MS: NOP
NOP
NOP
NOP
NOP
NOP
DJNZ ACC,DELAY_1MS ;每周期延时1毫秒
DJNZ R7,DELAY_MS
RET
;
;*********************************************************************************************************************
;
END
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -