?? ch372frm.c
字號:
/*
; 單片機通過CH372或者CH375連接到PC機進行USB通訊的框架程序
; 可以用include直接包含到應用系統的主程序中,或者添加到工程項目中
;
; Website: http://winchiphead.com
; Email: tech@winchiphead.com
; V1.0 @2004.09, V1.1 @2004.12
;****************************************************************************
*/
/* C語言, 適用用大多數單片機,包括MCS51以及其它內核的單片機 */
/* 如果單片機類型或者硬件資源不同時, 該程序應該根據需要進行局部修改 */
#include "CH375INC.H"
#ifdef __CX51__
#ifndef __C51__
#define __C51__ 1
#endif
#endif
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
#ifdef __C51__
typedef unsigned char idata *PUINT8;
typedef unsigned char volatile xdata IOPORT;
#pragma NOAREGS
#include <reg52.h>
#else
typedef unsigned char *PUINT8;
typedef unsigned char volatile IOPORT;
#endif
#define DELAY_START_VALUE 1 /* 根據單片機的時鐘選擇延時初值 */
/*#define MY_USB_VENDOR_ID 0x4348*/ /* 定義自己的USB設備的廠商ID */
/*#define MY_USB_PRODUCT_ID 0x5537*/ /* 定義自己的USB設備的產品ID */
/*#define ENABLE_USB_SUSPEND 1*/ /* 檢查USB總線的掛起狀態,便于進入低功耗模式 */
IOPORT CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址,根據實際硬件電路進行修改 */
IOPORT CH375_DAT_PORT _at_ 0xBCF0; /* CH375數據端口的I/O地址,根據實際硬件電路進行修改 */
/* 延時1微秒,不精確,需要根據硬件實際情況調整 */
void Delay1us( )
{
#if DELAY_START_VALUE != 0
UINT8 i;
for ( i=DELAY_START_VALUE; i!=0; i-- );
#endif
}
/* 延時2微秒,不精確,需要根據硬件實際情況調整 */
void Delay2us( )
{
UINT8 i;
for ( i=DELAY_START_VALUE*2+1; i!=0; i-- );
}
/* 與CH372/CH375有關的基本I/O操作 */
void CH375_WR_CMD_PORT( UINT8 cmd ) { /* 向CH375的命令端口寫入命令,周期不小于4uS,如果單片機較快則延時 */
Delay2us();
CH375_CMD_PORT=cmd;
Delay2us();
}
void CH375_WR_DAT_PORT( UINT8 dat ) { /* 向CH375的數據端口寫入數據,周期不小于1.5uS,如果單片機較快則延時 */
CH375_DAT_PORT=dat;
Delay1us(); /* 如果是MCS51單片機,因其較慢,所以實際上無需延時 */
}
UINT8 CH375_RD_DAT_PORT( void ) { /* 從CH375的數據端口讀出數據,周期不小于1.5uS,如果單片機較快則延時 */
Delay1us(); /* 如果是MCS51單片機,因其較慢,所以實際上無需延時 */
return( CH375_DAT_PORT );
}
/* CH375初始化子程序 */
void CH375_Init( void ) {
UINT8 i;
#ifdef MY_USB_VENDOR_ID
#ifdef MY_USB_PRODUCT_ID
/* 設置外部自定義的USB設備VID和PID,可選操作,不執行該命令則使用默認的VID和PID,
如果設置使用自定義的ID,那么計算機端驅動程序INF安裝文件中的"USB\VID_4348&PID_5537"需要進行類似修改 */
CH375_WR_CMD_PORT( CMD_SET_USB_ID ); /* 設置外部自定義的USB設備VID和PID,可選操作 */
CH375_WR_DAT_PORT( (UINT8)MY_USB_VENDOR_ID ); /* 寫入廠商ID的低字節 */
CH375_WR_DAT_PORT( (UINT8)(MY_USB_VENDOR_ID>>8) ); /* 寫入廠商ID的高字節 */
CH375_WR_DAT_PORT( (UINT8)MY_USB_PRODUCT_ID ); /* 寫入產品ID的低字節 */
CH375_WR_DAT_PORT( (UINT8)(MY_USB_PRODUCT_ID>>8) ); /* 寫入產品ID的高字節 */
#endif
#endif
/* 設置USB工作模式, 必要操作 */
CH375_WR_CMD_PORT( CMD_SET_USB_MODE );
CH375_WR_DAT_PORT( 2 ); /* 設置為使用內置固件的USB設備方式 */
for ( i=100; i!=0; i-- ) if ( CH375_RD_DAT_PORT( ) == CMD_RET_SUCCESS ) break; /* 等待操作成功,通常需要等待10uS-20uS */
/* if ( i == 0 ) { CH372/CH375芯片內部或者物理連接存在硬件錯誤 }; */
#ifdef ENABLE_USB_SUSPEND
/* 設置檢查USB總線掛起狀態,便于在USB總線掛起時使CH375也進入低功耗狀態 */
CH375_WR_CMD_PORT( CMD_CHK_SUSPEND ); /* 設置檢查USB總線掛起狀態的方式 */
CH375_WR_DAT_PORT( 0x10 );
CH375_WR_DAT_PORT( 0x04 ); /* 以50mS為間隔檢查USB掛起 */
#endif
/* 下面啟用USB中斷,CH375的INT#引腳可以連接到單片機的中斷引腳,中斷為低電平有效或者下降沿有效,
如果不使用中斷,那么也可以用查詢方式,由單片機程序查詢CH375的INT#引腳為低電平則說明CH375請求中斷 */
#ifdef __C51__
IT0 = 0; /* 置外部信號為低電平觸發 */
IE0 = 0; /* 清中斷標志 */
EX0 = 1; /* 允許CH375中斷,假定CH375的INT#引腳連接到單片機的INT0 */
#endif
}
UINT8 UsbLength; /* USB數據緩沖區中數據的長度 */
UINT8 UsbBuffer[ CH375_MAX_DATA_LEN ]; /* USB數據緩沖區 */
/* CH375中斷服務程序,假定CH375的INT#引腳連接到單片機的INT0,使用寄存器組1 */
void mCH375Interrupt( void ) interrupt 0 using 1 {
UINT8 IntStatus;
UINT8 cnt;
PUINT8 buf;
CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 獲取中斷狀態并取消中斷請求 */
IntStatus = CH375_RD_DAT_PORT( ); /* 獲取中斷狀態 */
/* IE0 = 0; 清中斷標志,與單片機硬件有關,對應于INT0中斷 */
switch( IntStatus ) { /* 分析中斷狀態 */
case USB_INT_EP2_OUT: /* 批量端點下傳成功,接收到數據 */
CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 從當前USB中斷的端點緩沖區讀取數據塊,并釋放緩沖區 */
/* 如果使用CMD_RD_USB_DATA0命令碼,那么讀取數據塊后不會自動釋放緩沖區,需要CMD_UNLOCK_USB命令后才釋放 */
UsbLength = cnt = CH375_RD_DAT_PORT( ); /* 首先讀取后續數據長度 */
if ( cnt ) { /* 接收到數據放到緩沖區中 */
buf = UsbBuffer; /* 指向緩沖區 */
do {
*buf = CH375_RD_DAT_PORT( ); /* 接收命令包的數據 */
buf ++;
} while ( -- cnt );
}
else break; /* 長度為0,沒有數據,在某些應用中也可以將長度0定義為一種特殊命令 */
/* 分析接收到的數據并處理,此處略去,下面演示回傳數據 */
CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); /* 向USB端點2的發送緩沖區寫入數據塊 */
cnt = UsbLength;
CH375_WR_DAT_PORT( cnt ); /* 首先寫入后續數據長度 */
if ( cnt ) { /* 將緩沖區中的數據發出 */
buf = UsbBuffer; /* 指向緩沖區 */
do {
CH375_WR_DAT_PORT( *buf ); /* 寫入數據到CH375 */
buf ++;
} while ( -- cnt );
}
break;
case USB_INT_EP2_IN: /* 批量端點上傳成功,數據發送成功 */
/* 如果還有數據需要接著發送,可在此通過CMD_WR_USB_DATA7命令寫入,參考前面的回傳 */
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區,收到上傳成功中斷后,必須解鎖USB緩沖區,以便繼續收發 */
break;
case USB_INT_EP1_IN: /* 中斷端點上傳成功,中斷數據發送成功 */
/* 中斷端點可以用于單片機及時通知計算機端,本程序未用到 */
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區 */
break;
case USB_INT_EP1_OUT: /* 輔助端點下傳成功,接收到輔助數據 */
/* 輔助端點可以用于計算機端向單片機端發送包,本程序未用到,輔助數據的接收可以參考批量端點 */
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區 */
break;
#ifdef ENABLE_USB_SUSPEND
/* 默認情況下不會出現這些中斷狀態,只有當執行相應的命令后才會出現這些狀態,根據需要處理 */
case USB_INT_USB_SUSPEND: /* USB總線掛起事件,只有當執行過CMD_CHK_SUSPEND命令后才可能出現該中斷狀態 */
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區 */
CH375_WR_CMD_PORT( CMD_ENTER_SLEEP ); /* 這是可選操作,進入低功耗睡眠掛起狀態 */
break;
case USB_INT_WAKE_UP: /* 從睡眠中被喚醒事件,只有當執行過CMD_ENTER_SLEEP命令后才可能出現該中斷狀態 */
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區 */
break;
#endif
default:
/* 內置固件的USB方式下不應該出現其它中斷狀態,如果啟用USB總線掛起檢查,那么還要處理USB總線掛起和睡眠喚醒事件 */
CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區 */
break;
}
}
/*
main( void ) {
CH375_Init( );
EA = 1;
while ( 1 );
}
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -