1. 程式人生 > >“USB狀態與資訊檢測”上位機設計方法

“USB狀態與資訊檢測”上位機設計方法

1. 使用MFC新建USB上位機工程

    USB晶片型號為:CYC7C68013A,上位機的開發環境為Visual Studio 2008,工程檔案由MFC嚮導生成,具體步驟如下:

(1)開啟VS2008,依次單擊 檔案 -> 新建 -> 專案,選單中專案型別一欄選擇“MFC”,右側模板選擇“MFC應用程式”。在選單欄下方,名稱填入“USBdetect”,位置選擇“C:\project”,最後點選確定!

(2)在MFC應用程式嚮導選單中,左側概述選擇應用程式型別,右側應用程式型別選擇“基於對話方塊(D)”,其它選項預設,點選下一步。

(3)連續單擊“下一步”,直到點選完成!

使用MFC嚮導得到的USB上位機工程模板如下,其中

區域1:工程需要包含的標頭檔案;

區域2:工程的主程式檔案;

區域3:工程的資原始檔連結;

區域4:程式除錯視窗;

區域5:上位機的執行介面;

區域6:對話方塊編輯器視窗。

2. 新增相關標頭檔案與庫檔案

(1)檔案的獲取

在電腦上安裝Cypress Suite USB 3.4.7應用程式後,可在路徑“C:\Cypress\Cypress Suite USB 3.4.7\CyAPI\inc”和“C:\Cypress\Cypress Suite USB 3.4.7\CyAPI\lib”下,分別得到所需的

USB標頭檔案:CyAPI.h、cyioctl.h、usb100.h、usb200.h,

與庫檔案:CyAPI.lib,

(注意:不同平臺的庫檔案不一樣,64位系統選擇x64資料夾下的庫檔案)

(2)在工程檔案中新增Cypress公司的標頭檔案和庫檔案

    首先,將檔案CyAPI.h、cyioctl.h、usb100.h、usb200.h和CyAPI.lib拷貝至“C:\project\USBdetect\USBdetect”目錄下;

接著,開啟程式USBdetectDlg.cpp,在頭部新增以下程式碼:

    #include "CyAPI.h"

    #include "cyioctl.h"

    #include <dbt.h>

    開啟標頭檔案USBdetectDlg.h,在頭部新增以下程式碼:

    #include "CyAPI.h"

    #include <afxmt.h>

    在網上下載devioctl.h標頭檔案,放在工程路徑下,開啟cyioctl.h修改第24行程式碼為 #include "devioctl.h"!

   最後,給工程新增庫檔案CyAPI.lib,在工程USBdetect上右擊並點選屬性,依次單擊左側選項中的 配置屬性->連結器->輸入,在右側的附加依賴項中填入CyAPI.lib,至此工程的標頭檔案與庫檔案新增完畢!

3. 上位機介面設計

(1)刪除控制元件“IDC_STATIC1 (Text Control)”,新增控制元件Group Box,並調整box邊框大小和名稱,名稱由靜態改為“USB狀態與資訊”;

(2)新增4個“Static Text”控制元件,並將它們的ID修改為IDC_TEXTA、IDC_TEXTB、IDC_TEXTC、IDC_TEXTD;

上位機介面如下,4個靜態文字控制元件的含義分別是:

IDC_TEXTA:用於顯示USB狀態,斷開或者連線!

IDC_TEXTB:顯示VendorID

IDC_TEXTC:顯示ProductID

IDC_TEXTD:顯示裝置資訊

4. 上位機檢測程式設計

開啟標頭檔案“USBdetectDlg.h”,在public:宣告下填寫:

    CCyUSBDevice *USBDevice;

CWinThread *ReadThread; //Thread

//CCyUSBEndPoint *InEndpt; //USB endpoint

BOOL ReadThreadLooping; //執行緒迴圈標誌

CCyUSBEndPoint* pInEndpt;

CCyUSBEndPoint* pOutEndpt;

CSemaphore m_Semaphore;

bool bPnP_Arrival;

bool bPnP_DevNodeChange;

bool bPnP_Removal;

CWinThread *pXferInThread;

CWinThread *pXferOutThread;

    bool m_bXfer;

    void DisplayDevices(void);

    afx_msg void OnDestroy();

    void EndOutThread(int nThreadID);

    void TestRate(double mb, unsigned long nSuc, unsigned long nErr);

在USBdetectDlg.cpp的初始化函式OnInitDialog()的“// TODO: 在此新增額外的初始化程式碼宣告下填寫:

    ReadThread=NULL;                           //執行緒禁止

USBDevice = new CCyUSBDevice(m_hWnd);    //USB裝置

SetDlgItemText(IDC_TEXTA,_T("USB狀態: 斷開!"));

SetDlgItemText(IDC_TEXTB,_T("VendorID=NULL"));

SetDlgItemText(IDC_TEXTC,_T("ProductID=NULL"));

    SetDlgItemText(IDC_TEXTD,_T("裝置:NULL"));

另外,新增兩個新的成員函式DisplayDevices(void)和WindowProc(UINT message, WPARAM wParam, LPARAM lParam),前者用於更新上位機介面,後者用於實現USB熱拔插功能!

void CUSBdetectDlg::DisplayDevices(void)

{

CString strA = _T("USB狀態: 斷開!");

CString strB = _T("VendorID=NULL");

CString strC = _T("ProductID=NULL");

CString strD = _T("裝置:NULL");

UCHAR nCount,n;

int vID,pID;

Sleep(10);

m_Semaphore.Lock();

nCount=USBDevice->DeviceCount();

    for(n=0;n < nCount;n++)

{

if(USBDevice->Open(n))

{

strD = USBDevice->DeviceName;

if(strD==_T("YJ-Development Kit C402"))

{

strA = _T("USB狀態: 已連線!");

vID=USBDevice->VendorID; //讀取VID

pID=USBDevice->ProductID; //讀取PID

strB.Format(_T("VendorID=0x%x"),vID);

//SetDlgItemText(IDC_TEXT1,str2);

strC.Format(_T("ProductID=0x%x"),pID);

//SetDlgItemText(IDC_TEXT2,str3);

strD = _T("裝置:");

strD+=USBDevice->DeviceName;

pInEndpt  = USBDevice->EndPointOf(0x86);

pOutEndpt = USBDevice->EndPointOf(0x02);

if(!pInEndpt || !pOutEndpt) strD +=  _T("錯誤!    裝置端點不可用");

break;

}

}

pInEndpt  = NULL;

pOutEndpt = NULL;

}

m_Semaphore.Unlock();

//SetWindowText(str);

SetDlgItemText(IDC_TEXTA,strA);

SetDlgItemText(IDC_TEXTB,strB);

SetDlgItemText(IDC_TEXTC,strC);

SetDlgItemText(IDC_TEXTD,strD);

}

LRESULT CUSBdetectDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

if (message == WM_DEVICECHANGE) 

{

// Tracks DBT_DEVICEARRIVAL followed by DBT_DEVNODES_CHANGED

if (wParam == DBT_DEVICEARRIVAL)

{

bPnP_Arrival = true;

bPnP_DevNodeChange = false;

}

// Tracks DBT_DEVNODES_CHANGED followed by DBT_DEVICEREMOVECOMPLETE

if (wParam == DBT_DEVNODES_CHANGED) 

{

bPnP_DevNodeChange = true;

bPnP_Removal = false;

}

if (wParam == DBT_DEVICEREMOVECOMPLETE) 

{

bPnP_Removal = true;

PDEV_BROADCAST_HDR bcastHdr = (PDEV_BROADCAST_HDR) lParam;

if (bcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE) 

{

PDEV_BROADCAST_HANDLE pDev = (PDEV_BROADCAST_HANDLE) lParam;

if (pDev->dbch_handle == USBDevice->DeviceHandle())

USBDevice->Close();

DisplayDevices();

}

}

// If DBT_DEVNODES_CHANGED followed by DBT_DEVICEREMOVECOMPLETE

if (bPnP_Removal && bPnP_DevNodeChange) 

{

// Sleep(10);

// DisplayDevices();

bPnP_Removal = false;

bPnP_DevNodeChange = false;

}

// If DBT_DEVICEARRIVAL followed by DBT_DEVNODES_CHANGED

if (bPnP_DevNodeChange && bPnP_Arrival) 

{

DisplayDevices();

bPnP_Arrival = false;

bPnP_DevNodeChange = false;

}

}

return CDialog::WindowProc(message, wParam, lParam);

}

5. 上位機測試

    雙擊路徑“C:\project\USBdetect\Debug”下USBdetect.exe,當電腦沒有連線Cypress USB裝置時,上位機顯示介面如下:

插入Cypress USB裝置,上位機介面顯示USB裝置已連線,VendorID=0x4b4,ProductID=0x1004,裝置名稱為

YJ-Development Kit C402,當USB線斷開或者USB裝置斷電時,上位機的介面會返回至上面的狀態。

6. 參考資料

(1)MFC程式設計入門之十(對話方塊:設定對話方塊控制元件的Tab順序) - 木縹緲 - 部落格園

(2)Cyapi使用心得 - shengzhuzhu的專欄 - CSDN部落格

(3)基於Cy68013的USB裝置在VC程式中熱插拔的實現 | 學步園

(4)error C4430: 缺少型別說明符 - 一夢一程-記錄學習點滴-51CTO部落格

(5)理解Semaphore及其用法詳解 - flyingdon的專欄 - CSDN部落格