Cyapi使用心得

Cyapi使用心得(1)--USB连接2009-11-07 19:23 

    用Cyapi也有一阵了,这个确实比EZusb的api好用,简单说下Cyapi的使用心得,在编程中应该注意的一些问题,毕竟,说起来,那个CYapi的说明文档讲的实在太简单了点,好多东西都讲得不明白,只能在使用中自己慢慢积累了。

    首先说下前提,固件架构是EZ-USB FX2/FX2LP(CY7C68013),编译环境VC++ 6.0,驱动是Cyusb.sys

上位机简单说下,建立一个MFC 单文档/对话框 应用程序;在路径项目中包含头文件cyapi.h和cyapi.lib所在的路径,最好移到最上面。然后手动导入cyapi.lib,注意是CV6_7的lib,不要导入BCB的。

下面讲得是按照USB一般工作流程来讲得。

(1)USB连接

1.首先要建立一个USB设备对象,文档里有说的了,copy一下

       CCyUSBDevice *USBDevice = new   CCyUSBDev(Handle);

括号中的Handle是USB所关联对象的句柄,一般在MFC中直接就是m_hwnd。

2.然后就该是打开USB设备了,可以用到两个函数open();isopen()

这两个都可以用来打开USB设备,isopen()还可以判断能否获得USB设备句柄

    一般来说,如果只有一个USB设备连接,可以这样打开:

               USBDevice->open(0)    //打开0号USB设备

如果要判断,可以:

            if(! USBDevice->open(0)) //打开失败

               {messagebox("USB未连接");}

或者        if(!USBDevice->Isopen())

                     ..........

    如果连接有多个USB设备,那么可以枚举所有的USB,用到DeviceCount()函数;具体的可以参考cybulk的例子,执行USBDevice->DeviceCount()后,返回所连接的USB设备个数:

       if (USBDevice->DeviceCount())   //保证至少有一个USB设备连接

    {

        for (i = 0; i < USBDevice->DeviceCount(); i++)    //枚举所有USB设备

        {

           USBDevice->Open(i);                   //打开第i号USB设备

           m_DeviceListComBox.AddString(USBDevice->DeviceName);//所选择的当前设备名

        }

    }

    好了,今天说到这里,有空接着写~

 

Cyapi使用心得(2)--端点使用及其他USB属性获取2009-11-13 22:52    

◆  在cybulk的例子中介绍了如何枚举固件中使用的所有端点,也就是使用多个端点的情况:

       CCyUSBDevice *USBDevice =new CCyUSBDevice(m_hWnd); //USB设备

       USBDevice->Open(0);    //打开0号USB设备

【1】首先获取所用的端点数目

       int epts = USBDevice->EndPointCount();

EndPointCount();函数返回当前所用的端点数+1,也就是包含了控制端点例如在固件接口描述符Interface Descriptor中设置Number of end points项(第5项)的值为4,则epts的值为4+1=5。

【2】定义端点指针

      CCyUSBEndPoint *endpt;  

CCyUSBEndPoint 建立一个端点对象,可建立所有的端点类型,控制端点,bulk端点,ISO端点等;

【3】开始枚举端点,并获得其属性:端点号,传输方向

       for (i=1; i

    {   

       endpt = USBDevice->EndPoints[i];    //EndPoints-端点列表,最大16.EndPoints[0]

                                       //指向控制端点( CCyControlEndPoint)

                                       //未使用的端点设置为NULL

        if (endpt->Attributes == 2)    // Bulk Attributes--判断传输类型bulk,control,等

        {

            sprintf(s, "0xX", endpt->Address);

            if (endpt->Address & 0x80)   //Address--判断传输方向in or out  

                                     //0x8_-in;0x0_-out

            {

                m_InEndptComBox.AddString(s); //最高位为8,in端点,添加到in组合框

                m_InEndptComBox.SetItemData(m_InEndptComBox.GetCount()-1,i);

            }

            else

            {

                m_OutEndptComBox.AddString(s); //否则,最高位为0,out端点,

                                             //添加到out组合框

                m_OutEndptComBox.SetItemData(m_OutEndptComBox.GetCount()-1,i);

            }

        }

    }

◆ 这样,就完成了某个具体端点的选择。从上面的代码来看,非常烦琐,如果只需要使用一个端点的画,那上面的代码无疑就显得冗长不够简洁了。仅使用一个端点,可以使用EndPointOf()函数,该函数直接使用指定的端点,返回其指针例如,要使用端点2,in传输,那么,可以这样:

            CCyUSBDevice *USBDevice =new CCyUSBDevice(m_hWnd); //USB设备 

            USBDevice->Open(0); //打开0号设备,

           CCyUSBEndPoint *endpt = USBDevice->EndPointOf(0X82); //使用端点2,in传输

可以看到,上面的只需要3行代码,比枚举简洁方便多了。

◆ 至于获取USB其他属性,这里列出经常使用的几个,具体的可参考cyapi的文档,在CCyUSBDevice和CCyUSBEndPoint这两个类里可查询到。

       USBDevice->DeviceCount()     //返回连接到电脑的USB设备个数,

                                   //从0,1,2.。开始命名

        USBDevice->DeviceName()     //返回USB设备名称,也就是固件中

                                    //StringDscr2: 字段字符串  

       USBDevice->VendorID           //返回USB设备VID

       USBDevice->ProductID           //返回USB设备PID

 

Cyapi使用心得(3)--控制传输2009-11-17 21:04        

今天写写控制传输吧--

可以说,写USB上位机,控制传输肯定第一个要做的例子和试验了;因为固件不用很多代码,VC也不用很多代码就测试你写的USB上位机的正确与否,这里简单介绍下cyapi写控制传输的一些方法。

    基本上,要对固件进行自定义命令(vendor)传输,通常都是用控制传输进行的。使用控制传输in或者out方式都可以实现对固件的自定义命令。

【1】out控制传输发送vendor命令

    我想采用out方式应该比较符合大家的思维,因为是从上位机发命令到下位机,怎么看都应该是out而不是in。

    例如你在固件里设置了out的接收buf:

      BOOL DR_VendorCmnd(void)

{

   switch (SETUPDAT[1])

{

   case 0xDD:

   { temp=EP0BUF[0];

    EP0BCH=0;

    EP0BCL=1;

    EP0CS |=bmHSNAK;

    break;

   }

   default:

    return(TRUE);

   }

   return(FALSE);

}

      VC中:

           CCyControlEndPoint* CtlEndpoint;   //定义一个控制端点  

          CtlEndpoint->Target    = TGT_DEVICE;       //不必关注,固定

          CtlEndpoint->ReqType   = REQ_VENDOR;  //请求类型:自定义请求(标准请求等)

          CtlEndpoint->Direction = DIR_TO_DEVICE;    //传输方向:主机->usb设备(out)

          CtlEndpoint->ReqCode   = 0XDD;      //自定义请求码  

          CtlEndpoint->Value     = 0;     //这里的设定值将传给setupdat的【2:3】位

           CtlEndpoint->Index     = 0;    //这里的设定值将传给setupdat的【4:5】位

          PUCHAR buf=new UCHAR[1];

         ZeroMemory(buf,1);             //用0填充buf区,填充大小(1字节)

          long buflen=1;        //传输的其他字节数:cy控制台console中length的值

           CtlEndpoint->XferData(buf,buflen);

当然,没有规定说一定必须传给下位机至少一个字节的数据;你也可以不传;不过最好下位机同样设置接收字节为0,否则小心有莫名奇妙的错误(XX内存不能为只读等等)。

将temp=EP0BUF[0];去掉,上位机:

          PUCHAR buf=new UCHAR;   //用0填充buf区,填充大小(1字节)

          long buflen=0;

           CtlEndpoint->XferData(buf,buflen);

也是可以的,友情提示:控制传输请尽量用同步的xferdata()而不是异步的begindataxfer()。

【2】in控制传输发送vendor命令

     基本上,跟out区别不大。固件中:

       BOOL DR_VendorCmnd(void)

{

   switch (SETUPDAT[1])

{

   case 0xDD:

   {

    *EP0BUF=0XDD;

    EP0BCH=0;

    EP0BCL=1;

    EP0CS |=bmHSNAK;

    break;

   }

   default:

    return(TRUE);

   }

   return(FALSE);

}

      VC中:

          CCyControlEndPoint* CtlEndpoint;   //定义一个控制端点  

          CtlEndpoint->Target    = TGT_DEVICE;  //不必关注,固定

          CtlEndpoint->ReqType   = REQ_VENDOR; //请求类型:自定义请求(标准请求等)

          CtlEndpoint->Direction = DIR_FROM_DEVICE;    //传输方向:usb设备->主机(in)

          CtlEndpoint->ReqCode   = 0XDD;      //自定义请求码  

          CtlEndpoint->Value     = 0;     //这里的设定值将传给setupdat的【2:3】位

           CtlEndpoint->Index     = 0;    //这里的设定值将传给setupdat的【4:5】位

          PUCHAR buf=new UCHAR[1];

         ZeroMemory(buf,1);           //用0填充buf区,填充大小(1字节)

          long buflen=1;          //传输的其他字节数:cy控制台console中length的值

           CtlEndpoint->XferData(buf,buflen);

这里的话,推荐尽量设置接收缓冲,不要将buflen设置为0.同样,友情提示:控制传输请尽量用同步的xferdata()而不是异步的begindataxfer()。

【3】另外,还有两个简化版本的函数Write(out传输)和Read(in传输)也可以进行控制传输,作用同XferData()是一样的,因为已经明确表示了是in还是out,所以Direction 项的值就省略了。只是看起来代码更加简洁,输入效率更高而已。基本上,大多数时候,我都是使用Write和Read。

          CCyControlEndPoint* CtlEndpoint;   //定义一个控制端点  

          CtlEndpoint->Target    = TGT_DEVICE;   //不必关注,固定

          CtlEndpoint->ReqType   = REQ_VENDOR; //请求类型:自定义请求(标准请求等)

          CtlEndpoint->ReqCode   = 0XDD;      //自定义请求码  

          CtlEndpoint->Value     = 0;     //这里的设定值将传给setupdat的【2:3】位

           CtlEndpoint->Index     = 0;    //这里的设定值将传给setupdat的【4:5】位

          PUCHAR buf=new UCHAR[1];

         ZeroMemory(buf,1);        //用0填充buf区,填充大小(1字节)

          long buflen=1;       //传输的其他字节数:cy控制台console中length的值

           CtlEndpoint->Write(buf,buflen);  

      Read的话同理。

 

Cyapi使用心得(4)--bulk传输2009-12-01 19:50           

今天有空写以下bulk传输。bulk的话,cy开发包里有个例子cybulk写的很好,不过说实话,那个太烦琐了,基本上我们自己只用到其中的一部分,另外,就是局限性很大,例如它只是512字节的倍数,对于任意数目的字节貌似是不支持的,数据会不同步。

    为了提高传输速度与效率,一般要把数据采集放在另外一个线程,单独开启一个bulk线程。恩,前面的还是稍微提一下,在打开USB,设定端点后,紧接着开启线程,进行bulk采集:

         if (USBDevice->IsOpen()) {   //如果USB设备已经打开

           bLooping = true;      //线程循环标志为真

          XferThread = AfxBeginThread(XferLoop, this); //启动线程

           }

然后是线程中的处理,在这里上位机用异步接收,创建异步事件:

     OVERLAPPED inOvLap;

     CVC_SimpleCyapiDlg *dlg = (CVC_SimpleCyapiDlg *) params;   //使该线程可访问

                                                //CBulkLoopDlg类的所 有公有成员

     inOvLap.hEvent   = CreateEvent(NULL, false, false, "CYUSB_IN");

线程循环:

    bool success;

    dlg->InEndpt->TimeOut = 120;

for (;dlg->bLooping;) {       //线程循环,直到循环标志blooping为假

   LONG inlen ;

   inlen = 512;

   UCHAR *inContext = dlg->InEndpt->BeginDataXfer(inData,inlen,&inOvLap);

        dlg->InEndpt->WaitForXfer(&inOvLap,TimeOut);

        success = dlg->InEndpt->FinishDataXfer(inData,inlen, &inOvLap,inContext);

     if (!success) dlg->bLooping = false;

}

    主要是三步,调用三个函数BeginDataXfer,WaitForXfer,FinishDataXfer。按照手册上说的,BeginDataXfer发起异步传输,并且立即返回。也就是说,发起此次的inlen后,并不会等inlen传输完,而是立即开始下一次inlen字节传输;WaitForXfer,异步传输最大等待时间;FinishDataXfer,到这里才开始真正的写内存,将读到的数写到缓冲区indata中。

      最后,完了别忘记释放对象:

     CloseHandle(inOvLap.hEvent);

     delete [] inData;

     另外,如果要传输非512字节整数倍的数据,而且不是一次传输完的话,最好在线程中用SetXferSize()重新设置传输大小,否则会导致数据不同步。

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
================================================================================ MICROSOFT 基础类库 : BulkTranferMFC 项目概述 =============================================================================== 应用程序向导已为您创建了此 BulkTranferMFC 应用程序。此应用程序不仅演示 Microsoft 基础类的基本使用方法,还可作为您编写应用程序的起点。 本文件概要介绍组成 BulkTranferMFC 应用程序的每个文件的内容。 BulkTranferMFC.vcxproj 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 BulkTranferMFC.vcxproj.filters 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 BulkTranferMFC.h 这是应用程序的主头文件。 其中包括其他项目特定的标头(包括 Resource.h),并声明 CBulkTranferMFCApp 应用程序类。 BulkTranferMFC.cpp 这是包含应用程序类 CBulkTranferMFCApp 的主应用程序源文件。 BulkTranferMFC.rc 这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源包含在 2052 中。 res\BulkTranferMFC.ico 这是用作应用程序图标的图标文件。此图标包括在主资源文件 BulkTranferMFC.rc 中。 res\BulkTranferMFC.rc2 此文件包含不在 Microsoft Visual C++ 中进行编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。 ///////////////////////////////////////////////////////////////////////////// 应用程序向导创建一个对话框类: BulkTranferMFCDlg.h、BulkTranferMFCDlg.cpp - 对话框 这些文件包含 CBulkTranferMFCDlg 类。此类定义应用程序的主对话框的行为。对话框模板包含在 BulkTranferMFC.rc 中,该文件可以在 Microsoft Visual C++ 中编辑。 ///////////////////////////////////////////////////////////////////////////// 其他功能: ActiveX 控件 该应用程序包含对使用 ActiveX 控件的支持。 ///////////////////////////////////////////////////////////////////////////// 其他标准文件: StdAfx.h, StdAfx.cpp 这些文件用于生成名为 BulkTranferMFC.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 Resource.h 这是标准头文件,可用于定义新的资源 ID。Microsoft Visual C++ 将读取并更新此文件。 BulkTranferMFC.manifest Windows XP 使用应用程序清单文件来描述特定版本的并行程序集的应用程序依赖项。加载程序使用这些信息来从程序集缓存中加载相应的程序集,并保护其不被应用程序访问。应用程序清单可能会包含在内,以作为与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件进行重新分发,它还可能以资源的形式包含在可执行文件中。 ///////////////////////////////////////////////////////////////////////////// 其他注释: 应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。 如果应用程序使用共享 DLL 中的 MFC,您将需要重新分发 MFC DLL。如果应用程序所使用的语言与操作系统的区域设置不同,则还需要重新分发相应的本地化资源 mfc110XXX.DLL。 有关上述话题的更多信息,请参见 MSDN 文档中有关重新分发 Visual C++ 应用程序的部分。 /////////////////////////////////////////////////////////////////////////////
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值