?? demo.c
字號:
// 2003.09.08, 2003.12.28, 2004.12.10, 2004.12.28
//****************************************
//** Copyright (C) W.ch 1999-2004 **
//** Web: http://www.winchiphead.com **
//****************************************
//** EXE for USB interface chip CH375 **
//** C, VC5.0 **
//****************************************
//
// USB總線接口芯片CH375的應用層演示程序 V1.2
// 南京沁恒電子有限公司 作者: W.ch 2004.12
// CH375-EXE V1.2 , Support: Ctrl/Bulk/Int
// 運行環境: Windows 98/ME, Windows 2000/XP
// support USB chip: CH372/CH375
//
#define mTHIS_VERSION 0x12 // 當前版本
#define mTHIS_VER_STR "1.2" // 當前版本字符串
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CH375DLL.H" // CH372/CH375的動態鏈接庫
#pragma comment(lib,"CH375DLL")
#include "DEMO.H"
#define IDC_INT_PRESS 2222 // 按鍵按下事件信號
#define IDC_INT_RELEASE 2223 // 按鍵釋放事件信號
#define IDC_INT_DEVARRIVAL 2224 // 設備插上事件信號
#define IDC_INT_DEVREMOVAL 2225 // 設備拔出事件信號
typedef struct _COMMAND_PACKET { // 自定義的命令包結構
UCHAR mCommandCode; // 命令請求碼,見下面的定義
UCHAR mCommandCodeNot; // 命令碼的反碼,用于校驗命令包
union {
UCHAR mParameter[5]; // 參數
struct {
UCHAR mBufferID; // 緩沖區識別碼,本程序針對MCS51單片機定義: 1-專用功能寄存器SFR, 2-內部RAM, 3-外部RAM, 不過本程序實際只演示內部RAM
USHORT mBufferAddr; // 讀寫操作的起始地址,尋址范圍是0000H-0FFFFH,低字節在前
USHORT mLength; // 數據塊總長度,低字節在前
};
};
} mCOMMAND_PACKET, *mpCOMMAND_PACKET;
#define CONST_CMD_LEN 0x07 // 命令塊的長度
// 由于命令與數據都是通過數據下傳管道(USB端點2的OUT)下傳, 為了防止兩者混淆,
// 我們可以在計算機應用程序與單片機程序之間約定, 命令塊的長度總是7, 而數據塊的長度肯定不是7, 例如64,32等
// 另外, 可以約定, 命令塊的首字節是命令碼, 等等
// 本程序約定命令碼: 80H-0FFH是通用命令,適用于各種應用
// 00H-7FH是專用命令,針對各種應用特別定義
// 通用命令
#define DEF_CMD_GET_INFORM 0x90 // 獲取下位機的說明信息,長度不超過64個字符,字符串以00H結束
#define DEF_CMD_TEST_DATA 0x91 // 測試命令,下位機將PC機發來的命令包的所有數據取反后返回
#define DEF_CMD_CLEAR_UP 0xA0 // 在上傳數據塊之前進行同步,實際是讓下位機清除上傳緩沖區的已有內容
#define DEF_CMD_UP_DATA 0xA1 // 從下位機的指定地址的緩沖區中讀取數據塊(上傳數據塊)
#define DEF_CMD_DOWN_DATA 0xA2 // 向下位機的指定地址的緩沖區中寫入數據塊(下傳數據塊)
// 專用命令
#define DEMO_CH451_CMD 0x56 // PC發送命令給CH451,用于演示CH451的功能
// 對于MCS51單片機在使用通用命令時,還需要指定緩沖區識別碼
#define ACCESS_MCS51_SFR 1 // 讀寫51單片機的SFR
#define ACCESS_MCS51_IRAM 2 // 讀寫51單片機的內部RAM
#define ACCESS_MCS51_XRAM 3 // 讀寫51單片機的外部RAM
HINSTANCE mSaveInstance; // 實例
HWND mSaveDialogMain; // 主對話框
HWND mEnterDialog; // 輸入數據對話框
UCHAR mEnterBuffer[8]; // 數據輸入緩沖區
UINT mBufferLength = 0; // 緩沖區內的有效數據長度
UINT mShowLED = 0; // 不為0則LED亮
UINT mKeyCode = 0xff; // 按鍵編號
UINT mIndex = 0; // 如果有多個CH372/CH375則指示序號
CHAR mCaptionInform[] = " 信息提示 ";
BOOL openflag=FALSE;
BOOL Arrivalflag=FALSE; //是設備插上
LRESULT CALLBACK mDialogMain(HWND,UINT,WPARAM,LPARAM); //主對話框調用程序
LRESULT CALLBACK mDialogEnter(HWND,UINT,WPARAM,LPARAM); //輸入數字對話框調用程序
VOID SendCH452Command(); //發送CH452命令.//mEnterBuffer存儲的是三位十六進制的命令字符
UCHAR mCharToBcd(UCHAR); // 將ASCII字符轉換為一位BCD碼
VOID mSyncKeyboard(HWND,UINT); // 同步按鍵顯示
VOID CALLBACK mInterruptEvent(PUCHAR); // 中斷服務程序
UINT mDownloadData( UCHAR *iBuffer, UINT iLength ); // 下傳數據塊,返回實際傳輸長度
UINT mUploadData( UCHAR *iBuffer, UINT iLength ); // 上傳數據塊,返回實際傳輸長度
VOID CALLBACK NotifyRoutine (ULONG iEventStatus ); // 設備事件通知回調程序
VOID Testcommunication(); //測試PC機與單片機之間的USB通訊
VOID devremoval(); //設備移除處理函數
VOID devarrival(); //設備插入處理函數
//程序入口
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd )
{
CHAR *CmdLine;
CmdLine = lpCmdLine;
mSaveInstance = hInstance;
if ( CmdLine != NULL && *CmdLine >= '0' && *CmdLine <= '9' ) { // 在命令行中指定CH375設備序號
// 如果運行DEMO時在命令行指定參數0至9,則對應CH375設備序號0-9,如果沒有命令行參數則默認為CH375設備序號0
// 例如,執行"DEMO 1"對應1#CH375設備,執行"DEMO 8"對應8號CH375設備
// 命令行帶參數可以通過Windows操作系統的"開始"中的"運行"窗口執行,或者在DOS窗口中執行
mIndex = *CmdLine - '0';
}
return( DialogBox( hInstance, "IDD_MAIN", NULL, mDialogMain ) ); //調用主對話框
}
//主對話框事件
LRESULT CALLBACK mDialogMain( HWND hDialog, UINT uMessage, WPARAM wParam, LPARAM lParam )
{
mCOMMAND_PACKET mDemoReq;
UINT mLength;
switch( uMessage )
{
case WM_INITDIALOG: //初始化
mSaveDialogMain = hDialog;
// 需要使用DLL則需要先加載
CheckDlgButton(mSaveDialogMain,IDC_WordShift,BST_CHECKED);
CheckDlgButton(mSaveDialogMain,IDC_SegUnLight,BST_CHECKED);
if ( LoadLibrary( "CH375DLL.DLL" ) == NULL ) // 加載DLL失敗,可能未安裝到系統中
{
MessageBox( hDialog, "無法加載CH372/CH375的DLL", mCaptionInform, MB_ICONSTOP | MB_OK );
EndDialog( hDialog, 0x81 ); // 關閉對話框
return( TRUE );
}
/* 為了從多個CH372/CH375設備中找出自己的設備,應用程序可以查詢USB設備的ID號(廠商ID和產品ID),直到ID比較正確,可以在打開設備之前或者之后查詢
#define MY_VENDOR_ID 0x4348
#define MY_PRODUCT_ID 0x5537
for ( mIndex = 0; mIndex < mCH375_MAX_NUMBER; mIndex ++ )
{
if ( CH375GetUsbID( mIndex ) == ( ( MY_PRODUCT_ID << 16 ) | MY_VENDOR_ID ) ) break; // 獲取USB設備ID,返回數據中,低16位為廠商ID,高16位為產品ID,錯誤時返回全0(無效ID)
}
if ( mIndex >= mCH375_MAX_NUMBER )
{
MessageBox( hDialog, "找不到指定的CH372/CH375設備", mCaptionInform, MB_ICONSTOP | MB_OK );
EndDialog( hDialog, 0x81 ); // 關閉對話框
return( TRUE );
}*/
if(!CH375SetDeviceNotify(mIndex,NULL,NotifyRoutine)) //設置設備插拔監視
MessageBox( hDialog, "設置監視CH372/CH375設備插拔失敗", mCaptionInform, MB_ICONSTOP | MB_OK );
if ( CH375OpenDevice( mIndex ) == INVALID_HANDLE_VALUE ) // 打開設備
{
openflag=FALSE;
NotifyRoutine(CH375_DEVICE_REMOVE); //設備沒打開,按鈕禁用
return ( TRUE );
break;
}
else //打開成功
openflag=TRUE;
NotifyRoutine(CH375_DEVICE_ARRIVAL); //設備打開,按鈕可用
CH375SetTimeout( mIndex, 3000, 3000 ); // 設置USB數據讀寫的超時,超過3000mS未完成讀寫將強制返回,避免一直等待下去
Testcommunication(); // 測試PC機與單片機之間的USB通訊,僅作演示,本身沒有意義
/* 下面是下傳/上傳數據塊的例子
{
UCHAR mBuffer[4096];
mBuffer[0]=data; // 準備下傳的數據
mLength = mDownloadData( mBuffer, 4096 ) ; // 將數據塊從計算機下傳給單片機,返回實際傳輸長度
mLength = mUploadData( mBuffer, 4096 ) ; // 從單片機上傳數據塊到計算機,返回實際傳輸長度
}*/
CH375SetExclusive( mIndex, FALSE ); // 臨時設置共享使用當前CH375設備,因為下面設置中斷服務程序時需要使用當前這個CH375設備
// 下面加載中斷服務程序,中斷服務程序是在應用層執行的,其線程優先級是THREAD_PRIORITY_TIME_CRITICAL
// 當單片機有事需要通知計算機時,可以用CMD_WR_USB_DATA5命令寫入中斷特征數據,計算機的mInterruptEvent線程將會收到該中斷特征數據
// 然后mInterruptEvent線程向主程序發出消息進行處理,mInterruptEvent線程相當于中斷服務程序,代替主程序定時查詢單片機
CH375SetIntRoutine( mIndex, mInterruptEvent ); //設置中斷
Sleep( 50 ); // 主程序休息50mS,以等待上一個操作CH375SetIntRoutine創建線程并由該線程再次打開CH375,否則下一個操作CH375SetExclusive將導致創建的線程無法打開CH375
CH375SetExclusive( mIndex, TRUE ); // 設置獨占使用當前CH375設備,在此之后其它應用程序不能同時使用當前這個CH375設備,實際是無法再打開CH375設備
return ( TRUE );
break;
case WM_COMMAND:
switch ( LOWORD( wParam ) )
{
char i=0,j=0,k=0;
char ledval[4]="",oldledval[4]="";
case IDC_N1: // 發送數據到演示板上的第1個數碼管,左邊第1個
case IDC_N2:
case IDC_N3:
case IDC_N4:
case IDC_N5:
case IDC_N6:
case IDC_N7:
case IDC_N8: // 發送數據到演示板上的第8個數碼管,右邊第1個
if(Arrivalflag== 0){ //將軟件上的顯示信息發送到評估板,不要輸入,保證上下顯示信息相同,
if(DialogBox( mSaveInstance, "IDD_ENTER", NULL, mDialogEnter )==IDC_CANCEL)
break;
}
Arrivalflag=FALSE;
if ( mBufferLength ) // 已經輸入數據
{
UCHAR mBcdCode;
UCHAR mNumber;
if ( mEnterBuffer[0] == ' ' ) mBcdCode = 0x10; // 空格
else if ( mEnterBuffer[0] == '=' ) mBcdCode = 0x13;
else if ( mEnterBuffer[0] == '.' ) mBcdCode = 0x1a;
else mBcdCode = mCharToBcd( mEnterBuffer[0] );
// 如果輸入一個字符和一個小數點,則在字符右下角追加小數點
if ( mBufferLength >= 2 && mEnterBuffer[1] == '.' ) mBcdCode |= 0x80;
if ( mBcdCode != 0xff ) // 輸入的字符有效
{
ZeroMemory(&mDemoReq,sizeof(mDemoReq));
mNumber = LOWORD( wParam ) - IDC_N1; // 如果IDC_N1至IDC_N8有序,則結果為0-7,分別對應于各個數碼管按鈕
mNumber = 7 - mNumber; // 以最高位為左,最低位為右,所以N1對應位7,N8對應0
mDemoReq.mCommandCode = DEMO_CH451_CMD;
mDemoReq.mCommandCodeNot = ~ DEMO_CH451_CMD;
mDemoReq.mParameter[2] = 0x08 | mNumber; // CH451命令:加載字數據到指定數碼管
mDemoReq.mParameter[1] = mBcdCode; // 字數據,對應于BCD譯碼方式
mLength = CONST_CMD_LEN; // 命令包的長度
if ( CH375WriteData( mIndex, &mDemoReq, &mLength ) ) // 通過CH375發送數據,成功
// 如果輸入時mLength大于64,則成功返回時,為了更加可靠,可以檢查實際發送的長度是否符合
{
if(lstrlen(mEnterBuffer)==1)
mEnterBuffer[1] = 0; // 字符串結束符,只要一個字符
else
mEnterBuffer[2] = 0;
SetDlgItemText( hDialog, LOWORD( wParam ), CharUpper(mEnterBuffer) ); //設置按鈕上的字符
}
else
MessageBox( hDialog, "CH375WriteData 失敗", mCaptionInform, MB_OK | MB_ICONERROR );
}
else
MessageBox( hDialog, "請輸入字符:\n0-9,A-F或者空格,小數點", mCaptionInform, MB_OK | MB_ICONERROR );
}
else
MessageBox( hDialog, "請至少輸入一個字符:\n0-9,A-F或者空格,小數點", mCaptionInform, MB_OK | MB_ICONERROR );
break;
case IDC_INT_PRESS: // 鍵被按下,以下先釋放原按鍵再讀取新按鍵值
mSyncKeyboard( hDialog, 0xff ); // 釋放上次的按鍵
mSyncKeyboard( hDialog, mKeyCode ); // 根據鍵值作同步顯示
break;
case IDC_INT_RELEASE: // 按鍵釋放
mSyncKeyboard( hDialog, 0xff ); // 釋放按鍵
break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -