?? ch375a51.asm
字號:
; CH372, CH375
; Interface Program for MCS-51
; 使用內置固件的USB設備方式
;
; Website: http://winchiphead.com
; Email: tech@winchiphead.com
; Author: W.ch 2003.09
;
;****************************************************************************
; 程序運行環境
;
;CH375_CS_ BIT P2.7 ;MCS-51單片機的A15引腳,用于CH375片選,不必定義
;CH375_A0 BIT P2.0 ;MCS-51單片機的A8引腳,用于CH375地址0,不必定義,也可用外部74373鎖存的A0地址
;CH375_INT_ BIT P3.2 ;MCS-51單片機的INT0引腳,用于CH375中斷請求,無需定義
;CH375_WR_ BIT P3.6 ;MCS-51單片機的RD引腳,用于CH375寫選通,無需定義
;CH375_RD_ BIT P3.7 ;MCS-51單片機的WR引腳,用于CH375讀選通,無需定義
;
; 本程序適用于時鐘頻率不高于24MHz的標準MCS-51單片機, 如果高于24MHz則應該適當增加延時, 如果低于24MHz則可以適當減少延時
;
; 需要主程序定義的參數
CH375_CMD_PORT EQU 0BDF1H ;CH375命令口的地址,地址譯碼后自動片選
CH375_DAT_PORT EQU 0BCF0H ;CH375命令口的地址,地址譯碼后自動片選
;
; 定義自己的USB設備的廠商VID是4348H, 產品PID是5537H
;USB_VENDOR_ID_L EQU 48H ;定義VENDOR ID的低字節
;USB_VENDOR_ID_H EQU 43H ;定義VENDOR ID的高字節
;USB_PRODUCT_ID_L EQU 37H ;定義PRODUCT ID的低字節
;USB_PRODUCT_ID_H EQU 55H ;定義PRODUCT ID的高字節
;
RECV_LEN DATA 3FH ;剛接收到的數據的長度
RECV_BUFFER DATA 40H ;數據緩沖區,用于保存接收到的下傳數據,長度為0到64字節
;SEND_LEN DATA 3EH ;準備下次發送的數據長度
;SEND_BUFFER DATA 80H ;準備下次發送的數據緩沖區
; 由于MCS-51單片機存取外部RAM的讀寫速度低于內部RAM, 并且需要用到DPTR, 所以讀寫速度較慢, 其程序可以參考本程序修改
;
; 定義位標志
FLAG_SEND_WAIT BIT 20H.1 ;發送等待標志,1指示有數據塊正在CH375中等待發送
FLAG_INT_WAIT BIT 20H.2 ;中斷數據等待發送標志,1指示有中斷數據正在CH375中等待發送
;
;
$INCLUDE (CH375INC.ASM)
;
;****************************************************************************
;
;對外接口子程序,僅供參考
;
; 1. CH375_INIT 初始化子程序
; USE: ACC, R7, DPTR
;
; 2. CH375_UPLOAD 上傳數據塊子程序(通過批量端點上傳)
; ENTRY: R0 指向存放了準備上傳數據的緩沖區, R7 準備上傳的數據長度, 有效數值是0到64
; USE: ACC, R0, R7, DPTR
;
; 3. CH375_UP_INT 上傳中斷數據子程序(通過中斷端點上傳),可選子程序
; ENTRY: R0 指向存放了準備上傳數據的緩沖區, R7 準備上傳的數據長度, 有效數值是0到8
; USE: ACC, R0, R7, DPTR
;
; 4. CH375_INTER 中斷服務子程序
; USE: 堆棧8字節
;
;****************************************************************************
;主程序的例子
; ORG 0000H ;復位后單片機入口
; LJMP START
; ORG 0003H ;CH375中斷
; LJMP CH375_INTER
;
;START: NOP
; ...
; CALL CH375_INIT ;初始化
; ...
; SETB EA ;允許中斷
; ...
;WAIT_REQUEST: NOP
; SJMP WAIT_REQUEST ;主循環
;
;****************************************************************************
;
; 初始化子程序
; USE: ACC, R7, DPTR
CH375_INIT: CLR FLAG_SEND_WAIT ;清發送等待標志,1指示有數據塊正在CH375中等待發送
CLR FLAG_INT_WAIT ;清中斷數據發送等待標志,1指示有中斷數據正在CH375中等待發送
; 測試CH375是否正常工作,可選操作
; MOV DPTR,#CH375_CMD_PORT ;命令口地址
; MOV A,#CMD_CHECK_EXIST
; MOVX @DPTR,A ;測試CH375是否正常工作,可選操作
; NOP ;如果時鐘頻率低于16MHz則無需該指令延時
; DEC DPL ;數據口地址
; MOV A,#55H
; MOVX @DPTR,A ;寫入測試數據
; NOP ;如果時鐘頻率低于16MHz則無需該指令延時
; CPL A
; MOV R7,A ;取反數據
; MOVX A,@DPTR ;返回數據應該是測試數據取反
; XRL A,R7
; JZ CH375_INIT_OK ;測試通過
; MOV DPTR,#CH375_CMD_PORT ;命令口地址
; MOV A,#CMD_RESET_ALL
; MOV R7,#50H ;多次重復發命令
;CH375_INIT_HR: MOVX @DPTR,A ;執行硬件復位
; DJNZ R7,CH375_INIT_HR
; 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則無需該指令延時
; DEC DPL ;數據口地址
; MOV A,#USB_VENDOR_ID_L
; MOVX @DPTR,A ;寫入廠商ID的低字節
; MOV A,#USB_VENDOR_ID_H
; MOVX @DPTR,A ;寫入廠商ID的高字節
; MOV A,#USB_PRODUCT_ID_L
; MOVX @DPTR,A ;寫入產品ID的低字節
; MOV A,#USB_PRODUCT_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則無需該指令延時
DEC DPL ;數據口地址
MOV A,#02H
MOVX @DPTR,A ;設置為使用內置固件的USB設備方式
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
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: NOP ;為了防止計算機程序沒有讀取數據而導致單片機一直在此等待,可以計算超時,參考CH375_UP_INT子程序
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則無需該指令延時
DEC DPL ;數據口地址
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
;
; 上傳中斷數據子程序(通過中斷端點上傳),可選子程序
; ENTRY: R0 指向存放了準備上傳數據的緩沖區, R7 準備上傳的數據長度, 有效數值是0到8
; USE: ACC, R0, R7, DPTR
CH375_UP_INT: MOV A,#0FFH
CH375_UP_INT_W: JNB FLAG_INT_WAIT,CH375_UP_INT_G ;前次中斷數據已經被PC機取走則繼續
NOP ;等待發送中斷數據
NOP
NOP ;最多等待2毫秒,以12MHz時鐘計算
NOP
DJNZ ACC,CH375_UP_INT_W ;繼續等待,滿2毫秒后超時,建議將超時設置為較大的值,可以是正常情況下應該被取走的時間的2倍
; 如果未與計算機相連,或者計算機中的應用程序未運行,則會出現超時,否則不超過1毫秒中斷數據就應該被PC機取走
CH375_UP_INT_G: CLR EX0 ;為了防止中途被中斷而亂了順序,必須先禁止中斷
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_WR_USB_DATA5
MOVX @DPTR,A ;向USB端點1的發送緩沖區寫入數據塊
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
DEC DPL ;數據口地址
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 FLAG_INT_WAIT ;置中斷等待標志
SETB EX0 ;允許中斷
RET
;
; 中斷服務子程序
; USE: 堆棧8字節
CH375_INTER: PUSH PSW ;現場保護
PUSH ACC
PUSH DPL
PUSH DPH
PUSH 01H ;R1
PUSH 02H ;R2
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_GET_STATUS
MOVX @DPTR,A ;獲取中斷狀態并取消中斷請求
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
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批量數據接收成功,USB端點2的OUT
CH375_INT_1: CJNE A,#USB_INT_EP2_IN,CH375_INT_2 ;批量端點上傳成功,發送數據成功
LJMP CH375_UP_OK ;USB批量數據發送成功,USB端點2的IN
CH375_INT_2: CJNE A,#USB_INT_EP1_IN,CH375_INT_3 ;中斷端點上傳成功,發送中斷數據成功
LJMP CH375_UP_INT_OK ;USB中斷數據發送成功,USB端點1的IN
CH375_INT_3: CJNE A,#USB_INT_EP1_OUT,CH375_INT_4 ;輔助端點下傳成功,接收到輔助數據
LJMP CH375_DN_AUX_OK ;USB輔助數據接收成功,USB端點1的OUT
CH375_INT_4: ;如果需要在USB總線掛起時使CH375進入低功耗模式,那么還應該處理USB_INT_USB_SUSPEND和USB_INT_WAKE_UP中斷狀態
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;釋放當前USB緩沖區
SJMP CH375_INT_RET
CH375_INT_RET: POP 02H ;R2
POP 01H ;R1
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則無需該指令延時
NOP ;如果時鐘頻率低于16MHz則無需該指令延時
MOV DPTR,#CH375_DAT_PORT ;數據口地址
MOVX A,@DPTR ;首先讀取后續數據長度
MOV R2,A
JZ CH375_INT_RET ;長度為0,沒有數據則直接退出
MOV RECV_LEN,A
MOV R1,#RECV_BUFFER ;接收緩沖區
CH375_INT_RECV: MOVX A,@DPTR ;接收數據
MOV @R1,A
INC R1
DJNZ R2,CH375_INT_RECV ;繼續接收數據直至結束
; CALL PROCESS ;分析下傳數據并準備應答
LJMP CH375_INT_RET
; USB批量數據發送成功
CH375_UP_OK: NOP
; MOV A,SEND_LEN
; JZ CH375_INT_UNLK ;剩余長度為0,沒有數據需要發送,解鎖后退出
; 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,SEND_LEN
; MOVX @DPTR,A ;首先寫入后續數據長度
; MOV R1,#SEND_BUFFER ;發送緩沖區
;CH375_INT_SEND: MOV A,@R1
; MOVX @DPTR,A ;發送數據
; INC R1
; DJNZ SEND_LEN,CH375_INT_SEND ;繼續發送數據直至結束
CH375_INT_UNLK: MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;釋放當前USB緩沖區
CLR FLAG_SEND_WAIT ;發送完成
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
; USB輔助數據接收成功,輔助端點可以用于計算機端向單片機端發送包,本程序未用到,輔助數據的接收可以參考批量端點
CH375_DN_AUX_OK:
MOV DPTR,#CH375_CMD_PORT ;命令口地址
MOV A,#CMD_UNLOCK_USB
MOVX @DPTR,A ;釋放當前USB緩沖區
LJMP CH375_INT_RET
;
;****************************************************************************
;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -