搜档网
当前位置:搜档网 › USB上位机开发指南

USB上位机开发指南

USB上位机开发指南
USB上位机开发指南

第10章 上位机程序开发

在USB 设备开发中,上位机程序是用于与用户进行接口的。上位机程序通过USB 设备驱动程序和外部的USB 硬件进行通信,USB 固件程序执行所用的硬件操作。一般来说,根据选择开发平台的不同,可以使用Visual C++、Visual C#和LabVIEW 等开发上位机程序。

本章首先介绍了Visual C++中控制USB 设备的相关函数,接着介绍了Visual C#中读写USB 设备的主意函数,最后介绍了在LabVIEW 中如何读写USB 设备。本章内容包括:

Visual C++读写USB 设备; Visual C#读写USB 设备; LabVIEW 读写USB 设备。

10.1 Visual C++读写USB 设备

在USB 设备开发过程中,上位机程序可以采用广泛应用的Visual C++来实现。对于Cypress 公司的

EZ-USB 系列芯片,其提供了全面的CY3684开发包。在该开发包中,可以使用CYIOCTL 控制函数类和CyAPI 控制函数类来实现Visual C++环境下对USB 设备的读写。

10.1.1 CYIOCTL 控制函数类

CYIOCTL 控制函数类为Cypress 公司的EZ-USB FX2LP 系列USB 接口芯片,提供了简单的控制接口。在使用Cypress 公司提供的驱动程序基础上,只需在主机Visual C++程序中加入头文件cyioctl.h ,然后便可以调用相应的控制函数。

为了能够使用这些函数,主机程序必须首先获得USB 设备的控制句柄。可以通过以下的代码在程序中获得连接到主机的USB 设备句柄。

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

HANDLE hDevice = USBDevice->DeviceHandle();

//打开设备句柄

其中,hDevice 即为获得的USB 设备句柄。在退出程序的时候,需要释放该USB 设备句柄,使用如下的语句即可:

delete USBDevice;

在主程序获得USB 设备的控制句柄后,便可以调用CYIOCTL 控制函数类提供的接口控制函数,下面分别进行介绍。

1.中止I/O 端点的请求接口IOCTL_ADAPT_ABORT_PIPE

中止I/O 端点的请求接口IOCTL_ADAPT_ABORT_PIPE 用于中止I/O 端点的请求,其使用示例代码如下:

DWORD dwBytes = 0; UCHAR Address =

0x82; //地址

DeviceIoControl(hDevice, IOCTL_ADAPT_ABORT_PIPE, //DeviceIoControl 函数 &Address, sizeof (UCHAR),

151

NULL, 0,

&dwBytes, NULL);

这里在DeviceIoControl函数中,参数hDevice表示当前USB设备的句柄,参数IOCTL_ADAPT_ABORT_PIPE表示使用该接口进行通信,参数Address为通信的端点号及传输方向。

2.断开USB设备接口IOCTL_ADAPT_CYCLE_PORT

断开USB设备接口IOCTL_ADAPT_CYCLE_PORT用于将EZ-USB设备从USB总线上断开,并进行重连接。其使用代码示例如下:

DWORD dwBytes = 0;

DeviceIoControl(hDevice, IOCTL_ADAPT_CYCLE_PORT, //DeviceIoControl函数

NULL, 0,

NULL, 0,

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数IOCTL_ADAPT_CYCLE_PORT表示使用该接口进行通信。

3.获得设备地址接口IOCTL_ADAPT_GET_ADDRESS

获得设备地址接口IOCTL_ADAPT_GET_ADDRESS用于重新获得EZ-USB设备的地址,其使用示例代码如下:

DWORD dwBytes = 0;

UCHAR DevAddr;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_ADDRESS, //DeviceIoControl函数

&DevAddr, sizeof (UCHAR),

&DevAddr, sizeof (UCHAR),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数IOCTL_ADAPT_GET_ADDRESS表示使用该接口进行通信,DevAddr为返回的USB设备地址。

4.获取替换接口IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING

获取替换接口IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING用于获得当前EZ-USB设备的可替换接口设置,其使用示例代码如下:

DWORD dwBytes = 0;

UCHAR intfc = 0;

UCHAR alt;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING, //DeviceIoControl函数

&intfc, sizeof (alt),

&alt, sizeof (alt),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING表示使用该接口进行通信。

5.获取字符串接口IOCTL_ADAPT_GET_DEVICE_NAME

获取字符串接口IOCTL_ADAPT_GET_DEVICE_NAME用于获得连接的EZ-USB设备的产品描述字符串,其使用示例代码如下:

DWORD dwBytes = 0;

ULONG len = 256;

UCHAR *buf = new UCHAR[len];

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_DEVICE_NAME, //DeviceIoControl函数

·152·

buf, len,

buf, len,

&dwBytes, NULL);

delete[] buf;

其中,参数hDevice表示当前USB设备的句柄,参数buf为返回的字符串,参数IOCTL_ADAPT_GET_DEVICE_NAME表示使用该接口进行通信。

6.获取电源接口IOCTL_ADAPT_GET_DEVICE_POWER_STATE

获取电源接口IOCTL_ADAPT_GET_DEVICE_POWER_STATE用于获得EZ-USB设备的电源状态,其使用示例代码如下:

DWORD dwBytes = 0;

UCHAR pwrState;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_DEVICE_POWER_STATE, //DeviceIoControl函数

&pwrState, sizeof (pwrState),

&pwrState, sizeof (pwrState),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数pwrState为返回的字符串,参数IOCTL_ADAPT_GET_DEVICE_POWER_STATE表示使用该接口进行通信。

7.获取版本接口IOCTL_ADAPT_GET_DRIVER_VERSION

获取版本接口IOCTL_ADAPT_GET_DRIVER_VERSION用于获得EZ-USB驱动的版本,其使用示例代码如下:

DWORD dwBytes = 0;

ULONG ver;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_DRIVER_VERSION, //DeviceIoControl函数

&ver, sizeof (ver),

&ver, sizeof (ver),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数ver为返回的版本号,参数IOCTL_ADAPT_GET_DRIVER_VERSION表示使用该接口进行通信。

8.获取替换名称接口IOCTL_ADAPT_GET_FRIENDLY_NAME

获取替换名称接口IOCTL_ADAPT_GET_FRIENDLY_NAME用于获得EZ-USB设备的替换名称,其使用示例代码如下:

DWORD dwBytes = 0;

PUCHAR FriendlyName = new UCHAR[256];

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_FRIENDLY_NAME, //DeviceIoControl函数

FriendlyName, 256,

FriendlyName, 256,

&dwBytes, NULL);

delete[] FriendlyName;

其中,参数hDevice表示当前USB设备的句柄,参数FriendlyName为返回的字符串,参数IOCTL_ADAPT_GET_FRIENDLY_NAME表示使用该接口进行通信。

9.获取端点数接口IOCTL_ADAPT_GET_NUMBER_ENDPOINTS

获取端点数接口IOCTL_ADAPT_GET_NUMBER_ENDPOINTS用于获得EZ-USB的端点数,其使用的示例代码如下:

DWORD dwBytes = 0;

153

UCHAR endPts;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_NUMBER_ENDPOINTS, //DeviceIoControl函数

NULL, 0,

&endPts, sizeof (endPts),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数endPts为返回的端点个数,参数IOCTL_ADAPT_GET_NUMBER_ENDPOINTS表示使用该接口进行通信。

10.获取传输大小接口IOCTL_ADAPT_GET_TRANSFER_SIZE

获取传输大小接口IOCTL_ADAPT_GET_TRANSFER_SIZE用于获得EZ-USB的传输大小,其使用的示例代码如下:

DWORD BytesXfered;

SET_TRANSFER_SIZE_INFO SetTransferInfo;

SetTransferInfo.EndpointAddress = Address;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_TRANSFER_SIZE, //DeviceIoControl函数

&SetTransferInfo, sizeof (SET_TRANSFER_SIZE_INFO),

&SetTransferInfo, sizeof (SET_TRANSFER_SIZE_INFO),

&BytesXfered, NULL);

LONG transferSz = SetTransferInfo.TransferSize;

其中,参数hDevice表示当前USB设备的句柄,使用了SET_TRANSFER_SIZE_INFO结构,参数IOCTL_ADAPT_GET_TRANSFER_SIZE表示使用该接口进行通信。

11.获取USBDI接口IOCTL_ADAPT_GET_USBDI_VERSION

获取USBDI接口IOCTL_ADAPT_GET_USBDI_VERSION用于获得USBDI的版本号,其使用的示例代码如下:

DWORD dwBytes = 0;

ULONG ver;

DeviceIoControl(hDevice, IOCTL_ADAPT_GET_USBDI_VERSION, //DeviceIoControl函数

&ver, sizeof (ver),

&ver, sizeof (ver),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数ver表示返回的USBDI版本号,参数IOCTL_ADAPT_GET_USBDI_VERSION表示使用该接口进行通信。

12.复位设备接口IOCTL_ADAPT_RESET_PARENT_PORT

复位设备接口IOCTL_ADAPT_RESET_PARENT_PORT用于复位EZ-USB设备,并清除错误标记,其使用代码示例如下:

DWORD dwBytes;

DeviceIoControl(hDevice, IOCTL_ADAPT_RESET_PARENT_PORT, //DeviceIoControl函数

NULL, 0,

NULL, 0,

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数IOCTL_ADAPT_RESET_PARENT_PORT表示使用该接口进行通信。

13.复位端点接口IOCTL_ADAPT_RESET_PIPE

复位端点接口IOCTL_ADAPT_RESET_PIPE用于复位EZ-USB设备的端点,并清除错误标记,其使用代码示例如下:

·154·

DWORD dwBytes;

UCHAR Address = 0x82;

DeviceIoControl(hDevice, IOCTL_ADAPT_RESET_PIPE, //DeviceIoControl 函数 &Address, sizeof (Address) NULL, 0,

&dwBytes, NULL);

其中,参数hDevice 表示当前USB 设备的句柄,参数IOCTL_ADAPT_RESET_PIPE 表示使用该接口进行通信。 14.设置替换接口IOCTL_ADAPT_SELECT_INTERFACE

设置替换接口IOCTL_ADAPT_SELECT_INTERFACE 用于选择设置EZ-USB 可替换接口的设置,其使用示例代码如下:

DWORD dwBytes = 0; UCHAR alt = 2;

DeviceIoControl (hDevice, IOCTL_ADAPT_SELECT_INTERFACE, //DeviceIoControl 函数 &alt, sizeof (alt), &alt, sizeof (alt), &dwBytes, NULL);

其中,参数hDevice 表示当前USB 设备的句柄,参数IOCTL_ADAPT_SELECT_INTERFACE 表示使用该接口进行通信。

15.发送控制请求接口IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER

发送控制请求接口IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER 通过EZ-USB 默认的端点0向设备发送控制请求,其使用示例代码如下:

union {

struct { UCHAR Recipient:5; UCHAR Type:2; UCHAR Direction:1; } bmRequest; UCHAR bmReq; };

bmRequest.Recipient =

0; //设备 bmRequest.Type = 2; //供应商 bmRequest.Direction = 1; //输入命令(从设备到主机) int iXmitBufSize = sizeof(SINGLE_TRANSFER) + bufLen; //长度 UCHAR *pXmitBuf = new UCHAR[iXmitBufSize]; //申请内存 ZeroMemory(pXmitBuf, iXmitBufSize); PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER)pXmitBuf; pTransfer->SetupPacket.bmRequest = bmReq; pTransfer->SetupPacket.bRequest = ReqCode; pTransfer->SetupPacket.wValue = Value; pTransfer->SetupPacket.wIndex = Index; pTransfer->SetupPacket.wLength = bufLen;

pTransfer->SetupPacket.ulTimeOut = TimeOut / 1000; pTransfer->WaitForever = false; pTransfer->ucEndpointAddress = 0x00; //控制管道 pTransfer->IsoPacketLength = 0;

155

pTransfer->BufferOffset =sizeof (SINGLE_TRANSFER);

pTransfer->BufferLength =bufLen;

DWORD dwReturnBytes;

DeviceIoControl (hDevice, IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER,

pXmitBuf, iXmitBufSize,

pXmitBuf, iXmitBufSize,

&dwReturnBytes, NULL);

UCHAR *ptr = pXmitBuf + sizeof (SINGLE_TRANSFER); //复制数据到buf中

memcpy(buf, ptr, dwReturnBytes);

16.数据传输接口IOCTL_ADAPT_SEND_NON_EP0_TRANSFER

数据传输接口IOCTL_ADAPT_SEND_NON_EP0_TRANSFER用于进行EZ-USB的块、中断、同步等数据传输,其使用示例代码如下:

PUCHAR CCyBulkEndPoint::BeginDataXfer(PCHAR buf, LONG bufLen, OVERLAPPED *ov)

{

if (hDevice == INVALID_HANDLE_VALUE)

return NULL;

int iXmitBufSize =sizeof (SINGLE_TRANSFER) + bufLen;

PUCHAR pXmitBuf =new UCHAR[iXmitBufSize];

ZeroMemory(pXmitBuf, iXmitBufSize);

PSINGLE_TRANSFER pTransfer =(PSINGLE_TRANSFER)pXmitBuf;

pTransfer->WaitForever =false;

pTransfer->ucEndpointAddress =Address;

pTransfer->IsoPacketLength =0;

pTransfer->BufferOffset =sizeof (SINGLE_TRANSFER);

pTransfer->BufferLength =bufLen;

UCHAR *ptr = (PUCHAR) pTransfer + pTransfer->BufferOffset; //复制buf中的内容到pXmitBuf中 memcpy(ptr, buf, bufLen);

DWORD dwReturnBytes;

DeviceIoControl(hDevice, IOCTL_ADAPT_SEND_NON_EP0_TRANSFER,

pXmitBuf, iXmitBufSize,

pXmitBuf, iXmitBufSize,

&dwReturnBytes, ov);

return pXmitBuf;

}

17.设置电源接口IOCTL_ADAPT_SET_DEVICE_POWER_STATE

设置电源接口IOCTL_ADAPT_SET_DEVICE_POWER_STATE用于设置EZ-USB设备的电源状态,其使用示例代码如下:

DWORD dwBytes = 0;

UCHAR pwrState = 0;

DeviceIoControl(hDevice, IOCTL_ADAPT_SET_DEVICE_POWER_STATE, //DeviceIoControl函数

&pwrState, sizeof (pwrState),

&pwrState, sizeof (pwrState),

&dwBytes, NULL);

其中,参数hDevice表示当前USB设备的句柄,参数pwrState表示电源状态码,参数IOCTL_ADAPT_SET_DEVICE_POWER_STATE表示使用该接口进行通信。

18.设置传输字节接口IOCTL_ADAPT_SET_TRANSFER_SIZE

设置传输字节接口IOCTL_ADAPT_SET_TRANSFER_SIZE用于设置EZ-USB的传输字节,其使用

·156·

示例代码如下:

DWORD BytesXfered;

SET_TRANSFER_SIZE_INFO SetTransferInfo; SetTransferInfo.EndpointAddress = Address; //地址 SetTransferInfo.TransferSize =

0x2000; //8 KB 传输字节

DeviceIoControl(hDevice, IOCTL_ADAPT_SET_TRANSFER_SIZE, //DeviceIoControl 函数 &SetTransferInfo, sizeof (SET_TRANSFER_SIZE_INFO), &SetTransferInfo, sizeof (SET_TRANSFER_SIZE_INFO), &BytesXfered, NULL);

10.1.2 CyAPI 控制函数类

Cypress 的cyioctl 接口控制函数只是提供了基本的USB 控制及传输操作,一般用于测试USB 设备的连接。如果需要进行更加详细的控制操作,则需用使用CyAPI 控制函数类。

CyAPI 控制函数类提供了更为精细的控制接口来读写EZ-USB FX2LP 系列USB 接口芯片。在使用Cypress 公司提供的驱动程序基础上,只需在Visual C++主机程序的加入头文件CyAPI.h 和库文件CyAPI.lib 即可调用相应的控制函数。

CyAPI 控制函数类主要包括8个控制类,包括块传输端点控制类CCyBulkEndPoint 、控制传输端点类CCyControlEndPoint 、中断传输端点控制类CCyInterruptEndPoint 、同步传输端点控制类CCyIsocEndPoint 、设备控制类CCyUSBDevice 、配置信息类CCyUSBConfig 、端点控制类CCyUSBEndPoint 和接口控制类CCyUSBInterface 。下面分别进行介绍。

1.块传输端点控制类CCyBulkEndPoint

块传输端点控制类CCyBulkEndPoint 主要用于块传输端点。在该类中最常用的函数是BeginDataXfer ,其函数原型为:

PUCHAR CCyBulkEndPoint::BeginDataXfer(PCHAR buf, LONG len, OVERLAPPED *ov)

BeginDataXfer 函数是一个非常好用的异步IO 传输方法。这个函数建立一个数据传输通道,初始化传输,并且立刻返回,不用等待传输完毕。其使用代码示例如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

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

char inBuf[128];

ZeroMemory(inBuf, 128);

char buffer[128]; LONG length = 128;

//初始化数据输入输出

UCHAR *inContext = USBDevice->BulkInEndPt->BeginDataXfer(inBuf, length, &inOvLap); UCHAR *outContext = USBDevice->BulkOutEndPt->BeginDataXfer(buffer, length, &outOvLap); //等待传输介绍

USBDevice->BulkOutEndPt->WaitForXfer(&outOvLap,100); USBDevice->BulkInEndPt->WaitForXfer(&inOvLap,100); //结束传输

157

USBDevice->BulkOutEndPt->FinishDataXfer(buffer, length, &outOvLap,outContext);

USBDevice->BulkInEndPt->FinishDataXfer(inBuf, length, &inOvLap,inContext);

//关闭输入输出

CloseHandle(outOvLap.hEvent);

CloseHandle(inOvLap.hEvent);

2.控制传输端点类CCyControlEndPoint

在CCyControlEndPoint类中,同样定义了BeginDataXfer函数,用于异步IO操作。这里的函数原型如下:

PUCHAR CCyControlEndPoint::BeginDataXfer (PCHAR buf, LONG len, OVERLAPPED *ov)

该函数同样建立一个数据传输通道,初始化传输,并且立刻返回,不用等待传输完毕。在这里主要用于控制端点的数据传输。例如:

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

// Just for typing efficiency

CCyControlEndPoint *ept =USBDevice->ControlEndPt;

OVERLAPPED OvLap;

OvLap.hEvent =CreateEvent(NULL, false, false, "CYUSB_CTL");

char buffer[128];

LONG length =128; //长度

ept->Target = TGT_DEVICE;

ept->ReqType =REQ_VENDOR;

ept->Direction =DIR_TO_DEVICE;

ept->ReqCode =0x05; //请求码

ept->Value = 1;

ept->Index =0;

PUCHAR Context =ept->BeginDataXfer(buffer, length, &OvLap);

ept->WaitForXfer(&OvLap,100);

ept->FinishDataXfer(buffer, length, &OvLap,Context);

CloseHandle(OvLap.hEvent);

在程序中,首先声明控制端点ept,并对ept进行了参数设置。共有5个参数,规定的端点0传输的方向,数据字节数等。下面分别介绍:

Target:控制传输中的一个重要的参数,其可取值为TGT_DEVICE、TGT_INTFC、TGT_ENDPT 和TGT_OTHER。

ReqType:请求的类型,其可取值为REQ_STD、REQ_CLASS和REQ_VENDOR。

Direction:控制控制端点数据传输的方向,其可取值为DIR_TO_DEVICE和DIR_FROM_DEVICE 两个。

ReqCode:请求的代码,在USB芯片的固件程序中,对该代码有专门的处理程序。控制端点的通信,主要便是通过其来实现的。

Value:控制传输的重要参数,其值依赖于ReqCode参数。

Index:控制传输的重要参数,其值依赖于ReqCode参数。

本例中,对ept初始化表示数据从USB设备发送到主机,数据长度为128个字节。通过BeginDataXfer 函数将该命令发送USB设备。USB芯片得到这个请求后,在相应的请求代码程序处理中将128个数据

·158·

发送给主机,主机将接收到的数据保存在buffer 中。

除此以外,该类中还定义了Write 和Read 函数,其函数原型为:

bool CCyControlEndPoint::Write(PCHAR buf, LONG &len) bool CCyControlEndPoint::Read( PCHAR buf, LONG &len)

Write 函数是一个简化版本的传输函数,将函数的传输方向固定为DIR_TO_DEVICE ,即主机向USB 设备发送数据。Write 函数的使用代码示例如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

// Just for typing efficiency CCyControlEndPoint *ept = USBDevice->ControlEndPt; //控制端点

ept->Target = TGT_DEVICE; ept->ReqType = REQ_VENDOR; ept->ReqCode = 0x07;

//请求码

ept->Value = 1; ept->Index = 0;

char buf[512];

ZeroMemory(buf,512); LONG bytesToSend = 128;

ept->Write(buf, bytesToSend); //Write 函数

Read 函数是一个简化版本的传输函数,将函数的传输方向固定为DIR_FROM_DEVICE ,即主机向USB 设备发送数据。Read 函数的使用代码示例如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

// Just for typing efficiency CCyControlEndPoint *ept = USBDevice->ControlEndPt; //控制端点

ept->Target = TGT_DEVICE; ept->ReqType = REQ_VENDOR; ept->ReqCode = 0x07; ept->Value = 1; ept->Index = 0;

char buf[512]; LONG bytesToRead = 64;

ept->Read(buf, bytesToRead); //Read 函数

3.中断传输端点控制类CCyInterruptEndPoint

中断传输端点控制类CCyInterruptEndPoint 为CCyUSBEndPoint 类的一个子类。中断传输端点控制类CCyInterruptEndPoint 对中断端点的定义和使用代码,示例如下:

CCyInterruptEndPoint *IntInEpt = NULL; CCyInterruptEndPoint *IntOutEpt = NULL;

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

int eptCount = USBDevice->EndPointCount(); for (int i =

1; i

159

bool bIn =USBDevice->EndPoints[i]->Address & 0x80;

bool bInt =(USBDevice->EndPoints[i]->Attributes ==3);

if (bInt && bIn) IntInEpt =(CCyInterruptEndPoint *) USBDevice->EndPoints[i];

if (bInt && !bIn) IntOutEpt =(CCyInterruptEndPoint *) USBDevice->EndPoints[i];

}

在CCyInterruptEndPoint类中,同样定义了BeginDataXfer函数,其用法和前面的类似,这里不再具体介绍。BeginDataXfer函数原型为:

PUCHAR CCyInterruptEndPoint::BeginDataXfer(PCHAR buf, LONG len, OVERLAPPED *ov)

4.同步传输端点控制类CCyIsocEndPoint

同步传输端点控制类CCyIsocEndPoint同样为CCyUSBEndPoint类的一个子类。同步传输端点控制类CCyIsocEndPoint对同步端点的定义和使用代码,示例如下:

CCyIsocEndPoint *IsocInEpt = NULL;

CCyIsocEndPoint *IsocOutEpt =NULL;

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

int eptCount =USBDevice->EndPointCount();

for (int i=1; i

bool bIn =USBDevice->EndPoints[i]->Address & 0x80;

bool bInt =(USBDevice->EndPoints[i]->Attributes ==1);

if (bInt && bIn) IsocInEpt =(CCyIsocEndPoint *) USBDevice->EndPoints[i];

if (bInt && !bIn) IsocOutEpt =(CCyIsocEndPoint *) USBDevice->EndPoints[i];

}

在CCyIsocEndPoint类中定义了两个主要的函数:BeginDataXfer和CreatePktInfos。下面分别介绍。

BeginDataXfer函数

BeginDataXfer函数同样用于执行异步IO操作,其函数原型为:

PUCHAR CCyIsocEndPoint::BeginDataXfer (PCHAR buf, LONG len, OVERLAPPED *ov)

BeginDataXfer函数使用示例代码如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(hWnd);

CCyIsocEndPoint *IsoIn =USBDevice->IsocInEndPt;

if (IsoIn)

{

int pkts = 16;

LONG bufSize =IsoIn->MaxPktSize * pkts;

PUCHAR context;

OVERLAPPED inOvLap;

PUCHAR buffer =new UCHAR[bufSize];

CCyIsoPktInfo *isoPktInfos = new CCyIsoPktInfo[pkts];

IsoIn->SetXferSize(bufSize);

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

// 开始数据传输

·160·

context =IsoIn->BeginDataXfer(buffer, bufSize, &inOvLap);

// 等待传输完毕

if (!IsoIn->WaitForXfer(&inOvLap, 1500))

{

IsoIn->Abort();

// Wait for the stalled command to complete

WaitForSingleObject(inOvLap.hEvent,INFINITE);

}

int complete = 0;

int partial =0;

// 必须调用FinishDataXfer函数清除内存

if (IsoIn->FinishDataXfer(buffer, bufSize, &inOvLap, context, isoPktInfos))

{

for (int i=0; i< pkts; i++)

if (isoPktInfos[i].Status)

partial++;

else

complete++;

}

else

partial++;

//删除buffer

delete

buffer;

delete [] isoPktInfos;

}

CreatePktInfos函数

CreatePktInfos函数用于创建CCyIsoPktInfo实体,用于同步数据传输中,其函数原型为:CCyIsoPktInfo* CCyIsocEndPoint::CreatePktInfos(LONG bufLen, int &packets)

CreatePktInfos函数的使用示例代码如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice();

CCyIsocEndPoint *IsoIn =USBDevice->IsocInEndPt;

if (IsoIn) {

LONG bufSize =4096;

PUCHAR buffer =new UCHAR[bufSize];

CCyIsoPktInfo *isoPktInfos;

int pkts;

// 申请IsoPktInfo 实体,并指出多少个申请到

isoPktInfos =IsoIn->CreatePktInfos(bufSize, pkts);

if (IsoIn->XferData(buffer, bufSize, isoPktInfos)) {

LONG recvdBytes = 0;

161

for (int i=0; i

if (isoPktInfos[i].Status == 0)

recvdBytes +=isoPktInfos[i].Length;

}

delete

[]

buffer; //删除buffer

delete [] isoPktInfos;

}

5.设备控制类CCyUSBDevice

设备控制类CCyUSBDevice是一个原始的库入口类指针,其中定义了很多USB设备的各种操作,使用前必须首先获得USB设备的句柄。CCyUSBDevice类中的成员函数,如表10.1所示。

表10.1 CCyUSBDevice类成员函数

函数名声明原形功能

AltIntfc函数UCHAR CCyUSBDevice::AltIntfc(void) 返回当前设备的可替换接口设置。AltIntfcCount函数UCHAR CCyUSBDevice::AltIntfcCount(void) 返回设备的可替换接口数。BcdDevice USHORT

CCyUSBDevice::BcdUSB USB设备描述符中的BcdUSB值。BcdUSB USHORT

CCyUSBDevice::BcdUSB USB设备描述符中的BcdUSB值。BulkInEndPt CCyBulkEndPoint*

CCyUSBDevice::BulkInEndPt

指向第一个块输入端点数据的指

针。

BulkOutEndPt CCyBulkEndPoint*

CCyUSBDevice::BulkOutEndPt 指向第一个块输出端点数据的指

针。

Close函数void CCyUSBDevice:: Close(void) 关断主机程序和USB驱动的接口。Config函数UCHAR CCyUSBDevice::Config(void) 返回USB设备的当前设置值。ConfigAttrib UCHAR

CCyUSBDevice::ConfigAttrib USB设备当前配置描述符的

ConfigAttrib值。

ConfigCount函数UCHAR CCyUSBDevice::ConfigCount( void) 返回USB设备的配置数。ConfigValue UCHAR

CCyUSBDevice::ConfigValue USB设备当前配置描述符的

bConfigurationValue值。ControlEndPt CCyControlEndPoint* CCyUSBDevice::ControlEndPt 指向控制端点0。

DevClass UCHAR

CCyUSBDevice::DevClass USB描述符的bDeviceClass值。DeviceCount函数UCHAR CCyUSBDevice::DeviceCount(void) 返回连接到USB总线上的USB设

备个数。

DeviceHandle函数HANDLE CCyUSBDevice::DeviceHandle(void) 返回USB设备的句柄。

DeviceName char

CCyUSBDevice::DeviceName[USB_STRING_MAXLEN] 字符数组,表示设备描述符的iProduct域。

DevProtocol UCHAR

CCyUSBDevice::DevProtocol USB设备描述符bDeviceProtocol域

的值。

DevSubClass UCHAR

CCyUSBDevice::DevSubClass USB设备描述符bDeviceSubClass

域的值。

DriverGUID函数GUID CCyUSBDevice::DriverGUID(void) 返回USB驱动的GUID值。DriverVersion ULONG

CCyUSBDevice::DriverVersion 驱动的版本。

EndPointCount函数UCHAR CCyUSBDevice::EndPointCount( void) 返回当前接口的端点数加1,即包

括端点0。

EndPointOf函数CCyUSBEndPoint* CCyUSBDevice::EndPointOf(UCHAR

addr)

返回端点的指针。

EndPoints CCyUSBEndPoint*

CCyUSBDevice::EndPoints 端点的列表。

FriendlyName char

CCyUSBDevice::FriendlyName[USB_STRING_MAXLEN] 驱动文件中的FriendlyName字段值。

·162·

GetDeviceDescriptor函数void

获得当前设备的设备描述符。

CCyUSBDevice::GetDeviceDescriptor(PUSB_DEVICE_DE

SCRIPTOR descr)

GetConfigDescriptor函数void

获得当前设备的配置描述符。

CCyUSBDevice::GetConfigDescriptor(PUSB_CONFIGURA

TION_DESCRIPTOR descr)

GetIntfcDescriptor函数void

获得当前选择的接口描述符。

CCyUSBDevice::GetIntfcDescriptor(PUSB_INTERFACE_D

ESCRIPTOR descr)

GetUSBConfig函数CCyUSBConfig CCyUSBDevice::GetUSBConfig(int index) 返回配置描述符中的内容。Interface函数UCHAR CCyUSBDevice::Interface(void) 返回当前选择的设备接口号。InterruptInEndPt CCyInterruptEndPoint* CCyUSBDevice::InterruptInEndPt 指向当前接口的中断IN端点。InterruptOutEndPt CCyInterruptEndPoint* CCyUSBDevice::InterruptOutEndPt 指向当前接口的中断OUT端点。IntfcClass UCHAR

CCyUSBDevice::IntfcClass 当前接口描述符的

bInterfaceClass域的值。IntfcCount函数UCHAR CCyUSBDevice::IntfcCount(void) 返回USB设备的配置描述符

bNumInterfaces域的值。

CCyUSBDevice::IntfcProtocol 表示bInterfaceProtocol值。IntfcProtocol UCHAR

CCyUSBDevice::IntfcSubClass 当前接口描述符IntfcSubClass域的IntfcSubClass UCHAR

值。

IsocInEndPt CCyIsocEndPoint* CCyUSBDevice::IsocInEndPt 指向当前接口的同步IN端点。

CCyUSBDevice::IsocOutEndPt 指向当前接口的同步OUT端点。IsocOutEndPt CCyIsocEndPoint*

IsOpen函数bool CCyUSBDevice::IsOpen(void) 检查是否获得USB设备的句柄并

启动该设备。

Manufacturer wchar_t

设备描述符iManufacturer的值。

CCyUSBDevice::Manufacturer[USB_STRING_MAXLEN]

CCyUSBDevice::MaxPacketSize 设备描述符bMaxPacketSize0域的MaxPacketSize UCHAR

值。

MaxPower UCHAR

CCyUSBDevice::MaxPower 当前配置描述符MaxPower域的

值。

Open函数bool CCyUSBDevice::Open(UCHAR dev) 打开USB设备。

Product wchar_t

设备描述符iProduct域的值。

CCyUSBDevice::Product[USB_STRING_MAXLEN]

CCyUSBDevice::ProductID 设备描述符idProduct域的值。ProductID USHORT

ReConnect函数bool CCyUSBDevice::ReConnect(void) 断开USB设备,并进行重连接。Reset函数bool CCyUSBDevice::Reset( void) 复位USB设备。

SerialNumber wchar_t

设备描述符iSerialNumber域的值。

CCyUSBDevice::SerialNumber[USB_STRING_MAXLEN]

SetConfig函数void CCyUSBDevice::SetConfig( UCHAR cfg) 设置当前设备的配置。SetAltIntfc函数bool CCyUSBDevice::SetAltIntfc(UCHAR alt) 设置设备接口。

CCyUSBDevice::StrLangID 设备第一个字符串描述符的StrLangID USHORT

bString域的值。

CCyUSBDevice::USBAddress 当前打开的USB设备的总线地址。USBAddress UCHAR

CCyUSBDevice::USBDIVersion USB主机驱动器的版本,其值为USBDIVersion ULONG

BCD码的形式。

CCyUSBDevice::VendorID 设备描述符idVendor域的值。VendorID USHORT

下面介绍常用的成员函数及其在程序设计中的应用。

BulkInEndPt

BulkInEndPt为指向第一个块输入端点数据的指针的,其使用示例代码如下:

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

CCyBulkEndPoint *BulkIn2 = NULL;

163

int eptCount = USBDevice->EndPointCount();

for (int i =1; iEndPoints[i]->bIn; bool bBulk = (USBDevice->EndPoints[i]->Attributes == 2);

if (bBulk && bIn) BulkIn2 = (CCyBulkEndPoint *) USBDevice->EndPoints[i]; if (BulkIn2 == USBDevice->BulkInEndPt) BulkIn2 = NULL; }

BulkOutEndPt

BulkOutEndPt 为指向第一个块输出端点数据的指针的,其使用示例代码如下:

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

CCyBulkEndPoint *BulkOut2 = NULL;

int eptCount = USBDevice->EndPointCount();

for (int i=1; i

//OUT 端点信息

bool bIn = USBDevice->EndPoints[i]->Address & 0x80; bool bBulk = (USBDevice->EndPoints[i]->Attributes == 2);

if (bBulk && !bIn) BulkOut2 = (CCyBulkEndPoint *) USBDevice->EndPoints[i]; if (BulkOut2 == USBDevice->BulkOutEndPt) BulkOut2 = NULL; }

ControlEndPt

ControlEndPt 指向控制端点0,其使用示例代码如下所示:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

// Just for

typing efficiency CCyControlEndPoint *ept = USBDevice->ControlEndPt; //控制端点

ept->Target = TGT_DEVICE; ept->ReqType = REQ_VENDOR; ept->Direction = DIR_TO_DEVICE; ept->ReqCode = 0x05;

//请求码

ept->Value = 1; ept->Index = 0;

char buf[512]; ZeroMemory(buf, 512); LONG buflen = 512;

ept->XferData(buf, buflen); //传输

DeviceCount 函数

DeviceCount 函数用于返回连接到USB 总线上的USB 设备个数,其使用示例代码如下所示:

USBDevice = new CCyUSBDevice(Handle);

int devices = USBDevice->DeviceCount( ); //统计设备个数

·164·

int vID, pID;

int d = 0;

do {

USBDevice->Open(d); //自动打开USB设备

vID =USBDevice->VendorID;

pID =USBDevice->ProductID

d++;

} while ((d < devices ) && (vID != 0x0547) && (pID != 0x1002));

EndPointCount函数

EndPointCount函数返回当前接口的端点数加1,即包括端点0。其使用示例代码如下:CCyBulkEndPoint *BulkInEpt = NULL;

CCyBulkEndPoint *BulkOutEpt = NULL;

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

int eptCount =USBDevice->EndPointCount();

// 跳过控制端点0

for (int i=1; i

{

bool bIn =USBDevice->EndPoints[i]->Address & 0x80;

bool bBulk =(USBDevice->EndPoints[i]->Attributes ==2);

if (bBulk && bIn) B ulkInEpt =(CCyBulkEndPoint *) USBDevice->EndPoints[i];

if (bBulk && !bIn) BulkOutEpt =(CCyBulkEndPoint *) USBDevice->EndPoints[i];

}

EndPointOf函数

EndPointOf函数用于返回端点的指针,其使用示例代码如下:

UCHAR eptAddr = 0x82;

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

CCyUSBEndPoint *EndPt = USBDevice->EndPointOf(eptAddr);

if (EndPt) EndPt->Reset( );

EndPoints

EndPoints是端点的列表,其使用示例代码如下:

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

int epCnt =USBDevice->EndPointCount();

bool bBulk, bIn;

int blkInCnt =0;

for (int e=0; e

bBulk =USBDevice->EndPoints[e]->Attributes ==2;

bIn =USBDevice->EndPoints[e]->Address & 0x80;

if (bBulk && bIn) blkInCnt++;

}

GetUSBConfig函数

165

GetUSBConfig函数用于返回配置描述符中的内容,其使用示例代码如下:

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

String s;

for (int c=0; cConfigCount(); c++) {

CCyUSBConfig cfg = USBDevice->GetUSBConfig(c);

//输出配置信息

s.sprintf("bLength: 0x%x",cfg.bLength); EZOutputMemo->Lines->Add(s);

s.sprintf("bDescriptorType: %d",cfg.bDescriptorType); EZOutputMemo->Lines->Add(s);

s.sprintf("wTotalLength: %d (0x%x)",cfg.wTotalLength,cfg.wTotalLength); EZOutputMemo->Lines->Add(s);

s.sprintf("bNumInterfaces: %d",cfg.bNumInterfaces); EZOutputMemo->Lines->Add(s);

s.sprintf("bConfigurationValue: %d",cfg.bConfigurationValue); EZOutputMemo->Lines->Add(s);

s.sprintf("iConfiguration: %d",cfg.iConfiguration); EZOutputMemo->Lines->Add(s);

s.sprintf("bmAttributes: 0x%x",cfg.bmAttributes); EZOutputMemo->Lines->Add(s);

s.sprintf("MaxPower: %d",cfg.MaxPower); EZOutputMemo->Lines->Add(s);

EZOutputMemo->Lines->Add("**********************************");

for (int i=0; i

CCyUSBInterface *ifc =cfg.Interfaces[i];

EZOutputMemo->Lines->Add("Interface Descriptor:" + String(i+1));

EZOutputMemo->Lines->Add("--------------------------------");

s.sprintf("bLength: 0x%x",ifc->bLength); EZOutputMemo->Lines->Add(s);

s.sprintf("bDescriptorType: %d",ifc->bDescriptorType); EZOutputMemo->Lines->Add(s);

s.sprintf("bInterfaceNumber: %d",ifc->bInterfaceNumber); EZOutputMemo->Lines->Add(s);

s.sprintf("bAlternateSetting: %d",ifc->bAlternateSetting); EZOutputMemo->Lines->Add(s);

s.sprintf("bNumEndpoints: %d",ifc->bNumEndpoints); EZOutputMemo->Lines->Add(s);

s.sprintf("bInterfaceClass: %d",ifc->bInterfaceClass); EZOutputMemo->Lines->Add(s);

for (int e=0; ebNumEndpoints; e++) {

CCyUSBEndPoint *ept =ifc->EndPoints[e+1];

EZOutputMemo->Lines->Add("EndPoint Descriptor: " + String(e+1));

EZOutputMemo->Lines->Add("--------------------------------");

s.sprintf("bLength: 0x%x",ept->DscLen); EZOutputMemo->Lines->Add(s);

s.sprintf("bDescriptorType: %d",ept->DscType); EZOutputMemo->Lines->Add(s);

s.sprintf("bEndpointAddress: 0x%x",ept->Address); EZOutputMemo->Lines->Add(s);

s.sprintf("bmAttributes: 0x%x",ept->Attributes); EZOutputMemo->Lines->Add(s);

s.sprintf("wMaxPacketSize: %d",ept->MaxPktSize); EZOutputMemo->Lines->Add(s);

s.sprintf("bInterval: %d",ept->Interval); EZOutputMemo->Lines->Add(s);

EZOutputMemo->Lines->Add("**********************************");

}

}

}

InterruptInEndPt

InterruptInEndPt用于指向当前接口的中断IN端点,其使用示例代码如下:

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

CCyInterruptEndPoint *IntIn2 = NULL;

·166·

int eptCount =USBDevice->EndPointCount();

for (int i=1; iEndPoints[i]->Address & 0x80;

bool bInt =(USBDevice->EndPoints[i]->Attributes == 3);

if (bInt && bIn) IntIn2 =(CCyInterruptEndPoint *) USBDevice->EndPoints[i];

if (IntIn2 ==USBDevice->InterruptInEndPt) IntIn2 = NULL;

}

InterruptOutEndPt

InterruptOutEndPt用于指向当前接口的中断OUT端点,其使用示例代码如下:CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

CCyInterruptEndPoint *IntOut2 = NULL;

int eptCount = USBDevice->EndPointCount();

for (int i=1; i

bool bIn =USBDevice->EndPoints[i]->Address & 0x80;

bool bInt = (USBDevice->EndPoints[i]->Attributes == 3);

if (bInt && !bIn) IntOut2 =(CCyInterruptEndPoint *) USBDevice->EndPoints[i];

if (IntOut2 ==USBDevice->InterruptOutEndPt) IntOut2 = NULL;

}

IsocInEndPt

IsocInEndPt用于指向当前接口的同步IN端点,其使用示例代码如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

CCyIsocEndPoint *IsocIn2 = NULL;

int eptCount = USBDevice->EndPointCount();

for (int i=1; iEndPoints[i]->Address & 0x80;

bool bIsoc =(USBDevice->EndPoints[i]->Attributes == 1);

if (bIsoc && bIn) IsocIn2 =(CCyIsocEndPoint *) USBDevice->EndPoints[i];

if (IsocIn2 == USBDevice->IsocInEndPt) IsocIn2 = NULL;

}

IsocOutEndPt

IsocOutEndPt用于指向当前接口的同步OUT端点,其使用示例代码如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

CCyIsocEndPoint *IsocOut2 = NULL;

int eptCount = USBDevice->EndPointCount();

for (int i=1; iEndPoints[i]->Address & 0x80;

bool bIsoc =(USBDevice->EndPoints[i]->Attributes == 1);

167

if (bIsoc && !bIn) IsocOut2 = (CCyIsocEndPoint *) USBDevice->EndPoints[i];

if (IsocOut2 ==USBDevice->IsocOutEndPt) IsocOut2 = NULL;

}

Open函数

Open用于打开USB设备,其使用示例代码如下:

CCyUSBDevice *USBDevice = new CCyUSBDevice(Handle);

if (USBDevice->DeviceCount() && !USBDevice->Open(0)) { //打开设备0

USBDevice->Reset();

USBDevice->Open(0);

}

if (! USBDevice->IsOpen()) return false;

ProductID和VendorID

ProductID用于表示设备描述符idProduct域的值,VendorID用于表示设备描述符idVendor域的值。ProductID和VendorID的使用示例代码如下所示:

USBDevice =new CCyUSBDevice(Handle); // Create an instance of CCyUSBDevice

int devices =USBDevice->DeviceCount();

int vID, pID;

int d = 0;

do {

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

vID =USBDevice->VendorID;

pID =USBDevice->ProductID;

d++;

} while ((d < devices ) && (vID != 0x0547) && (pID != 0x1002));

6.配置信息类CCyUSBConfig

配置信息类CCyUSBConfig用于表示USB设备的配置信息。其定义了很多配置值。配置信息类CCyUSBConfig中的配置信息,如表10.2所示。

表10.2 配置信息类CCyUSBConfig的配置信息

配置名声明原型功能

AltInterfaces CCyUSBConfig::AltInterfaces 配置的接口总数。

CCyUSBConfig::bConfigurationValue 所选择配置描述符bConfigurationValue域bConfigurationValue UCHAR

的值。

bDescriptorType UCHAR

CCyUSBConfig::bDescriptorType 配置描述符bDescriptorType域的值。

CCyUSBConfig::bLength 当前选择配置描述符的bLength域的值。bLength UCHAR

CCyUSBConfig::bmAttributes 当前选择配置描述符的bmAttributes域的bmAttributes UCHAR

值。

bNumInterfaces UCHAR

CCyUSBConfig::bNumInterfaces 当前选择配置描述符bNumInterfaces域的

值。

CCyUSBConfig::iConfiguration 当前选择配置描述符iConfiguration域的iConfiguration UCHAR

值。

cfg)CCyUSBConfig的类结构。CCyUSBConfig CCyUSBConfig::CCyUSBConfig(CCyUSBConfig&

Interfaces CCyUSBInterface*

表示各个接口描述符。

CCyUSBConfig::Interfaces[MAX_INTERFACES]

CCyUSBConfig::wTotalLength 所选配置描述符wTotalLength域的值。wTotalLength USHORT

·168·

这里最主要的是Interfaces,其用于表示各个接口描述符。Interfaces的使用示例代码如下:

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

String s;

for (int c=0; cConfigCount(); c++) {

CCyUSBConfig cfg = USBDevice->GetUSBConfig(c);

//输出接口信息

s.sprintf("bLength: 0x%x",cfg.bLength); EZOutputMemo->Lines->Add(s);

s.sprintf("bDescriptorType: %d",cfg.bDescriptorType); EZOutputMemo->Lines->Add(s);

s.sprintf("wTotalLength: %d (0x%x)",cfg.wTotalLength,cfg.wTotalLength);

EZOutputMemo->Lines->Add(s);

s.sprintf("bNumInterfaces: %d",cfg.bNumInterfaces); EZOutputMemo->Lines->Add(s);

s.sprintf("bConfigurationValue: %d",cfg.bConfigurationValue); EZOutputMemo->Lines->Add(s);

s.sprintf("iConfiguration: %d",cfg.iConfiguration); EZOutputMemo->Lines->Add(s);

s.sprintf("bmAttributes: 0x%x",cfg.bmAttributes); EZOutputMemo->Lines->Add(s);

s.sprintf("MaxPower: %d",cfg.MaxPower); EZOutputMemo->Lines->Add(s);

EZOutputMemo->Lines->Add("**********************************");

for (int i=0; i

CCyUSBInterface *ifc =cfg.Interfaces[i];

EZOutputMemo->Lines->Add("Interface Descriptor:" + String(i+1));

EZOutputMemo->Lines->Add("--------------------------------");

s.sprintf("bLength: 0x%x",ifc->bLength); EZOutputMemo->Lines->Add(s);

s.sprintf("bDescriptorType: %d",ifc->bDescriptorType); EZOutputMemo->Lines->Add(s);

s.sprintf("bInterfaceNumber: %d",ifc->bInterfaceNumber); EZOutputMemo->Lines->Add(s);

s.sprintf("bAlternateSetting: %d",ifc->bAlternateSetting); EZOutputMemo->Lines->Add(s);

s.sprintf("bNumEndpoints: %d",ifc->bNumEndpoints); EZOutputMemo->Lines->Add(s);

s.sprintf("bInterfaceClass: %d",ifc->bInterfaceClass); EZOutputMemo->Lines->Add(s);

for (int e=0; ebNumEndpoints; e++) {

CCyUSBEndPoint *ept =ifc->EndPoints[e+1];

EZOutputMemo->Lines->Add("EndPoint Descriptor: " + String(e+1));

EZOutputMemo->Lines->Add("--------------------------------");

s.sprintf("bLength: 0x%x",ept->DscLen); EZOutputMemo->Lines->Add(s);

s.sprintf("bDescriptorType: %d",ept->DscType); EZOutputMemo->Lines->Add(s);

s.sprintf("bEndpointAddress: 0x%x",ept->Address); EZOutputMemo->Lines->Add(s);

s.sprintf("bmAttributes: 0x%x",ept->Attributes); EZOutputMemo->Lines->Add(s);

s.sprintf("wMaxPacketSize: %d",ept->MaxPktSize); EZOutputMemo->Lines->Add(s);

s.sprintf("bInterval: %d",ept->Interval); EZOutputMemo->Lines->Add(s);

EZOutputMemo->Lines->Add("**********************************");

}

}

}

7.端点控制类CCyUSBEndPoint

端点控制类CCyUSBEndPoint包含了对USB端点的各种描述符及操作函数。端点控制类CCyUSBEndPoint中的函数,如表10.3所示。

169

表10.3 端点控制类CCyUSBEndPoint的函数

函数名声明原型功能

Abort函数void CCyUSBEndPoint::Abort(void) 中止IO传输端点。

Address UCHAR

CCyUSBEndPoint::Address 设备返回的端点描述符

bEndpointAddress域的值。Attributes UCHAR

CCyUSBEndPoint::Attributes 端点描述符bmAttributes域的值。

BeginDataXfer函数virtual PUCHAR CCyUSBEndPoint::BeginDataXfer(PCHAR

buf, LONG len, OVERLAPPED *ov) = 0 用于通过端点进行异步数据传输。

bIn bool

CCyUSBEndPoint::bIn 表示该端点是否为IN端点。CCyUSBEndPoint CCyUSBEndPoint::CCyUSBEndPoint(CCyUSBEndPoint& ept) CCyUSBEndPoint类的构造。DscLen UCHAR

CCyUSBEndPoint::DscLen USB端点描述符bLength域的值。DscType UCHAR

CCyUSBEndPoint::DscType USB端点描述符bDescriptorType

域的值。

GetXferSize函数ULONG CCyUSBEndPoint::GetXferSize(void) 返回当前端点的传输字节数

FinishDataXfer函数bool CCyUSBEndPoint::FinishDataXfer(PCHAR buf, LONG

&len, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo*

pktInfos = NULL) 用于异步数据传输中,将数据保存或其他操作。

hDevice HANDLE

CCyUSBEndPoint::hDevice 表示获得的USB句柄。

Interval UCHAR

CCyUSBEndPoint::Interval 端点描述符bInterval域中的值。MaxPktSize UCHAR

CCyUSBEndPoint::MaxPktSize 表示端点描述符wMaxPacketSize

域中的值

Reset函数bool CCyUSBEndPoint::Reset(void) 复位端点,并清除错误标记。SetXferSize函数void CCyUSBEndPoint::SetXferSize(ULONG xfer) 用于设置传输大小。

TimeOut ULONG

CCyUSBEndPoint::TimeOut 用于表示传输等待的时间。WaitForXfer函数bool CCyUSBEndPoint::WaitForXfer(OVERLAPPED *ov,

ULONG tOut)

用于等待异步通信结束。

XferData函数bool CCyUSBEndPoint::XferData(PCHAR buf, LONG &len,

PUCHAR pktInfos = NULL)

用于进行同步IO数据传输。

下面介绍程序设计中常用的函数及其用法。

Abort函数

Abort函数用于中止IO传输端点,其使用示例代码如下:

CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

USBDevice->ControlEndPt->Abort(); //停止端点

Address

Address用于表示设备返回的端点描述符bEndpointAddress域的值,其高位如果为(0x8_)则表示IN端点,如果高位为(0x0_)则表示OUT端点。Address的使用代码,示例如下: CCyUSBDevice *USBDevice =new CCyUSBDevice(Handle);

CCyBulkEndPoint *BulkIn2 = NULL;

int eptCount = USBDevice->EndPointCount();

for (int i=1; i

bool bIn =USBDevice->EndPoints[i]->Address & 0x80; //端点地址

bool bBulk =(USBDevice->EndPoints[i]->Attributes ==2);

if (bBulk && bIn) BulkIn2 = (CCyBulkEndPoint *) USBDevice->EndPoints[i];

if (BulkIn2 ==BulkInEndPt) BulkIn2 =NULL;

}

上位机和下位机通信

目录 摘要 1 引言 (1) 2 结构设计与方案选择 (2) 2.1设计任务 (2) 2.1.1单片机的选择 (2) 2.1.2电平转换 (2) 2.1.1单片机的选择 (2) 2.1.3单片机与pc机通信原理 (2) 2.2软件方案选择 (2) 2.2.1 上位机编程方案选择 (3) 2.2.2 单片机编程方案选择 (3) 2.3 总体方案选择 (2) 3 硬件设计 (8) 3.1单片机主要特性 (5) 3.2 MAX232电平芯片介绍10 (10) 3.3 硬件电路设计图 (11) 3.3.1 PC机与单片机通信接口电路设计框图 (11) 3.3.2整体设计原理图 (11) 4软件设计 (12) 4.1上位机程序设计 (12) 4.2下位机程序设计 (13) 5 软硬件调试部分 (21) 5.1 PROTEUS软件仿真 (21) 5.1.1 Protues简介 (21) 5.1.2 Protues仿真电路图 (22) 5.2 VC软件仿真 (21) 结束语 (27) 致谢 (28) 参考文献 (29)

摘要 本文主要描述了利用PC机与AT89C51单片机之间的通信程序设计实现温度显示。并详述了在VC6.0环境下,上位机利用MSCOMM通信控件与单片机之间串口通信实现温度显示。由单片机采集一个温度信号,将采集到的温度信号传送给PC机显示,PC机用VC6.0编写程序,单片机程序用C语言编写,最后用PROTUES软件进行仿真实现温度显示。 关键词:单片机MSCOMM控件VC6.0 AT89C51 温度显示

1引言 随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从单片机技术入手,一切向着数字化控制,智能化控制方向发展。 现代化集中管理需要对现场数据进行统计、分析、制表、打印、绘图、报警等,同时,又要求对现场装置进行实时控制,完成各种规定操作,达到集中管理的目的。加之单片机的计算能力有限,难以进行复杂的数据处理。因此在功能比较复杂的控制系统中,通常以PC机为上位机,单片机为下位机,由单片机完成数据的采集及对装置的控制,而由上位机完成各种复杂的数据处理及对单片机的控制。

单机下各屏幕与上位机使用说明

目录 1. .......................................................... 设备拨码开关设置2 2. ............................................................. 触摸屏使用说明3 2.1触摸屏硬件配置 (3) 2.2触摸屏界面结构及上电说明 (3) 2.3触摸屏界面使用说明 (5) 2.3.1数据显示界面 (5) 2.3.2状态显示界面 (8) 2.3.3记录界面 (10) 2.3.4设置界面 (10) 2.3.5密码说明 (19) 3. ............................................................... 大屏使用说明20 3.1大屏硬件配置 (20) 3.2大屏操作说明 (20) 3.3大屏参数设置说明 (20) 4. ............................................................. 上位机使用说明20 4.1上位机硬件配置 (20) 4.2上位机操作说明 (20) 4.3上位机界面说明 (21)

1.设备拨码开关设置 SmartAPF功率单元对外通讯分别可与触摸屏、大屏、小屏和PC端的上位机通讯(同一时刻只能接入其中一种,小屏暂未开放),通讯接口使用的是485接口,一个单元有2个485接口可用,接口的选用根据拨码开关状态来判定。在使用上述4种人机界面通讯前,需要检查拨码开关设置是否正确。 拨码开关5 6 7 8 通讯485模块选择 触摸屏接485模块1,PC接485模块2 触摸屏接485模块2,PC接485模块1 触摸屏接485模块1,大屏接485模块2 触摸屏接485模块2,大屏接485模块1 大屏接485模块1,PC接485模块2

基于C#的串口通信上位机和下位机源程序

基于单片机串口通信的上位机和下位机实践 串口是计算机上一种非常通用设备通信的协议(不要与通用串行总线Universal Serial Bus或者USB混淆)。大多数计算机包含两个基于RS232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。 串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。 首先亮出C#的源程序吧。 主要界面: 只是作为简单的运用,可以扩展的。 源代码: using System; using System.Collections.Generic; using https://www.sodocs.net/doc/9011972130.html,ponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO.Ports; using System.Timers; namespace 单片机功能控制 { public partial class Form1 : Form

{ public Form1() { InitializeComponent(); } SerialPort sp = new SerialPort(); private void button1_Click(object sender, EventArgs e) { String str1 = comboBox1.Text;//串口号 String str2 = comboBox2.Text;//波特率 String str3 = comboBox3.Text;//校验位 String str4 = comboBox5.Text;//停止位 String str5 = comboBox4.Text;//数据位 Int32 int2 = Convert.ToInt32(str2);//将字符串转为整型 Int32 int5 = Convert.ToInt32(str5);//将字符串转为整型 groupBox3.Enabled = true;//LED控制界面变可选 try { if (button1.Text == "打开串口") { if (str1 == null) { MessageBox.Show("请先选择串口!", "Error"); return; } sp.Close(); sp = new SerialPort(); sp.PortName = comboBox1.Text;//串口编号 sp.BaudRate = int2;//波特率 switch (str4)//停止位 { case "1": sp.StopBits = StopBits.One; break; case "1.5": sp.StopBits = StopBits.OnePointFive; break; case "2": sp.StopBits = StopBits.Two; break;

AVC上位机操作使用说明书

A VC上位机软件操作使用说明书 1使用的条件:当机组并网后,可将HGC、AVQC下位机投入,机组要停机时退出。投退有两种方式:下位机直接投退和上位机控制投退,其作用是一样的。下位机直接投退则直接按电气控制台上的红色投按钮或绿色退按钮;如通过DCS控通过在DCS上做配置来实现制,则可下位机的投退。上位机控制投退则先在主界面(图8)上选择需要投退的机组,然后按需要投退的“P”或“Q”按钮,当投成功后,相应按钮变红,退成功后,相应按钮变绿。 2用户登录 要进行系统设置必须进行用户登录。用户分三个等级:初级用户、中级用户和高级用户,分别设置不同的口令。其中初级用户只能进行运行设置;中级用户可进行运行设置和机组保护设置;高级用户可进行运行设置和机组保护设置和初始设置。 操作时先从“文件”菜单或工具按钮选择进入“用户登录”。“登录”对话框出现后,通过下拉框选择用户级别,然后添入口令,按“确定”即可。如口令不对则给出出错信息。按“取消”则取消登录操作。

当用户离开,并不希望无关人员进行系统设置时,可从菜单或工具按钮选择进入“用户登录权限退出”。此时出现“权限退出”对话框,按“确定”即可。按“取消”则取消“权限登录退出”操作。也可通过进入“文件”菜单的的“修改密码”来改变密码。 3系统设置 系统设置包含初始设置、运行设置和机组保护设置,初始设置包含了通信协议等内容的设置,由厂家在初次安装软件时完成,

初次安装软件首先需要进行“机组配置”,即按照顺序把安装了下位机的机组名称添加到下拉框内,然后按“设定”确认。如输入错了可选出出错机组后按“删除”。 与上一级调度机构通信可通过RTU,也可通过基于IP的网络。如果通过RTU通信,则需进行规约设置,本软件支持SC1801规约和CDT规约。这里需要输入通信规约和站址,还应输入上一级调度机构下发目标值的板点号和相应的满刻度值。 如果通过网络通信,则需要设置本地和主站的IP和端口号。 对于返送给主站的数据应通过“发送数据设置”来确定所要发送数据在数据流中的位置、类型、名称、与主站对应的满刻度值以及死区。每设定一组数据都需点击“设定”钮。

VC++编写简单串口上位机程序

VC++编写简单串口上位机程序?? 2010年4月13日10:23:40 ?串口通信,MCU跟PC通信经常用到的一种通信方式,做界面、写上位机程序的编程语言、编译环境等不少,VB、C#、LABVIEW等等,我会的语言很少,C语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相当蹩脚的C++写出了一个简单的串口上位机程序,分享 一下,体验一下单片机和PC通信的乐趣。 编译环境:VC++6.0?操作系统:VMWare虚拟出来的Windows XP?? 程序实现功能: 1、 PC初始化COM1口,使用n81方式,波特率57600与单片机通信。PC的COM口编号可 以通过如下方式修改: ?当然也可以通过上位机软件编写,通过按钮来选择COM端口号,但是此次仅仅是简单的例程,就没有弄那么复杂了。COM1口可用的话,会提示串口初始化完毕。否则会提示串口已经打开Port already open,表示串口已经打开,被占用了。? 2、点击开始转换,串口会向单片机发送0xaa,单片机串口中断接收到0xaa后启动ADC 转换一次,并把转换结果ADCL、ADCH共两个字节的结果发送至PC,PC进行数值转换后在窗口里显示。(见文章末尾图)???3、为防止串口被一只占用,点击关闭串口可以关闭CO M1,供其它程序使用,点击后按钮变为打开串口,点击可重新打开COM1。 程序的编写:

1、打开VC++6.0建立基于对话框的MFC应用程序Test,? ?

??

??2、在项目中插入MSComm控件:工程->增加到工程->Componentsand Controls->双击Registered ActiveX Controls->选择MicrosoftCommunications Control, version 6.0->Insert,按默认值添加,你会发现多了个电话图标,这是 增加后串口通信控件。?

基于C#的串口通信上位机和下位机源代码

基于单片机串口通信的上位机和下位机实践串口 Universal Serial Bus或者USB RS232 GPIB兼容的设备也带有RS-232 获取远程采集设备的数据。 bit byte 发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488 202 1200米。 首先亮出C#的源程序吧。

using System; using System.Collections.Generic; using https://www.sodocs.net/doc/9011972130.html,ponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO.Ports; using System.Timers; namespace 单片机功能控制 { public partial class Form1 : Form { public Form1() {

InitializeComponent(); } SerialPort sp = new SerialPort(); private void button1_Click(object sender, EventArgs e) { String str1 = comboBox1.Text;//串口号 String str2 = comboBox2.Text;//波特率 String str3 = comboBox3.Text;//校验位 String str4 = comboBox5.Text;//停止位 String str5 = comboBox4.Text;//数据位 Int32 int2 = Convert.ToInt32(str2);//将字符串转为整型Int32 int5 = Convert.ToInt32(str5);//将字符串转为整型groupBox3.Enabled = true;//LED控制界面变可选 try { if (button1.Text == "打开串口") { if (str1 == null)

上位机的使用说明书

? ? ) ? ? ? ? ? -? ? ?? - - ? ? ? -? ?( ? c'Ρ) 1" üü? ? ? )?pCǎ?? ? ? üü?W ? ? ?W üü ?P ??- ? ? ?P ???-

üüμ 3 - üü ? ? ?$ ? - - ? ?? J # J ?? ? # ? ?? ? ?? / ??? - ? ? - ? - ? ? - ˋ? ? ? ˋ?? ? ?"? ?? ? Ρ ? ) ? ? + ? 6 W W6 ?"? ? - Ρ ? ? 8 ?( -?ń ? ? "? ) 8 ??3 ?? ? Ρ t ?cJ? t "? -" ? ń ? ? ? 6 ???- ? ? ?- ?- ?<"? ? ? ? ? ? "? ) / ?

! ? "?'Ρ "? ? 6 8 6 ? ??( ? ? ) ? ? ? (?? 8 8 6 ? ??(? ) ? ???? 8 ? ǎ - ? ?? Ρ 6 ? ? "?'Ρ 8 ?. )'Ρˋ? ) #? - ? " W ? W"? ? W ? "?< & ? J?"? ?. 6 ???? ? < 8

? 'Ρ?- 3 # / ?P ? ?? - ?) ?P ?? ? ? - ) "? J??? ? ?? +? 8

I? ? "?)?) " ?? ??" " ? " & ? " ! ? " ' ? & ( %' ''( " ? ?( %' ' " ? ?( %' " ? ?( %' &' " ? ?( %' " ? ?( %' ??? " ? ?? < ??? ? ??? ??

说把手教你编写LabView上位机程序

手把手教你从零开始用labview编写智能车上位机程序(1) labview, 智能, 手把手, 程序, 编写 软件安装和基础知识准备 其几天把我的上位机软件发布在里这里,发现大家对这个还是很感兴趣的,因为上位机软件对于做摄像头的来说是必备的工具(也许有人说他不需要,那我很佩服他的判断能力和程序调试能力,他肯定是天才级别的人物,希望我能拜他为师,呵呵!)。不过这种东西还是自己编写的用起来顺手。想显示什么就显示什么。选择labview编写是因为labview容易上手,我从完全不会到编写到完成那个上位机软件也就用了一个星期而已。如果学VC,MFC的话,你估计对用上1个月也许还做不出什么。但是labview功能也很强大,可是我们用到的并不多,网上教程多,可是我们能用上的也并不多,学起来麻烦。我下面就专门针对这个labview的智能车上位 机软件的编写来讲解吧! 首先发布一个关于labview的广告,大家了解一下labview主要是干什么的。 LabVIEW是一种程序开发环境,由美国国家仪器(NI)公司研制开发的,类似于C和BASIC开发环境,但是LabVIEW与其他计算机语言的显著区别是:其他计算机语言都是采用基于文本的语言产生代码,而LabVIEW使用的是图形化编辑语言G编写程序,产生的 程序是框图的形式。 与C和BASIC一样,LabVIEW也是通用的编程系统,有一个完成任何编程任务的庞大函数库。LabVIEW的函数库包括数据采集、GPIB、串口控制、数据分析、数据显示及数据存储,等等。LabVIEW也有传统的程序调试工具,如设置断点、以动画方式显示数据及 其子程序(子VI)的结果、单步执行等等,便于程序的调试。 虚拟仪器(virtual instrumention)是基于计算机的仪器。计算机和仪器的密切结合是目前仪器发展的一个重要方向。粗略地说这种结合有两种方式,一种是将计算机装入仪器,其典型的例子就是所谓智能化的仪器。随着计算机功能的日益强大以及其体积的日趋缩小,这类仪器功能也越来越强大,目前已经出现含嵌入式系统的仪器。另一种方式是将仪器装入计算机。以通用的计算机硬件及操作系统为依托,实现各种仪器功能。虚拟仪器主要是指这种方式。下面的框图反映了常见的虚拟仪器方案。 虚拟仪器的主要特点有: 尽可能采用了通用的硬件,各种仪器的差异主要是软件。 可充分发挥计算机的能力,有强大的数据处理功能,可以创造出功能更强的仪器。 用户可以根据自己的需要定义和制造各种仪器。 虚拟仪器实际上是一个按照仪器需求组织的数据采集系统。虚拟仪器的研究中涉及的基础理论主要有计算机数据采集和数字信号处理。目前在这一领域内,使用较为广泛的计算机语言是美国NI公司的LabVIEW。 虚拟仪器的起源可以追溯到20世纪70年代,那时计算机测控系统在国防、航天等领域已经有了相当的发展。PC机出现以后,仪

上位机下位机串口通信

大连海事大学 课程设计报告 课程名称:计算机微机原理课程设计 成员: 成员1:2220133293 范凯锋 成员2:2220132642 唐绍波 成员3:2220130079 曹晓露 设计时间:2016年3月7日至3月18日

考核记录及成绩评定

目录 1.设计任务与要求 (1) 1.1课程设计题目 (1) 1.2课程设计的背景 (1) 1.3课程设计的目的 (1) 1.4课程设计的意义 (1) 1.5设计任务 (1) 2.设计方案 (2) 2.1参数采集和传输设计 (2) 2.2参数显示设计 (2) 2.3模拟信号采样设计 (2)

2.4硬件研制过程 (2) 3.详细设计 (3) 3.1硬件系统框图与说明 (3) 3.2硬件设计 (4) 3.3软件主要模块流程图与说明 (7) 4.设计结果及分析 (8) 5.成员分工及工作情况 (9) 5.1成员分 工 (9) 5.2工作情 况 (9) 5.3实验总结 (9) 6.参考文献 (9) 7. 附录 (10)

一、设计任务与要求 1.1课程设计题目 双机数据采集系统设计 1.2 课程设计的背景 二十一世纪是信息化高速发展的世纪,产业的信息化离不开微型计算机的支持。微型计算机的进步是推动全球信息化的动力。因此在二十一世纪掌握微型计算机接口技术是十分有必要的。本次课题是双机参数采集系统设计,这次课题旨在通过自己对所需功能芯片的设计与实现来巩固以前所学的微机原理课程知识,同时也提高动手实践的能力,还有为将来进行更大规模更复杂的开发积累经验。 随着软件规模的增长,以及随之而来的对软件开发进度和效率的要求,高级语言逐渐取代了汇编语言。但即便如此,高级语言也不可能完全替代汇编语言的作用。 1.3课程设计的目的 《微机原理与汇编语言》是一门实践性和实用性都很强的课程,本次课程设计是在课程学习结束后,为使学生进一步巩固课堂和书本上所学知识,加强综合能力,充分理解和运用所学到的知识,通过简单的应用系统的设计,提高系统设计水平,启发创新思想。通过本课程设计希望达到以下目地: ?培养资料搜集和汇总的能力; ?培养总体设计和方案论证的意识; ?提高硬件,软件设计与开发的综合能力; ?提高软件和硬件联合调试的能力; ?熟练掌握相关测量仪器的使用方法;

多功能表上位机软件操作说明(VC版2007规约)

VC版07规约国网多功能表上位机软件操作说明 把文件夹解压后,即可运行“07规约上位机-VC版”文件夹下的文件“gw2007test.exe” 进入软件主界面。抄表 1.点击左上角菜单栏“配置”项,选择正确串口、波特率、偶校验E、数据位8、停止位1、密码权限、密码,点击“确认退出”。在右上角“表地址”栏输入正确的表地址,一般为局编号的带数字部分。(AAAAAAAAAAAA为广播地址可以作为万能表号使用) 2.点击左上角菜单栏“抄读”项,进入抄读窗口界面,在左侧定制抄表方案(在需要抄读数据前打√),在展开的图中可以看到各个大类的内容,选择自己的需要部分打√,全部选择完毕后在方案中输入一个名称,点击“方案保存”,然后“方案读取”。 3.点击菜单栏“单抄”按钮,即可将方案内容数据全部读出。(如需保存可点击右上方“数据保存”即可)。 4.点击“抄读数据保存”后,抄表完毕软件会自动把数据保存在该软件目录下的.MDB 文件中。打开该数据库可以导出数据为EXCEL实现打印。 5.抄读“负荷曲线”:点击菜单栏“曲线”按钮,按需要选择不同方式读取数据,点击“曲线数据保存”即可完成保存,可以导出为EXCEL格式实现打印。 一、设表 参数设置 正确输入表的实际地址(地址不支持AAAAAAAAAAAA)。在菜单栏点击“设置” 按钮,根据规约要求正确设置需要更改的项,在“数据域”修改数据后,选取“设置” 表示该项目需要设置,在“方案名”中输入方案名称,点击“方案保存”后“方案读取”,点击菜单栏“单设”后,观察栏目后设置“结果”。设置成功的在该项目后面结果栏出现“OK”,否则不成功则出现“ERROR”。 命令类 点击菜单栏“命令类”可以进行以下操作 1.“读通信地址”可以读取表地址 2.“写通信地址”输入新的表地址,按“发送”即可对表地址进行更改 3“广播校时”每日一次,5分钟以内 4“冻结命令”根据需要进行冻结 5.“更改通信速度”选择好合适的波特率,点击“发送”即可 6.“修改密码”输入原始密码和权限、及需要修改的新密码和权限,点击“发送”即 可。 7.“写表计时间和系统同步”根据需要选择修改日期、时钟,点击按钮即可。(校时 时首先保证电脑日期、时钟正确) 控制类

上位机操作手册

推焦联锁、自动走行控制系统 系 统 手 册 岳阳千盟电子有限公司 二00五年六月

目录 一、用户登录--------------------------------------------------------------------第2页 二、推焦动画--------------------------------------------------------------------第3页 三、各车的数据显示-----------------------------------------------------------第4页 四、显示计划部分--------------------------------------------------------------第5页 五、显示记录部分--------------------------------------------------------------第6页 六、其他系统--------------------------------------------------------------------第9页 1、推焦统计---------------------------------------------------------------第9页 2、数据输出---------------------------------------------------------------第10页 3、数据存储---------------------------------------------------------------第10页 4、焦炉状态---------------------------------------------------------------第11页 七、系统设置---------------------------------------------------------------------第12页 1、设置串口-----------------------------------------------------------------第12页 2、设置炉号与推焦串法--------------------------------------------------第13页 3、设置周转时间与检修时间--------------------------------------------第14页 4、设置推熄车煤车--------------------------------------------------------第15页 5、设置班组-----------------------------------------------------------------第17页 6、用户管理-----------------------------------------------------------------第18页

vc++上位机程序

VC++编写简单串口上位机程序 2010年4月13日10:23:40 串口通信,MCU跟PC通信经常用到的一种通信方式,做界面、写上位机程序的编程语言、编译环境等不少,VB、C#、LABVIEW等等,我会的语言很少,C 语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相当蹩脚的C++写出了一个简单的串口上位机程序,分享一下,体验一下单片机和PC通信的乐趣。 编译环境:VC++6.0 操作系统:VMWare虚拟出来的Windows XP 程序实现功能: 1、PC初始化COM1口,使用n81方式,波特率57600与单片机通信。PC的COM口编号可以通过如下方式修改: 当然也可以通过上位机软件编写,通过按钮来选择COM端口号,但是此次仅仅是简单的例程,就没有弄那么复杂了。COM1口可用的话,会提示串口初始化完毕。否则会提示串口已经打开Port already open,表示串口已经打开,被占用了。 2、点击开始转换,串口会向单片机发送0xaa,单片机串口中断接收到0xaa后启动ADC转换一次,并把转换结果ADCL、ADCH共两个字节的结果发送至PC,PC进行数值转换后在窗口里显示。(见文章末尾图) 3、为防止串口被一只占用,点击关闭串口可以关闭COM1,供其它程序使用,

点击后按钮变为打开串口,点击可重新打开COM1。 程序的编写: 1、打开VC++6.0建立基于对话框的MFC应用程序Test,

2、在项目中插入MSComm控件:工程->增加到工程->Components and Controls->双击Registered ActiveX Controls->选择Microsoft Communications Control, version 6.0->Insert,按默认值添加,你会发现多了个电话图标,这是增加后串口通信控件。

上位机与下位机之间通信编程

摘要 本文主要描述了利用PC机与A T89C51单片机之间的通信程序设计实现温度显示。并详述了在VC6.0环境下,上位机利用MSCOMM通信控件与单片机之间串口通信实现温度显示。由单片机采集一个温度信号,将采集到的温度信号传送给PC机显示,PC机用VC6.0编写程序,单片机程序用C语言编写,最后用PROTUES软件进行仿真实现温度显示。 关键词:单片机MSCOMM控件VC6.0 AT89C51 温度显示

目录 摘要 1 引言 (1) 2 结构设计与方案选择 (2) 2.1设计任务 (2) 2.1.1单片机的选择 (2) 2.1.2电平转换 (2) 2.1.1单片机的选择 (2) 2.1.3单片机与pc机通信原理 (2) 2.2软件方案选择 (2) 2.2.1 上位机编程方案选择 (3) 2.2.2 单片机编程方案选择 (3) 2.3 总体方案选择 (2) 3 硬件设计 (8) 3.1单片机主要特性 (5) 3.2 MAX232电平芯片介绍10 (10) 3.3 硬件电路设计图 (11) 3.3.1 PC机与单片机通信接口电路设计框图 (11) 3.3.2整体设计原理图 (11) 4软件设计 (12) 4.1上位机程序设计 (12) 4.2下位机程序设计 (13) 5 软硬件调试部分 (21) 5.1 PROTEUS软件仿真 (21) 5.1.1 Protues简介 (21) 5.1.2 Protues仿真电路图 (22) 5.2 VC软件仿真 (21) 结束语 (27) 致谢 (28) 参考文献 (29)

1引言 随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从单片机技术入手,一切向着数字化控制,智能化控制方向发展。 现代化集中管理需要对现场数据进行统计、分析、制表、打印、绘图、报警等,同时,又要求对现场装置进行实时控制,完成各种规定操作,达到集中管理的目的。加之单片机的计算能力有限,难以进行复杂的数据处理。因此在功能比较复杂的控制系统中,通常以PC机为上位机,单片机为下位机,由单片机完成数据的采集及对装置的控制,而由上位机完成各种复杂的数据处理及对单片机的控制。

上位机使用说明书

上位机使用说明书 上位机即为整流柜监测系统,其通过与各个整流柜的均流仪通讯,召唤柜数据(柜平均电流、柜电流系数)、臂数据(臂平均电流、臂电流系数)、管电流(管平均电流、管最大电流、管最下电流)、越限报警等实时数据,并以友好的图形界面显示给用户;上位机可以自由设定历史数据存储周期,并以报表、曲线等形式显示历史数据;同时上位机提供了查询、打印功能,其还可以对比各整流柜的管电流波形。 上位机的主画面如下图所示: 主画面显示了各个整流柜的柜平均电流、柜电流系数。若想查看某柜的臂数据,只要在相应的柜号上单击鼠标左键,则显示此柜的各个臂数据,如下图所示: 臂数据画面显示了各个臂的臂平均电流、臂电流系数。若想查看某臂的管数据,只要在相应的臂号上单击鼠标左键,则显示此臂的各个管数据,如下图所示:

在臂数据、管数据画面的右侧都显示了当前柜的柜平均电流和柜电流系数,在屏幕右上角显示的是返回上级按扭,点击鼠标左键可以返回上一层画面。 在主画面、臂数据画面、管数据画面中最上面一排菜单从左至右分别显示的是系统、参数、实时数据、历史数据、录波曲线。 当点击参数时会弹出一个下拉菜单,包括系统参数和设备参数两项。点击系统参数会显 示如下图所示的画面: 当点击设备参数时会显示如下图所示的画面:

在设备参数画面中可以对各个柜的总增益、管数量、零点陷阱、管电流量程、采样点、传送频率、采样周期、柜电流最大值、柜电流最小值、管电流最大值、管电流最小值等进行修改,同时还可以查看当前柜的各个臂中的各个管的管零点以及管增益。 当点击实时数据菜单时会显示如下图所示的画面: 实时数据画面中显示的是当前柜的各个臂中的各个管的管平均电流以及各个臂的臂平均电流值。 当点击历史数据时会弹出一个下拉菜单,包括历史曲线和历史数据两项。点击历史曲线 会显示如下图所示的画面:

上位机和下位机控制功能对比

【修改】上位机和下位机控制功能对比 本文上位机控制和下位机控制组态软件进行了简单的对比,通过一些典型示例说明了分别适合上位机和下位机控制的场合。 当前组态软件在工业控制中得到了日益广泛的应用。组态软件依据自身的过程数据库,下连各种硬件设备,并通过动态人机界面可以将采集处理的数据展现给用户,或者传递给其他应用程序。其结构如图所示: 图1 组态软件结构图 组态软件的出现,由于其预先提供了各种常用组件和相关设备驱动,一方面将监控系统设计的难度大为降低,开发相关系统的时间也大为缩短,另一方面,由于可以自由连接多种设备,提供了一个平台,用户可以依据需要设计出成本最优的工程。 对于硬件设备,特别是可编程的PLC等硬件,自身具有一定的控制功能,而可以连接PLC等硬件的组态软件也可以通过脚本等执行一定的控制功能,那么控制是交给上位机的组态软件,还是下位机的PLC呢?这里先对两者做一个简单的比较: 下位机控制 下位机可以执行一些相关的控制动作,优点在于其速度快,可靠性高,稳定。其缺点在于受到其自身的限制,对于一些特殊的复杂控制,以及和其他特殊设备相关或者

涉及到关系数据库等控制功能作无法执行。 上位机控制 上位机的组态软件同样可以执行一定的控制动作,其优点在于脚本编写更容易,而且可以方便可执行涉及到多个设备以及关系数据库或者其他数据的控制动作,能充分发挥自身系统的优势。缺点在于有时会遇到上位机和下位机通讯的时间瓶颈,而且通常组态软件运行工控机在其他操作系统上,其稳定性和PLC等有差距。 在实际工程中,应该根据需要来进行相关的控制分布。下面通过一些典型示例进行说明: 适合下位机控制场合 对于一些实时性要求较高,或者上位机和下位机通讯较慢或容易受到干扰的情况下,建议把关键的控制放在下位机执行。比如对于一些典型的水利项目,比如水质监测,其运行监测系统的子站和运行组态软件的中心站可能相距较远,其通讯可能采用数传电台,拨号,GSM,GPRS等方式。在这种情况下,由于其通讯距离远,可能会有些延迟,所以控制功能更多的放在了下位机,而上位机主要负责数据的采集,存储和显示,也可包含一些对下位机的设置功能。 适合上位机控制的场合 对于一些和关系数据库或者多种设备相关的控制功能,单纯的依靠下位机进行控制,可能非常麻烦或者难以实现,这种情况下建议由上位机进行控制。比如车站的灯光控制,需要获取火车的行车信号以及其他数据来进行判断是否亮灯,而行车信号一般存在数据库或者需要从引导系统中获取,这种情况下,如果其控制几乎全部由上位机实现。 在更多的时候,是根据控制功能自身的特点来进行相关设置。下位机和上位机可以根据需要各执行相关部分控制功能,实时性要求较高的控制可以放到下位机,复杂的,关联其他数据的控制可以放在上位机,两者在一起构成一个完备的控制系统。合理的进行分配,不仅可以减少劳动量,而且可以提高工程的健壮性。

上位机程序

经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。 程序如下: //这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收//和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的 #include< reg51.h> #include< stdio.h> #include< string.h> #define INBUF_LEN 4 //数据长度 unsigned char inbuf1[INBUF_LEN]; unsigned char checksum,count3 , flag,temp,ch; bit read_flag=0; sbit cp=P1^1; sbit DIR=P1^2; int i; unsigned int xdata *RAMDATA; /*定义RAM地址指针*/ unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ; void init_serialcomm(void) { SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收 PCON=0x00; ES=1; TMOD=0x21; //定时器工作于方式2,自动装载方式 TH0=(65536-1000)%256; TL0=(65536-1000)/256; TL1=0xfd; TH1=0xfd; ET0=1; TR0=1; TR1=1;

EA=1; // TI=1; RAMDATA=0x1F45; } void serial () interrupt 4 using 3 { if(RI) { RI=0; ch=SBUF; TI=1; //置SBUF空 switch(ch) { case 0x01 :printf("A"); TI=0;break; case 0x02 :printf("B"); TI=0;break; case 0x03 :printf("C"); TI=0;break; case 0x04 :printf("D"); TI=0;break; default :printf("fg"); TI=0;break; } } } //向串口发送一个字符 void timer0() interrupt 1 using 3{ // char i; flag++; TH0=0x00; TL0=0x00; if(flag==10) {// cp=!cp; // for(i=0;i<6;i++)

执法记录仪上位机后台管理软件使用手册资料

警用执法记录仪后台管理软件用户操作手册

1.0软件登录操作 双击程序“management.exe”进入登录界面,登录界面如图1-1所示,在连接设备时,将执法记录仪处于开机状态,然后使用随机配送的数据线连接到计算机上,接着输入密码(初始密码:12345678),点击【连接设备】按钮即可,连接成功后,【连接设备】按钮自动变成【断开设备】按钮如下图1-2。软件自动识别设备上设置设备ID和警员ID及通信模式(图1-2)。 图1-1 图1-2

图1-3 软件主界面 1.1. 设备操作 1、状态 当前显示设备ID、警员ID和运行模式。(图1-4)。 图1-4 2、密码 2.1 设备登陆密码修改 设备登入密码修改(默认是:12345678)如下图1-5-1,输入新密码 ,确认新密码,点击【OK】,那么设备登入密码修改成功。

图1-5-1 2.2 硬件解密密码修改 硬件解密密码是执法仪设备SD卡密码(默认是:123456),如下图1-5-2,输入新 密码,确认新密码,点击【OK】,那么硬件解密密码修改成功。 图1-5-2 3、设备ID 如下图1-6,修改为客户自己所需要的设备ID,按【确认】修改成功。 图1-6 4、警员ID 显示【当前警员ID】如下图1-7,【修改警员ID】为客户自己所需要的警员ID号如下图,按【OK】确认修改成功。

图1-7 5、时间 点击【同步到设备】按钮,成功显示同步时间(图1-8)。 图1-8 时间同步 6、分辨率设置 点击下拉框选择客户自己所需要的分辨率(此处可选720p和1080p),然后按【OK】确认修改成功,在设备重启后生效。 图1-9 7、复位 如下图所示输入管理员密码:联系生产商,然后按【确认】确认设备将恢复

51单片机与上位机串口通信程序设计

51单片机与上位机串口通信程序设计 1. 发送:向总线上发命令 2. 接收:从总线接收命令,并分析是地址还是数据。 3. 定时发送:从内存中取数并向主机发送. 经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。程序如下: //这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收 //和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的 #include< reg51.h> #include< stdio.h> #include< string.h> #define INBUF_LEN 4 //数据长度 unsigned char inbuf1[INBUF_LEN]; unsigned char checksum,count3 , flag,temp,ch; bit read_flag=0; sbit cp=P1^1; sbit DIR=P1^2; int i; unsigned int xdata *RAMDATA; /*定义RAM地址指针*/ unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ; void init_serialcomm(void) { SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收 PCON=0x00; ES=1;

TMOD=0x21; //定时器工作于方式2,自动装载方式TH0=(65536-1000)%256; TL0=(65536-1000)/256; TL1=0xfd; TH1=0xfd; ET0=1; TR0=1; TR1=1; // TI=0; EA=1; // TI=1; RAMDATA=0x1F45; } void serial () interrupt 4 using 3 { if(RI) { RI=0; ch=SBUF; TI=1; //置SBUF空 switch(ch) { case 0x01 :printf("A"); TI=0;break; case 0x02 :printf("B"); TI=0;break; case 0x03 :printf("C"); TI=0;break; case 0x04 :printf("D"); TI=0;break; default :printf("fg"); TI=0;break; } }

上位机操作说明

神宁炭基活性炭厂集中控制系统 操作手册 平顶山中选自控系统有限公司

神宁炭基活性炭厂集中控制系统操作手册 一、集控系统的起动与退出 起动:计算机开机后,点击桌面上的“神宁炭基活性炭集中控制系统”图标(下图)来启动集中控制系统。 集控系统起动后的画面如下图示,上部是标题栏,中间是主画面显示区,下部是页面导航栏,点击导航栏按钮可以切换显示不同的画面: 退出: 点击集控系统画面右下角的退出图标即可退出集控系统。

二、设备的起停操作 参与集控的设备有两种工作方式:集中、就地,这两种工作方式由现场控制箱上的“集中/就地”选择旋扭来选择。 集中工作方式: 在“集中”工作方式下,设备的起停由PLC控制,在人机界面上,相应处于“集控”状态的设备,其设备号显示为黄色(ZF201),可通过在人机界面上点击设备号来控制设备的起停,此时,现场起车按钮无法控制起车,但停车按钮可以停车;具体操作方法:用鼠标点击需要起停设备的设备号,系统会弹出设备起停控制对话框: 1、对于普通单向动作的设备,其对话框如下: 根据设备的当前状态,系统会让操作员确认是否要对设备进行起停操作,操作员确认后,系统将对设备发出相应的起停控制指令。

2、对于正反转设备,其对话框如下: 操作员通过点击相应的“正转”、“反转”、“停车”按钮来控制设备的“正转”、“反转”和“停车”。 “联锁”和“解锁” 当设备处于“集中”工作方式时,有“联锁”和“解锁”两种工作状态,当设备处于“联锁”状态时,它的起停与其它设备之间存在联锁关系,其起停受其它设备当前开停状态影响,在人机界面上以图标:来标识;当设备处于“解锁”状态时,它的起停不受其它设备状态的影响,可以自由起停,在人机界面上以图标:来标识。设备的“联锁/解锁”状态可通过点击设备号旁边的“联锁/解锁”图标(/)进行切换。 就地工作方式 在“就地”工作方式下,设备的起停由硬接线控制,在人机界面上,相应的设备号显示为灰色(ZF201),只能通过现场控制按钮来控制设备的起停。

相关主题