CyAPI编写程序基础入门

1.首先要建立一个USB设备对象

CCyUSBDevice *USBDevice = new CCyUSBDev(Handle);

2.然后就该是打开USB设备了

如果只有一个USB设备
USBDevice->open(0) //打开0号USB设备

如果要判断,可以:

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

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

如果连接有多个USB设备,那么可以枚举所有的USB,用到DeviceCount()函数;执行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);   //所选择的当前设备名
        }

    }

3.端点设置

【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; iEndPoints[i];    //EndPoints-端点列表,最大16.EndPoints[0]指向控制端点( CCyControlEndPoint)
        //未使用的端点设置为NULL

    if (endpt->Attributes == 2)    // Bulk Attributes--判断传输类型bulk,control,等
    {
        sprintf(s, "0x%02X", 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传输

4.控制传输

【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的话同理。

4.bulk传输

为了提高传输速度与效率,一般要把数据采集放在另外一个线程,单独开启一个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()重新设置传输大小,否则会导致数据不同步。

USBDevice->BulkInEndPt->SetXferSize(len);→接收数据速度提升。

你可能感兴趣的:(usb3.0)