“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部落格