vsU口API函数使用流程.docx
- 文档编号:3978046
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:10
- 大小:20.69KB
vsU口API函数使用流程.docx
《vsU口API函数使用流程.docx》由会员分享,可在线阅读,更多相关《vsU口API函数使用流程.docx(10页珍藏版)》请在冰豆网上搜索。
vsU口API函数使用流程
上位机U口使用(USB2.0芯片)
一、函数
CCyUSBDevice*USBDveice=newCCyUSBDevice(handle);
1.USBDevice->open(i),USBDevice->isopen(i)
打开i号设备
2.USBDevice->EndPointCount()
获取用到的断点数目
3.USBDevice->EndPointOf(0X82)
直接使用指定的端点2,in传输
USBDevice->EndPointOf(0X02)
直接使用指定的端点2,out传输
4.USBDevice->DeviceCount()
返回连接到电脑的USB设备个数,从0,1,2.。
开始命名
5.USBDevice->DeviceName()
返回USB设备名称,也就是固件中StringDscr2:
字段字符串
6.USBDevice->VendorID
返回USB设备VID
7.USBDevice->ProductID
返回USB设备PID
8.BeginDataXfer(PUCHARbuf,LONGlen,OVERLAPPED*ov)
读取len个数据到buf里
9.WaitForXfer(OVERLAPPED*ov,ULONGtout)
等待数据发送完成
10.FinishDataXfer(PUCHARbuf,LONGlen,OVERLAPPED*ov,PUCHARpXmiBuf,CCyIsoPktInfos=NULL)
BeginDataXfer(),>WaitForXfer()和>FinishDataXfer()。
这三个函数就完成一个完整的块传输。
第一个启动块传输,第二个等待数据返回,第三句是完成块传输
OVERLAPPED结构类型声明如下:
typedefstruct_OVERLAPPED{
ULONG_PTRInternal;//操作系统保留,指出一个和系统相关的状态
ULONG_PTRInternalHigh;//指出发送或接收的数据长度
union{
struct{
DWORDOffset;//文件传送的开始位置
DWORDOffsetHigh;//文件传送的字节偏移量的高位字
};
PVOIDPointer;//指针,指向文件传送位置
};
HANDLEhEvent; //指定一个I/O操作完成后触发的事件
}OVERLAPPED,*LPOVERLAPPED;
OVERLAPPED结构主要在一些重叠IO等异步操作中起作用。
即:
你需要操作系统传递一批数据,于是填了一个overlapped的订单,订单上写着从哪里(数据的偏移位置)开始传输,于是你去干别的事去了。
系统完成传输就打个电话(激活hEvent)叫你验收,你看到overlapped订单上系统写着的传输的数据数量验收接收的数据
二、一般流程
1、打开设备:
USBDevice->Open(DeviceIndex);
2、获得USB批量传输的断点:
OutEndpt=USBDevice->EndPoints;
3、确定设备打开则创建线程函数:
AfxBeginThread(XferLoopw,this);
4、打开事件对象:
outOvLap.hEvent=CreateEvent(NULL,false,false,"CYUSB_OUT");
inOvLap.hEvent=CreateEvent(NULL,false,false,"CYUSB_IN");
5、开启异步传输并完成数据的传输:
BeginDataXfer(data,outlen,&outOvLap);
WaitForXfer(&outOvLap,500);
FinishDataXfer(data,outlen,&outOvLap,outContext);
6、关闭设备
CloseHandle(outOvLap.hEvent);
delete[]data;
2.1数据传输
将上述步骤5详解。
2.1.1接收数据:
1.UCHAR*inContext=USBDevice->BulkInEndPt->BeginDataXfer(inbuf,bc,&inOvLap);
//开始接收数据到
2.USBDevice->BulkOutEndPt->WaitForXfer(&outOvLap,100); //等待发送完成
3.Success=USBDevice->BulkOutEndPt->FinishDataXfer(outbuf,bc,&outOvLap,outContext);
//这里才真正将outbuf里的数据发送出
4.CloseHandle(outOvLap.hEvent); //关闭句柄,释放资源
2.1.2发送数据
UCHAR*outContext=USBDevice->BulkOutEndPt->BeginDataXfer(outbuf,bc,&outOvLap);
//开始发送数据到
USBDevice->BulkInEndPt->WaitForXfer(&inOvLap,100);
//等待接收完成
Success=USBDevice->BulkInEndPt->FinishDataXfer(inbuf,bc,&inOvLap,inContext);
//这里才真正将接收到的数据存储到inbuf里
CloseHandle(inOvLap.hEvent);
//关闭句柄,释放资源
三、
1.将CyAPI.lib和CyAPI.h拷贝到工程目录下
2.建立一个USB设备对象
CCyUSBDevice*USBDveice=newCCyUSBDevice(handle);
括号中的hanlde是USB所关联对象的句柄,一般在MFC中直接就是m_hwnd
3.打开USB设备
函数:
open();isopen();
一般来说,如果只有一个USB设备连接,可以这样打开:
USBDevice->open(0)//打开0号USB设备
USBDevice->isopen(0)//打开0号USB设备
判断
If(!
USBDevice->open(0))//打开失败
{messagebox(“USB未连接”)}
如果连接多个USB设备,那么可以枚举所有USB,用到DeviceCount()函数,执行后,返回所连接的USB设备个数
If(USBDevice->DeviceCount())//保证至少有一个USB设备连接
{
For(i=0;i
{
USBDevice->open(i);//打开第i号USB设备
m_DeviceListComBox.AddString(USBDevice->DeviceName);//所选择的当前设备名
}
}
4.获取所用的端点数目:
intepts=USBDevice->EndPointCount();
返回当前所用端点数+1,也就是包含控制端点
5.定义端点指针
6.CCyUSBEndPoint*endpt;
CCyUSBEndPoint:
建立一个端点对象,可建立所有的断点类型,控制端点,bulk端点,ISO端点等。
7.开始枚举端点,并获得其属性,端点号,传输方向
for(i=1;i { //EndPoints-端点列表,最大16,EndPoints[0]指向控制端点 //(CCyControlEndPoint),未使用的端点设置为NULL Endpt=USBDevice->EndPoints[i]; If(endpt->Attributes==2)//bulkAttributes—判断传输类型bulk,control等 { sprintf(s,"0x%02X",endpt->Address); if(endpt->Address&0x80)//Address--判断传输方向inorout0x8_-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=newCCyUSBDevice(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 --可以说,写USB上位机,控制传输肯定第一个要做的例子和试验了;因为固件不用很多代码,VC也不用很多代码就测试你写的USB上位机的正确与否,这里简单介绍下cyapi写控制传输的一些方法。 基本上,要对固件进行自定义命令(vendor)传输,通常都是用控制传输进行的。 使用控制传输in或者out方式都可以实现对固件的自定义命令。 【1】out控制传输发送vendor命令 我想采用out方式应该比较符合大家的思维,因为是从上位机发命令到下位机,怎么看都应该是out而不是in。 例如你在固件里设置了out的接收buf: BOOLDR_VendorCmnd(void) { switch(SETUPDAT[1]) { case0xDD: { 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】位 PUCHARbuf=newUCHAR[1]; ZeroMemory(buf,1);//用0填充buf区,填充大小(1字节) longbuflen=1;//传输的其他字节数: cy控制台console中length的值 CtlEndpoint->XferData(buf,buflen); 当然,没有规定说一定必须传给下位机至少一个字节的数据;你也可以不传;不过最好下位机同样设置接收字节为0,否则小心有莫名奇妙的错误(XX内存不能为只读等等)。 将temp=EP0BUF[0];去掉,上位机: PUCHARbuf=newUCHAR;//用0填充buf区,填充大小(1字节) longbuflen=0; CtlEndpoint->XferData(buf,buflen); 也是可以的,友情提示: 控制传输请尽量用同步的xferdata()而不是异步的begindataxfer()。 【2】in控制传输发送vendor命令 基本上,跟out区别不大。 固件中: BOOLDR_VendorCmnd(void) { switch(SETUPDAT[1]) { case0xDD: { *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】位 PUCHARbuf=newUCHAR[1];ZeroMemory(buf,1);//用0填充buf区,填充大小(1字节) longbuflen=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】位 PUCHARbuf=newUCHAR[1]; ZeroMemory(buf,1);//用0填充buf区,填充大小(1字节) longbuflen=1;//传输的其他字节数: cy控制台console中length的值 CtlEndpoint->Write(buf,buflen); Read的话同理。 bulk的话,cy开发包里有个例子cybulk写的很好,不过说实话,那个太烦琐了,基本上我们自己只用到其中的一部分,另外,就是局限性很大,例如它只是512字节的倍数,对于任意数目的字节貌似是不支持的,数据会不同步。 为了提高传输速度与效率,一般要把数据采集放在另外一个线程,单独开启一个bulk线程。 恩,前面的还是稍微提一下,在打开USB,设定端点后,紧接着开启线程,进行bulk采集: if(USBDevice->IsOpen()) {//如果USB设备已经打开 bLooping=true;//线程循环标志为真 XferThread=AfxBeginThread(XferLoop,this);//启动线程 }然后是线程中的处理,在这里上位机用异步接收,创建异步事件: OVERLAPPEDinOvLap; CVC_SimpleCyapiDlg*dlg=(CVC_SimpleCyapiDlg*)params;//使该线程可访问CBulkLoopDlg类的所有公有成员 inOvLap.hEvent=CreateEvent(NULL,false,false,"CYUSB_IN");线程循环: boolsuccess; dlg->InEndpt->TimeOut=120; for(;dlg->bLooping;)//线程循环,直到循环标志blooping为假 { LONGinlen; 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()重新设置传输大小,否则会导致数据不同步。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- vsU API 函数 使用 流程