?? ch375451.asm
字號:
; MOV BUF_ADDR_L,DPL
; MOV BUF_ADDR_H,DPH
; MOV DPTR,#CH375_DAT_PORT ;數(shù)據(jù)口地址
; MOVX @DPTR,A ;將數(shù)據(jù)寫入批量端點的發(fā)送緩沖區(qū)
; DJNZ R7,CH375_INT_UP0 ;繼續(xù)寫入數(shù)據(jù)直至結(jié)束
; LJMP CH375_INT_RET
CH375_INT_CMD3: CJNE A,#DEMO_TEST_DATA,CH375_INT_CMD4
; 測試數(shù)據(jù)傳輸命令,將PC機發(fā)來的當前命令包的所有數(shù)據(jù)按位取反后返回
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_WR_USB_DATA7
MOVX @DPTR,A ;向批量端點的發(fā)送緩沖區(qū)寫入數(shù)據(jù)塊
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
MOV DPTR,#CH375_DAT_PORT ;數(shù)據(jù)口地址
MOV A,#CONST_CMD_LEN
MOV R7,A
MOVX @DPTR,A ;首先寫入后續(xù)數(shù)據(jù)長度,也就是命令包的長度
MOV R0,#CMD_BUFFER ;命令包緩沖區(qū)
CH375_TEST_DAT: MOV A,@R0
CPL A ;數(shù)據(jù)按位取反
MOVX @DPTR,A
INC R0
DJNZ R7,CH375_TEST_DAT ;將命令包數(shù)據(jù)按位取反寫入批量端點的發(fā)送緩沖區(qū)
MOV BUF_LEN_L,#00H ;剩余數(shù)據(jù)長度為0,只發(fā)送一組數(shù)據(jù)
MOV BUF_LEN_H,#00H
LJMP CH375_INT_RET
CH375_INT_CMD4: CJNE A,#DEMO_CH451_CMD,CH375_INT_CMD5
; PC發(fā)送命令給CH451
MOV A,CMD_BUFFER_ADRH
MOV CH451_CMD_H,A ;高4位命令
MOV A,CMD_BUFFER_ADRL ;低8位命令
MOV CH451_CMD_L,A
; 為了防止在CH375中斷服務(wù)程序打斷主程序中的CH451_READ而執(zhí)行CH451_WRITE產(chǎn)生錯誤
; 所以在此保存CH451的命令碼由主程序在空閑時發(fā)給CH451
LJMP CH375_INT_RET
CH375_INT_CMD5: NOP ;未定義的命令碼,不支持,放棄
LJMP CH375_INT_RET
; 接收下傳的數(shù)據(jù)塊,每組數(shù)據(jù)的長度不超過64字節(jié)
CH375_INT_DN1:
; 下面是向MCS51單片機的內(nèi)部RAM保存下傳的數(shù)據(jù),速度是外部RAM快3倍
MOV R0,BUF_ADDR_L ;由于演示板中沒有外部RAM,并且外部RAM的效率很低,所以用內(nèi)部RAM示范
MOV R0,#40H ;為了防止做測試時誤操作到數(shù)據(jù)區(qū)域00H-3FH,臨時指定專用緩沖區(qū)
CH375_INT_DN0: MOVX A,@DPTR ;從批量端點的接收緩沖區(qū)讀取數(shù)據(jù)
MOV @R0,A ;向內(nèi)部RAM緩沖區(qū)保存接收到的下傳數(shù)據(jù)
INC R0 ;在12MHz時鐘是這種方法每復(fù)制1字節(jié)大概需要6uS
DJNZ R7,CH375_INT_DN0 ;繼續(xù)取出數(shù)據(jù)直至結(jié)束
LJMP CH375_INT_RET
; 下面從MCS51單片機的外部RAM讀取數(shù)據(jù)并上傳,如果采用較高時鐘并且具有雙DPTR的單片機則速度可以快些
;CH375_INT_DN0: MOV DPTR,#CH375_DAT_PORT ;數(shù)據(jù)口地址
; MOVX A,@DPTR ;從批量端點的接收緩沖區(qū)讀取數(shù)據(jù)
; MOV DPL,BUF_ADDR_L ;由于MCS51單片機讀取外部RAM的效率很低
; MOV DPH,BUF_ADDR_H ;所以在12MHz時鐘是這種方法每復(fù)制1字節(jié)大概需要18uS
; MOVX @DPTR,A ;向外部RAM緩沖區(qū)保存接收到的下傳數(shù)據(jù)
; INC DPTR ;緩沖區(qū)地址增量
; MOV BUF_ADDR_L,DPL
; MOV BUF_ADDR_H,DPH
; DJNZ R7,CH375_INT_DN0 ;繼續(xù)取出數(shù)據(jù)直至結(jié)束
; LJMP CH375_INT_RET
; USB批量數(shù)據(jù)發(fā)送成功
CH375_UP_OK:
; 假定在命令包中指定了總共需要上傳的數(shù)據(jù)長度,則根據(jù)該長度上傳數(shù)據(jù)
MOV A,BUF_LEN_L ;檢查剩余長度
ORL A,BUF_LEN_H
JZ CH375_INT_UNLK ;剩余數(shù)據(jù)長度為0,沒有數(shù)據(jù)需要發(fā)送,解鎖后直接退出
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 ;剩余長度不足一個數(shù)據(jù)包的最大長度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的發(fā)送緩沖區(qū)寫入數(shù)據(jù)塊
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
MOV DPTR,#CH375_DAT_PORT ;數(shù)據(jù)口地址
MOV A,R7 ;每次最多上傳64個字節(jié)的數(shù)據(jù)
MOVX @DPTR,A ;首先寫入后續(xù)數(shù)據(jù)長度
; 下面是從MCS51單片機的內(nèi)部RAM讀取數(shù)據(jù)并上傳,速度是外部RAM快3倍
MOV R0,BUF_ADDR_L ;由于演示板中沒有外部RAM,并且外部RAM的效率很低,所以用內(nèi)部RAM示范
CH375_INT_UP1: MOV A,@R0 ;從內(nèi)部RAM緩沖區(qū)取出準備上傳的數(shù)據(jù)
INC R0 ;在12MHz時鐘是這種方法每復(fù)制1字節(jié)大概需要6uS
MOVX @DPTR,A ;將數(shù)據(jù)寫入批量端點的發(fā)送緩沖區(qū)
DJNZ R7,CH375_INT_UP1 ;繼續(xù)寫入數(shù)據(jù)直至結(jié)束
LJMP CH375_INT_UNLK
; 下面從MCS51單片機的外部RAM讀取數(shù)據(jù)并上傳,如果采用較高時鐘并且具有雙DPTR的單片機則速度可以快些
;CH375_INT_UP1: MOV DPL,BUF_ADDR_L ;由于MCS51單片機讀取外部RAM的效率很低
; MOV DPH,BUF_ADDR_H ;所以在12MHz時鐘是這種方法每復(fù)制1字節(jié)大概需要18uS
; MOVX A,@DPTR ;從外部RAM緩沖區(qū)取出準備上傳的數(shù)據(jù)
; INC DPTR ;緩沖區(qū)地址增量
; MOV BUF_ADDR_L,DPL
; MOV BUF_ADDR_H,DPH
; MOV DPTR,#CH375_DAT_PORT ;數(shù)據(jù)口地址
; MOVX @DPTR,A ;將數(shù)據(jù)寫入批量端點的發(fā)送緩沖區(qū)
; DJNZ R7,CH375_INT_UP1 ;繼續(xù)寫入數(shù)據(jù)直至結(jié)束
; LJMP CH375_INT_UNLK
; 收到上傳成功中斷后,在退出之前必須解鎖USB緩沖區(qū),以便繼續(xù)收發(fā)數(shù)據(jù)
CH375_INT_UNLK: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;釋放當前USB緩沖區(qū)
LJMP CH375_INT_RET
; USB中斷數(shù)據(jù)發(fā)送成功
CH375_UP_INT_OK: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;釋放當前USB緩沖區(qū)
CLR FLAG_INT_WAIT ;清中斷等待標志,通知應(yīng)用程序可以繼續(xù)發(fā)送中斷數(shù)據(jù)
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 ;置外部信號為低電平觸發(fā)
CLR IE1 ;清中斷標志
CLR PX1 ;置低優(yōu)先級
SETB EX1 ;允許鍵盤中斷
RET
;
;
; 輸出命令子程序
; ENTRY: B-ACC 待寫的12位數(shù)據(jù), 低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 ;送出一位數(shù)據(jù)
SETB CH451_DCLK ;產(chǎn)生時鐘上升沿通知CH451輸入位數(shù)據(jù)
DJNZ R7,CH451_WRITE_8 ;位數(shù)據(jù)未完繼續(xù)
MOV A,B
MOV R7,#04H ;將B中4位送出
CH451_WRITE_4: RRC A ;低位在前,高位在后
CLR CH451_DCLK
MOV CH451_DIN,C ;送出一位數(shù)據(jù)
SETB CH451_DCLK ;產(chǎn)生時鐘上升沿通知CH451輸入位數(shù)據(jù)
DJNZ R7,CH451_WRITE_4 ;位數(shù)據(jù)未完繼續(xù)
SETB CH451_LOAD ;產(chǎn)生加載上升沿通知CH451處理命令數(shù)據(jù)
SETB EX1 ;允許鍵盤中斷
RET
;
;
; 輸入鍵值子程序
; EXIT: ACC 鍵值數(shù)據(jù)
; 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 ;送出一位數(shù)據(jù)
SETB CH451_DCLK ;產(chǎn)生時鐘上升沿鎖通知CH451輸入位數(shù)據(jù)
DJNZ R7,CH451_READ_4 ;位數(shù)據(jù)未完繼續(xù)
SETB CH451_LOAD ;產(chǎn)生加載上升沿通知CH451處理命令數(shù)據(jù)
CLR A ;先清除鍵值單元以便移位
MOV R7,#07H ;讀入7位鍵值
CH451_READ_7: MOV C,CH451_DOUT ;讀入一位數(shù)據(jù)
CLR CH451_DCLK ;產(chǎn)生時鐘下升沿通知CH451輸出下一位
RLC A ;數(shù)據(jù)移入ACC,高位在前,低位在后
SETB CH451_DCLK
DJNZ R7,CH451_READ_7 ;位數(shù)據(jù)未完繼續(xù)
CLR IE1 ;清中斷標志,讀操作過程中有低電平脈沖
SETB EX1 ;允許鍵盤中斷
RET
;
;
; 鍵盤中斷子程序
; USE: 堆棧6字節(jié)
CH451_INTER: PUSH PSW ;現(xiàn)場保護
PUSH ACC
CLR CH451_LOAD ;命令開始
MOV A,#0F7H ;讀鍵值命令,忽略12位命令的低8位,高4位用作結(jié)束標志
CH451_INTER_4: SETB C ;在高位添0以檢測位數(shù)據(jù)結(jié)束
RRC A ;低位在前,高位在后
CLR CH451_DCLK
MOV CH451_DIN,C ;送出一位數(shù)據(jù)
SETB CH451_DCLK ;產(chǎn)生時鐘上升沿鎖通知CH451輸入位數(shù)據(jù)
CJNE A,#0FFH,CH451_INTER_4 ;位數(shù)據(jù)未完繼續(xù),共4位,完成后為0FFH
SETB CH451_LOAD ;產(chǎn)生加載上升沿通知CH451處理命令數(shù)據(jù)
MOV A,#0FCH ;該數(shù)據(jù)用以檢測位數(shù)據(jù)結(jié)束
CH451_INTER_7: MOV C,CH451_DOUT ;讀入一位數(shù)據(jù)
CLR CH451_DCLK ;產(chǎn)生時鐘下升沿通知CH451輸出下一位
RLC A ;數(shù)據(jù)移入ACC,高位在前,低位在后
SETB CH451_DCLK
JC CH451_INTER_7 ;位數(shù)據(jù)未完繼續(xù),共7位,完成后才移出0
MOV CH451_KEY,A ;保存鍵值
POP ACC
POP PSW
CLR IE1 ;清中斷標志,該指令需根據(jù)實際情況作修改
RETI ;中斷返回
;
;*********************************************************************************************************************
;
; 以毫秒為單位延時
; ENTRY: R7 延時毫秒數(shù)
; 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
;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -