Cyapi使用心得(1)--USB连接

用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属性获取

◆  在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)--控制传输

可以说,写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传输

今天有空写以下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()重新设置传输大小,否则会导致数据不同步。

usb fx2 cy68013 Cyapi使用心得的更多相关文章

  1. USB Loader使用心得之游戏名称、简介、背景音乐

    我在<WAD独立安装版USB Loader的下载和安装>(链接:http://www.cnblogs.com/duxiuxing/p/4255124.html)开头提到:“任何版本的USB ...

  2. USB学习笔记连载(八):FX2替换到FX2LP需要注意事项

    对于使用FX2的用户,可以升级到FX2LP,上述的应用笔记<AN4078-C>中就讲解了在升级中的注意事项.   必要的修改:   1.晶振的匹配电容需要更改,FX2LP是12pF,不过笔 ...

  3. USB上位机通信:CyAPI

    至今的工作中,有USB接口通信的需求,记录一下. 建立一个USB设备对象 CCyUSBDevice *USBDevice = new CCyUSBDev(Handle): 打开USB设备 一个USB设 ...

  4. android4.0.3源码之USB wifi移植心得

    http://blog.csdn.net/eastmoon502136/article/details/7850157 http://forum.cubietech.com/forum.php?mod ...

  5. EZ-USB FX2(68013)固件研究

    原始资料来自网络 整理日: 2015年2月12日 1. Welcome 算是给所有正在学习USB,还徘徊着不得其门而入的朋友一个入门的契机吧,我也深知入门的痛苦,有些人入门就是抱着那什么USB协议,包 ...

  6. 感受机房管理化繁为简-新款KVM使用心得

    感受机房管理化繁为简-新款KVM使用心得 一. 背景 随着网络应用的不断增多,各地机房服务器数量也随之增加,利用多传统主机切换器的方式已经无法满足目前这种区域广.设备多人员紧缺的现状,而且即使是使用了 ...

  7. 25.usb固件深入

    dscr51里放的是USB描述符表,EZ-USB在重枚举阶段会读取或设置相应的描述符: db    DSCR_DEVICE_LEN          ;; Descriptor length db   ...

  8. Android USB Host 通信程序

    换到了一家新公司,于是就有了新的项目.这次的项目 要用Android SDK与USB HID设备进行通信.第一次接触Android SDK,以及USB,记录下源程序.开发过程以及一些心得. 首先,要感 ...

  9. usb.ids

    # # List of USB ID's # # Maintained by Vojtech Pavlik <vojtech@suse.cz> # If you have any new ...

随机推荐

  1. [javascript] 编写一个计算器,实现加减法

    1.代码 <script> function sum(){ //加法 var value1 = document.getElementById("num1").valu ...

  2. 爬虫多线程模板,xpath,etree

    class QuiShi: def __init__(self): self.temp_url = "http://www.lovehhy.net/Joke/Detail/QSBK/{0}& ...

  3. requests保存图片

    1.创建07_save_jpg.py文件 import requests #发送请求respone = requests.get("https://www.baidu.com/img/bd_ ...

  4. Bootstrap——导航条(navbar)

    导航条和导航从外观上差别不是太多,但在实际使用中导航条要比导航复杂得多. 导航条(navbar)中有一个背景色.而且导航条可以是纯链接(类似导航).表单以及表单和导航一起结合等多种形式. 在制作一个基 ...

  5. Linux系统时间\硬件时间(date、tzselect、clock、hwclock、ntpdate)

    1.系统时间和硬件时间 在Linux中有硬件时钟与系统时钟两种时钟.硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟.系统时钟则是指kernel中的时钟.所有Linux相关指令与函 ...

  6. 逆向分析objc,所有类的信息都能在动态调试中获取。

    因为objc是动态绑定的,程序运行时必须知道如何绑定,依靠的就是类描述.只要知道类描述是如何组织的就可以获取一切有用的信息.不知道是幸运还是不幸,这些信息全部都在运行的程序中.即使没有IDA这样的工具 ...

  7. 揭秘String类型背后的故事——带你领略汇编语言魅力

    字符串或串(String)是由数字.字母.下划线组成的一串字符.一般记为 s=“a1a2···an”(n>=0).它是编程语言中表示文本的数据类型.在程序设计中,字符串(string)为符号或数 ...

  8. Java并发之synchronized关键字深度解析(一)

    前言 近期研读路神之绝世武学,徜徉于浩瀚无垠知识之海洋,偶有攫取吉光片羽,惶恐未领略其精髓即隐入岁月深处,遂急忙记录一二,顺备来日吹cow之谈资.本小系列为并发之亲儿子-独臂狂侠synchronize ...

  9. scrapy实现自动抓取51job并分别保存到redis,mongo和mysql数据库中

    项目简介 利用scrapy抓取51job上的python招聘信息,关键词为“python”,范围:全国 利用redis的set数据类型保存抓取过的url,现实避免重复抓取: 利用脚本实现每隔一段时间, ...

  10. 关于JMeter原子性相关探究

    1.背景 最近宝路遇到个项目,在使用JMeter过程中引发了一些思考,宝路尝试用各种方式去验证,进而有了今天"JMeter原子性"相关主题. 2.目的 探究JMeter的事务的原子 ...