转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家提出意见,一起讨论!
需要源码的可以与我联系.
在我的一篇文章 Window XP驱动开发(十二) 驱动应用程序端 (原理分析)
中讲到了驱动应用程序端的开发原理。
这里针对CY7C68013A供应商提供的 .sys .inf及提供的.lib文件进行应用程序端的开发。
先看一下界面效果:
到 http://www.cypress.com/?rID=34870 下载 CY7C68013的组件开发安装程序。
下载后得到
安装后得到驱动安装文件与应用程序开发库:
图一:
现在我们就基于CyAPI.lib进行三次开发。
1、首先将 CyAPI.lib 与 CyAPI.lib加入到我们工程的链接中。(相对简单,不介绍了)
2、代码实现:
2、1 创建CCyUSBDevice接口
USBDevice = new CCyUSBDevice(m_hWnd); // Create an instance of CCyUSBDevice
2、2 获得设备列表,并找开设备。用:
UCHAR DeviceCount(void);
bool Open(UCHAR dev);
获得端点列表,用:
UCHAR EndPointCount(void);
void CBulkLoopDlg::OnRefreshBtn() { int i; // if we are currently running loopback, stop if (XferThread) { bLooping = false; InEndpt->Abort(); InEndpt->Reset(); OutEndpt->Abort(); OutEndpt->Reset(); m_StartBtn.SetWindowText("Start"); } // clear the combo boxes m_DeviceListComBox.ResetContent(); m_InEndptComBox.ResetContent(); m_OutEndptComBox.ResetContent(); // make sure there is at lesat one device out there if (USBDevice->DeviceCount()) { // search for all connected devices, and add them to the device // combo box for (i = 0; i < USBDevice->DeviceCount(); i++) { USBDevice->Open(i); m_DeviceListComBox.AddString(USBDevice->DeviceName); } m_DeviceListComBox.SetCurSel(0); OnSelchangeDeviceListCombox(); // This will set the device index and load the ep lists } }
void CBulkLoopDlg::OnSelchangeDeviceListCombox() { int i; char s[12]; DeviceIndex = m_DeviceListComBox.GetCurSel(); USBDevice->Open(DeviceIndex); // 获得端点数目 int epts = USBDevice->EndPointCount(); CCyUSBEndPoint *endpt; // Load the endpoint combo boxes // 跳过端点0,因为我们知道它是控制端点 for (i=1; i<epts; i++) { endpt = USBDevice->EndPoints[i]; if (endpt->Attributes == 2) // Bulk { sprintf(s, "0x%02X", endpt->Address); if (endpt->Address & 0x80) // In 端点 { m_InEndptComBox.AddString(s); m_InEndptComBox.SetItemData(m_InEndptComBox.GetCount()-1,i); } else // Out端点 { m_OutEndptComBox.AddString(s); m_OutEndptComBox.SetItemData(m_OutEndptComBox.GetCount()-1,i); } } } m_InEndptComBox.SetCurSel(0); m_OutEndptComBox.SetCurSel(0); OnSelchangeInCombox(); // Set the InEndpt member OnSelchangeOutCombox(); // Set the OutEndpt member }
2、3 根据选定的In端点与Out 端点进行数据传输.
Loop线程函数是 XferLoop,用到的函数有:
PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov);
bool WaitForXfer(OVERLAPPED *ov, ULONG tOut);
bool FinishDataXfer(PUCHAR buf, LONG &len, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos = NULL);
void CBulkLoopDlg::OnStartBtn() { if (XferThread) { bLooping = false; // InEndpt->Abort(); // InEndpt->Reset(); // OutEndpt->Abort(); // OutEndpt->Reset(); m_StartBtn.SetWindowText("Start"); } else { char s[12]; ZeroMemory(s,12); m_XferSize.GetLine(0,s,8); LONG xfer = atol(s); if (xfer > 2048) { xfer = 2048; m_XferSize.SetWindowText("2048"); } USBDevice->Open(DeviceIndex); OutEndpt = USBDevice->EndPoints[m_OutEndptComBox.GetItemData(m_OutEndptComBox.GetCurSel())]; InEndpt = USBDevice->EndPoints[m_InEndptComBox.GetItemData(m_InEndptComBox.GetCurSel())]; // Launch the looping thread (Calls XferLoop() function, above.) if (xfer && USBDevice->IsOpen()) { bLooping = true; XferThread = AfxBeginThread(XferLoop, this); } m_StartBtn.SetWindowText("Stop"); } }
UINT XferLoop( LPVOID params ) { OVERLAPPED outOvLap, inOvLap; CBulkLoopDlg *dlg = (CBulkLoopDlg *) params; char s[24]; ZeroMemory(s, 24); dlg->m_XferSize.GetLine(0,s,8); LONG xfer = atol(s); PUCHAR data = new UCHAR[xfer]; ZeroMemory(data,xfer); PUCHAR inData = new UCHAR[xfer]; ZeroMemory(inData,xfer); outOvLap.hEvent = CreateEvent(NULL, false, false, "CYUSB_OUT"); inOvLap.hEvent = CreateEvent(NULL, false, false, "CYUSB_IN"); dlg->m_SeedValue.GetLine(0,s,8); LONG seed = atol(s); int stopOnError = dlg->m_StopOnErrorChkBox.GetCheck(); stuffBuff(data,xfer,seed,dlg->m_FillPatternComBox.GetCurSel()); dlg->m_StatusLabel.SetWindowText(" STATUS: Transferring data . . ."); dlg->m_SuccessCount.SetWindowText("0"); dlg->m_FailureCount.SetWindowText("0"); bool success; LONG nSuccess = 0; LONG nFailure = 0; if (dlg->m_DisableTimeoutChkBox.GetCheck()) { dlg->OutEndpt->TimeOut = 0; dlg->InEndpt->TimeOut = 0; } else { dlg->OutEndpt->TimeOut = 2000; dlg->InEndpt->TimeOut = 2000; } for (;dlg->bLooping;) { LONG outlen,inlen,len; outlen = inlen = len = xfer; // Use temp var because XferData can change the value of len // 发送数据给USB设备 UCHAR *outContext = dlg->OutEndpt->BeginDataXfer(data,outlen,&outOvLap); // 从USB设备中读到数据 UCHAR *inContext = dlg->InEndpt->BeginDataXfer(inData,inlen,&inOvLap); // 等待 dlg->OutEndpt->WaitForXfer(&outOvLap,2000); dlg->InEndpt->WaitForXfer(&inOvLap,2000); // 完成数据传输 success = dlg->OutEndpt->FinishDataXfer(data, outlen, &outOvLap,outContext); success = dlg->InEndpt->FinishDataXfer(inData,inlen, &inOvLap,inContext); if (success) { bool pass = (memcmp(data,inData,len) == 0); if (pass) nSuccess++; else nFailure++; } else nFailure++; sprintf(s,"%d",nSuccess); dlg->m_SuccessCount.SetWindowText(s); sprintf(s,"%d",nFailure); dlg->m_FailureCount.SetWindowText(s); if ((!success) && stopOnError) dlg->bLooping = false; } CloseHandle(outOvLap.hEvent); CloseHandle(inOvLap.hEvent); delete [] data; delete [] inData; dlg->m_StatusLabel.SetWindowText(" STATUS: Stopped"); dlg->XferThread = NULL; dlg->USBDevice->Close(); return true; }
固件源码在CYPRESS提供的安装包下:
设计方法请看我的另一篇文章:<<>>
这里我们得把得到的bulkloop.hex单片机文件写入的CY7C里。
我们采用的工具是CYPRESS提供的工具: CyConsole.exe
(1)在运行界面下打开EZ-USB Interface选项界面
(2)选择Download按钮,将选择bulkloop.hex
(3)写入bulkloop.hex文件后,我们在设备管理器中发现此设备变化无法识别了。
这是因为我们之前的驱动是建立的VID:04B4 PID:8613 基础上的。
而现在我们的VID与PID变了,所以找不到驱动:
为什么PID发生了变化?这是因为bulkloop.hex改变了PID。请看我的文章:
<<http://blog.csdn.net/chenyujing1234/article/details/7722669>>
接下来我们修改CyUsb.inf文件。
中的CyUSB.chm里有讲到怎么对CyUSB.INF进行修改,使之在具体的应该中使用.
1、1 增加设备的标识符到驱动中
把 图一中的CyUSB.inf中的;%VID_XXXX&PID_XXXX.DeviceDesc%=CyUsb, USB\VID_XXXX&PID_XXXX
改为:
%VID_04B4&PID_8613.DeviceDesc%=CyUsb, USB\VID_04B4&PID_8613
1、2 替换Cypress 串,使之与自己的公司描述更确切。
CYUSB_Provider = "Cypress"
CYUSB_Company = "Cypress Semiconductor Corporation"
CYUSB_Description = "Cypress Generic USB Driver"
CYUSB_DisplayName = "Cypress USB Generic"
1、3 执行一个通用的GUID
应用程序软件通过驱动的的GUID访问驱动,每一个Window系统的驱动都应该有一个唯一的GUID。
因为可能会有不同的硬件供应商,这样就会有很多CYUSB.SYS的实例。我们可以通过GUIDGEN.exe来产生我们
自己的GUID。并把此GUI写在CyUSB.inf中
CYUSB.GUID="{AE18AA60-7F6A-11d4-97DD-00010229B959}"
1、4 在启动时执行一个脚本
CYUSB.sys驱动在启动时能被配置到默认的控制端点(端点0)。
为了配置设备使之能表现控制传输,我们用CyConsole.exe来创建一个脚本文件。
我们保存此脚本文件为MyDevice.SPT,把此文件放到.INF文件下。
目的是让此脚夫本文件把固件镜像下载到设备中。
1、4、1 在CyUSB.inf中的 [CYUSB.AddReg.Guid]下添加
HKR,,DriverEXECSCRIPT,,%CYUSB.EXECSCRIPT%
1、4、2 在[Strings]下添加
CYUSB.EXECSCRIPT="\systemroot\system32\MyDevice\MyDevice.spt"
由于cyusb.inf文件中没有提供DefaultInstall 默认安装节点,但我们可以通过EzDriverInstaller安装(请参见:http://blog.csdn.net/chenyujing1234/article/details/7676812)
安装完后,我们的应用程序才有意义,接下来开始测试应用程序了。