使用标准USB/5VC电动汽车充电接口标准,是什么意思?

用VC++编写USB接口通讯程序_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
用VC++编写USB接口通讯程序
阅读已结束,下载本文需要
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩2页未读,
定制HR最喜欢的简历
你可能喜欢驱动开发向来是内核开发中工作量最多的一块,随着USB设备的普及,大量的USB设备的驱动开发也成为驱动开发者手头上做的最多的事情。本文主要介绍 Linux平台下基于libusb的驱动开发,希望能够给从事Linux驱动开发的朋友带来些帮助,更希望能够给其他平台上的无驱设计带来些帮助。文章是我在工作中使用libusb的一些总结,难免有错误,如有不当的地方,还请指正。
&&& Linux 平台上的usb驱动开发,主要有内核驱动的开发和基于libusb的无驱设计。
对于内核驱动的大部分设备,诸如带usb接口的hid设备,linux本身已经自带了相关的驱动,我们只要操作设备文件便可以完成对设备大部分的操作,而另外一些设备,诸如自己设计的硬件产品,这些驱动就需要我们驱动工程师开发出相关的驱动了。内核驱动有它的优点,然而内核驱动在某些情况下会遇到如下的一些问题:
1 当使用我们产品的客户有2.4内核的平台,同时也有2.6内核的平台,我们要设计的驱动是要兼容两个平台的,就连makefile 我们都要写两个。
2 当我们要把linux移植到嵌入平台上,你会发现原先linux自带的驱动移过去还挺大的,我的内核当然是越小越好拉,这样有必要么。这还不是最郁闷的地方,如果嵌入平台是客户的,客户要购买你的产品,你突然发现客户设备里的系统和你的环境不一样,它没有你要的驱动了,你的程序运行不了,你会先想:&没关系,我写个内核驱动加载一下不就行了&。却发现客户连insmod加载模块的工具都没移植,那时你就看看老天,说声我怎么那么倒霉啊,客户可不想你动他花了n时间移植的内核哦
3 花了些功夫写了个新产品的驱动,挺有成就感啊,代码质量也是相当的有水准啊。正当你沉醉在你的代码中时,客服不断的邮件来了,&客户需要2.6.5内核的驱动,config文件我已经发你了& &客户需要双核的 2.6.18-smp 的驱动& &客户的平台是自己定制的是2.6.12-xxx &&& 你恨不得把驱动的源代码给客户,这样省得编译了。你的一部分工作时间编译内核,定制驱动
有问题产生必然会有想办法解决问题的人, libusb的出现给我们带来了某些方便,即节约了我们的时间,也降低了公司的成本。 所以在一些情况下,就可以考虑使用libusb的无驱设计了。
&&& 下面我们就来详细讨论一下libusb, 并以写一个hid设备的驱动来讲解如何运用libusb,至于文章中涉及的usb协议的知识,限于篇幅,就不详细讲解了,相关的可自行查看usb相关协议。
一 libusb 介绍
&& libusb 设计了一系列的外部API 为应用程序所调用,通过这些API应用程序可以操作硬件,从libusb的源代码可以看出,这些API 调用了内核的底层接口,和kernel driver中所用到的函数所实现的功能差不多,只是libusb更加接近USB 规范。使得libusb的使用也比开发内核驱动相对容易的多。
Libusb 的编译安装请查看Readme,这里不做详解
二 libusb 的外部接口
2.1 初始化设备接口
这些接口也可以称为核心函数,它们主要用来初始化并寻找相关设备。
函数定义: void usb_init(void);
从函数名称可以看出这个函数是用来初始化相关数据的,这个函数大家只要记住必须调用就行了,而且是一开始就要调用的.
usb_find_busses
函数定义: int usb_find_busses(void);
寻找系统上的usb总线,任何usb设备都通过usb总线和计算机总线通信。进而和其他设备通信。此函数返回总线数。
usb_find_devices
函数定义: int usb_find_devices(void);
寻找总线上的usb设备,这个函数必要在调用usb_find_busses()后使用。以上的三个函数都是一开始就要用到的,此函数返回设备数量。
usb_get_busses
函数定义: struct usb_bus *usb_get_busses(void);
这个函数返回总线的列表,在高一些的版本中已经用不到了,这在下面的实例中会有讲解
2.2 操作设备接口
&&& usb_open
函数定义: usb_dev_handle *usb_open(struct *usb_device dev);
打开要使用的设备,在对硬件进行操作前必须要调用usb_open 来打开设备,这里大家看到有两个结构体 usb_dev_handle 和 usb_device 是我们在开发中经常碰到的,有必要把它们的结构看一看。在libusb 中的usb.h和usbi.h中有定义。
这里我们不妨理解为返回的 usb_dev_handle 指针是指向设备的句柄,而行参里输入就是需要打开的设备。
&& usb_close
&& 函数定义: int usb_close(usb_dev_handle *dev);
&& 与usb_open相对应,关闭设备,是必须调用的, 返回0成功,&0 失败。
&& usb_set_configuration
&& 函数定义: int usb_set_configuration(usb_dev_handle *dev, int configuration);
&& 设置当前设备使用的configuration,参数configuration 是你要使用的configurtation descriptoes中的bConfigurationValue, 返回0成功,&0失败( 一个设备可能包含多个configuration,比如同时支持高速和低速的设备就有对应的两个configuration,详细可查看usb标准)
&& usb_set_altinterface
&& 函数定义: int usb_set_altinterface(usb_dev_handle *dev, int alternate);
&& 和名字的意思一样,此函数设置当前设备配置的interface descriptor,参数alternate是指interface descriptor中的bAlternateSetting。返回0成功,&0失败
&& usb_resetep
&& 函数定义: int usb_resetep(usb_dev_handle *dev, unsigned int ep);
&& 复位指定的endpoint,参数ep 是指bEndpointAddress,。这个函数不经常用,被下面介绍的usb_clear_halt函数所替代。
&& usb_clear_halt
&& 函数定义: int usb_clear_halt (usb_dev_handle *dev, unsigned int ep);
&& 复位指定的endpoint,参数ep 是指bEndpointAddress。这个函数用来替代usb_resetep
&& usb_reset
&& 函数定义: int usb_reset(usb_dev_handle *dev);
&& 这个函数现在基本不怎么用,不过这里我也讲一下,和名字所起的意思一样,这个函数reset设备,因为重启设备后还是要重新打开设备,所以用usb_close就已经可以满足要求了。
&& usb_claim_interface
&& 函数定义: int usb_claim_interface(usb_dev_handle *dev, int interface);
&& 注册与操作系统通信的接口,这个函数必须被调用,因为只有注册接口,才能做相应的操作。
Interface 指 bInterfaceNumber. (下面介绍的usb_release_interface 与之相对应,也是必须调用的函数)
&& usb_release_interface
&& 函数定义: int usb_release_interface(usb_dev_handle *dev, int interface);
&& 注销被usb_claim_interface函数调用后的接口,释放资源,和usb_claim_interface对应使用。
&& 2.3 控制传输接口
&& usb_control_msg
&& 函数定义:int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
&& 从默认的管道发送和接受控制数据
&& usb_get_string
&& 函数定义: int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, size_t buflen);
&& usb_get_string_simple
函数定义: int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen);
&& usb_get_descriptor
&& 函数定义: int usb_get_descriptor(usb_dev_handle *dev, unsigned char type, unsigned char index, void *buf, int size);
&& usb_get_descriptor_by_endpoint
&& 函数定义: int usb_get_descriptor_by_endpoint(usb_dev_handle *dev, int ep, unsigned char type, unsigned char index, void *buf, int size);
&& 2.4 批传输接口
&& usb_bulk_write
&& 函数定义: int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
&&& usb_interrupt_read
函数定义: int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
2.5 中断传输接口
usb_bulk_write
函数定义: int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
usb_interrupt_read
函数定义: int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
基本上libusb所经常用到的函数就有这些了,和usb协议确实很接近吧。下面我们实例在介绍一个应用。
//----------------===================================
Libusb库的使用
使用libusb之前你的linux系统必须装有usb文件系统,这里还介绍了使用hiddev设备文件来访问设备,目的在于不仅可以比较出usb的易用性,还提供了一个转化成libusb驱动的案例。
3.1 find设备
任何驱动第一步首先是寻找到要操作的设备,我们先来看看HID驱动是怎样寻找到设备的。我们假设寻找设备的函数Device_Find(注:代码只是为了方便解说,不保证代码的健全)
/* 我们简单看一下使用hid驱动寻找设备的实现,然后在看一下libusb是如何寻找设备的 */
int Device_Find()
&&& char dir_str[100];&& /* 这个变量我们用来保存设备文件的目录路径 */
&&& char hiddev[100];&&& /* 这个变量用来保存设备文件的全路径 */
DIR&&&&&&&&&&& &&&
/* 申请的字符串数组清空,这个编程习惯要养成 */
memset (dir_str, 0 , sizeof(dir_str));
memset (hiddev, 0 , sizeof(hiddev));
&&& /* hiddev 的设备描述符不在/dev/usb/hid下面,就在/dev/usb 下面
这里我们使用opendir函数来检验目录的有效性
打开目录返回的值保存在变量dir里,dir前面有声明
dir=opendir("/dev/usb/hid");
&&& if(dir){
&&&&&&& /* 程序运行到这里,说明存在 /dev/usb/hid 路径的目录 */
&&& &&& sprintf(dir_str,"/dev/usb/hid/");
&&& &&& closedir(dir);
&&& }else{
&&&&&&& /* 如果不存在hid目录,那么设备文件就在/dev/usb下 */
&&& &&& sprintf(dir_str,"/dev/usb/");
&&& /* DEVICE_MINOR 是指设备数,HID一般是16个 */
for(i = 0; i & DEVICE_MINOR; i++) {
&&& /* 获得全路径的设备文件名,一般hid设备文件名是hiddev0 到 hiddev16 */
&&& &&& sprintf(hiddev, "%shiddev%d", dir_str,i);
&&&&&& /* 打开设备文件,获得文件句柄 */
&&&&&& fd = open(hiddev, O_RDWR);
&&&&&& if(fd & 0) {
&&&&&& &&& /* 操作设备获得设备信息 */
&&&&&& && ioctl(fd, HIDIOCGDEVINFO, &info);
&&&&&&&&&&&&& /* VENDOR_ID 和 PRODUCT_ID 是标识usb设备厂家和产品ID,驱动都需要这两个参数来寻找设备,到此我们寻找到了设备 */
&&&&&& &&& if(info.vendor== VENDOR_ID && info.product== PRODUCT_ID) {
&&&&&&&&&& &&&& /* 这里添加设备的初始化代码 */
&&&&&&&&&&&&&&&&&&
&&&&&&&&&& &&& device_num++;&& /* 找到的设备数 */
&&&&&&&&&& }
&&&&&& &&& close(fd);
&&& return device_&&&&&&&& /* 返回寻找的设备数量 */
我们再来看libusb是如何来寻找和初始化设备
int Device_Find()
struct usb_bus &&&&&&&&&&& *
&&& int&&&&&&&&&&&&&&&& &&&&&&&&& device_num = 0;
&&& device_num = 0;&&&&&& /* 记录设备数量 */
&&& usb_init();&&&&&&&&&&& /* 初始化 */
&&& usb_find_busses();&& /* 寻找系统上的usb总线 */
&&& usb_find_devices(); /* 寻找usb总线上的usb设备 */
&&& /* 获得系统总线链表的句柄 */
busses = usb_get_busses();
&&& struct usb_bus&&& && *
&&& /* 遍历总线 */
&&& for (bus = bus = bus-&next) {
&&& &&& struct usb_device *
&&&&&&& /* 遍历总线上的设备 */
&&& &&& for (dev = bus-& dev = dev-&next) {
&&&&&& &&& /* 寻找到相关设备, */
if(dev-&descriptor.idVendor==VENDOR_ID&& dev-&descriptor.idProduct == PRODUCT_ID) {
&&& &&&&&&&&&&& /* 这里添加设备的初始化代码 */
&&&&&&&&&&&&&&&&&&
&&&&&&&&&& &&& device_num++;&& /* 找到的设备数 */
}&&&&&&&&&&&&&&
&&& &&& }&&&&&&&
&&& return device_&&&&&&& /* 返回设备数量 */
注:在新版本的libusb中,usb_get_busses就可以不用了 ,这个函数是返回系统上的usb总线链表句柄
这里我们直接用usb_busses变量,这个变量在usb.h中被定义为外部变量
所以可以直接写成这样:
struct usb_bus && *
&&& &&& for (bus = usb_ bus = bus-&next) {
&&&&&& &&&&&&& struct usb_device *
&&& &&& for (dev = bus-& dev = dev-&next) {
&&& &&&&&& /* 这里添加设备的初始化代码 */
3.2&打开设备
假设我们定义的打开设备的函数名是device_open,
/* 使用hid驱动打开设备 */
int Device_Open()
&&& /* 传统HID驱动调用,通过open打开设备文件就可 */
handle = open(&hiddev0&, O_RDONLY);
/* 使用libusb打开驱动 */
int Device_Open()
/* LIBUSB 驱动打开设备,这里写的是伪代码,不保证代码有用 */
struct usb_device*&&&
usb_dev_handle*&&& &&& device_
/* 当找到设备后,通过usb_open打开设备,这里的函数就相当open 函数 */
device_handle = usb_open(udev);
3.3&读写设备和操作设备
假设我们的设备使用控制传输方式,至于批处理传输和中断传输限于篇幅这里不介绍
我们这里定义三个函数,Device_Write, Device_Read, Device_Report
Device_Report 功能发送接收函数
Device_Write 功能写数据
Device_Read&& 功能读数据
Device_Write和Device_Read调用Device_Report发送写的信息和读的信息,开发者根据发送的命令协议来设计,我们这里只简单实现发送数据的函数。
假设我们要给设备发送72字节的数据,头8个字节是报告头,是我们定义的和设备相关的规则,后64位是数据。
HID驱动的实现(这里只是用代码来有助理解,代码是伪代码)
int Device_Report(int fd, unsigned char *buffer72)
int &&&&& /* 保存ioctl函数的返回值 */
&&& unsigned char send_data[72]; /* 发送的数据 */
unsigned char recv_data[72]; /* 接收的数据 */
&&& struct hiddev_usage_ /* hid驱动定义的数据包 */
&&& struct hiddev_report_ /* hid驱动定义的
&&& memset(send_data, 0, sizeof(send_data));
memset(recv_data, 0, sizeof(recv_data));
&&& memcpy(send_data, buffer72, 72);
&& /* 这在发送数据之前必须调用的,初始化设备 */
&&& ret = ioctl(fd, HIDIOCINITREPORT, 0);
&&& if( ret !=0) {
&&& &&& return NOT_OPENED_DEVICE;/* NOT_OPENED_DEVICE 属于自己定义宏 */
&&& /* HID设备每次传输一个字节的数据包 */
&&& for(index = 0; index & 72; index++) {
&&&&&&& /* 设置发送数据的状态 */
&&& uref.report_type = HID_REPORT_TYPE_FEATURE;
&&& uref.report_id = HID_REPORT_ID_FIRST;
&&& uref.usage_index =
&&& uref.field_index = 0;
&&& uref.value = send_data[index];
&&& ioctl(fd, HIDIOCGUCODE, &uref);
&&& ret=ioctl(fd, HIDIOCSUSAGE, &uref);
&&& if(ret != 0 ){
&&&&&& &&& return UNKNOWN_ERROR;
/* 发送数据 */
rinfo.report_type = HID_REPORT_TYPE_FEATURE;
rinfo.report_id = HID_REPORT_ID_FIRST;
rinfo.num_fields = 1;
ret=ioctl(fd, HIDIOCSREPORT, &rinfo);&& /* 发送数据 */
if(ret != 0) {
&&& &&& return WRITE_REPORT;
/* 接受数据 */
ret = ioctl(fd, HIDIOCINITREPORT, 0);
for(index = 0; index & 72; index++) {
&&& uref.report_type = HID_REPORT_TYPE_FEATURE;
&&& uref.report_id = HID_REPORT_ID_FIRST;
&&& uref.usage_index =
&&& uref.field_index = 0;
&&& ioctl(fd, HIDIOCGUCODE, &uref);
&&& ret = ioctl(fd, HIDIOCGUSAGE, &uref);
&&& if(ret != 0 ) {
&&& &&& return UNKNOWN_ERROR;
&&& recv_data[index] = uref.
memcpy(buffer72, recv_data, 72);
return SUCCESS;
libusb驱动的实现
int Device_Report(int fd, unsigned char *buffer72)
&&& /* 定义设备句柄 */
&&& usb_dev_handle* Device_
&&& /* save the data of send and receive */
&&& unsigned char&& send_data[72];
&&& unsigned char&& recv_data[72];
&&& int &&&&&& &&&&& send_
&&& int &&&&&&&&&&& recv_
&&& /* 数据置空 */
&&& memset(send_data, 0 , sizeof(send_data));
&&& memset(recv_data, 0 , sizeof(recv_data));
&&& /* 这里的g_list是全局的数据变量,里面可以存储相关设备的所需信息,当然我们 也可以从函数形参中传输进来,设备的信息在打开设备时初始化,我们将在后面的总结中详细描述一下 */
&&& Device_handle = (usb_dev_handle*)(g_list[fd].device_handle);
&&& if (Device_handle == NULL) {
&&&&&&& return NOT_OPENED_DEVICE;
/* 这个函数前面已经说过,在操作设备前是必须调用的, 0是指用默认的设备 */
usb_claim_interface(Device_handle, 0);
/* 发送数据,所用到的宏定义在usb.h可以找到,我列出来大家看一下
&& &&&& #define USB_ENDPOINT_OUT&& &&& 0x00
&&&&&& #define USB_TYPE_CLASS &&& (0x01 && 5)
&&&&&& #define USB_RECIP_INTERFACE 0x01
&&&&&& #define HID_REPORT_SET&&&&&& 0x09 */
send_len = usb_control_msg(Device_handle,
USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& HID_REPORT_SET,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0x300,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& send_data, 72, USB_TIMEOUT);
/* 发送数据有错误 */
if (send_len & 0) {
&&&&&&& return WRITE_REPORT;
if (send_len != 72) {
&&& &&& return send_
/* 接受数据
&&&&&& #define USB_ENDPOINT_IN&&&&&&&& 0x80
&&&&&& #define USB_TYPE_CLASS&&&&&&&&& (0x01 && 5)
&&&&&& #define USB_RECIP_INTERFACE&&& &&& 0x01
&&&&&& #define HID_REPORT_GET&&&&&&&&& 0x01
recv_len = usb_control_msg(Device_handle,
USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& HID_REPORT_GET,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0x300,
&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&& 0,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& recv_data, 72, USB_TIMEOUT);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& if (recv_len & 0) {
&&&&&&& printf("failed to retrieve report from USB device!\n");
&&&&&&& return READ_REPORT;
&&& if (recv_len != 72) {
&&& &&& return recv_
&&& /* 和usb_claim_interface对应 */
&&& usb_release_interface(RY2_handle, 0);
&&& memcpy(buffer72, recv_data, 72);
return SUCCESS;
3.4&关闭设备
假设我们定义的关闭设备的函数名是Device_Close()
/* 使用hid驱动关闭设备 */
int Device_Close()
handle = open(&hiddev0&, O_RDONLY);
/* 传统HID驱动调用,通过close()设备文件就可 */
close( handle );
/* 使用libusb关闭驱动 */
int Device_Close()
/* LIBUSB 驱动打开设备,这里写的是伪代码,不保证代码有用 */
struct usb_device*&&&
usb_dev_handle*&&& &&& device_
device_handle = usb_open(udev);
/* libusb库使用usb_close关闭程序 */
usb_close(device_handle);
libusb的驱动框架
前面我们看了些主要的libusb函数的使用,这里我们把前面的内容归纳下:
一般的驱动应该都包含如下接口:
Device_Find(); /* 寻找设备接口 */
Device_Open(); /* 打开设备接口 */
Device_Write(); /* 写设备接口 */
Device_Read(); /* 读设备接口 */
Device_Close(); /* 关闭设备接口 */
具体代码如下:
#include &usb.h&
/* usb.h这个头文件是要包括的,里面包含了必须要用到的数据结构&*/
/*&我们将一个设备的属性用一个结构体来概括&*/
typedef struct
&&& struct usb_device*&&&
&&& usb_dev_handle*&&& &&& device_
&&& /*&这里可以添加设备的其他属性,这里只列出每个设备要用到的属性&*/
/*&用来设置传输数据的时间延迟&*/
#define USB_TIMEOUT&&&& 10000
/*&厂家ID&和产品&ID */
#define VENDOR_ID&&& 0xffff&&&&
#define PRODUCT_ID&& 0xffff
/*&这里定义数组来保存设备的相关属性,DEVICE_MINOR可以设置能够同时操作的设备数量,用全局变量的目的在于方便保存属性&*/
#define DEVICE_MINOR 16
int&&&& g_
device_descript g_list[ DEVICE_MINOR ];
/*&我们写个设备先找到设备,并把相关信息保存在&g_list&中&*/
int Device_Find()
&&& struct usb_bus&&& && *
&&& struct usb_device *
&&& g_num = 0;
&&& usb_find_busses();
&&& usb_find_devices();
&&& /*&寻找设备&*/
&&& for (bus = usb_ bus = bus-&next) {
&&& &&& for (dev = bus-& dev = dev-&next) {
if(dev-&descriptor.idVendor==VENDOR_ID&& dev-&descriptor.idProduct == PRODUCT_ID) {
&&& &&&&&&&&&&&&&&& /*&保存设备信息&*/
&&& &&&&&&&&&&&&&&& if (g_num & DEVICE_MINOR) {
&&& &&&&&&&&&&&&&&&& g_list[g_num].udev =&&
&&& &&&&&&&&&&&&&&&& g_num ++;
&&& &&& &&&&&&&&&&&& }&&&&&&&&&&&&&&
&&& &&&&&&& }&&&&&&&
&&& return g_
/*&找到设备后,我们根据信息打开设备&*/
int Device_Open()
&&& /*&根据情况打开你所需要操作的设备,这里我们仅列出伪代码&*/
&&& if(g_list[g_num].udev != NULL) {&&& &&& g_list[g_num].device_handle = usb_open(g_list[g_num].udev);
/*&下面就是操作设备的函数了,我们就不列出来拉,大家可以参考上面的介绍&*/
int DeviceWite(int handle)
&&& /*&填写相关代码,具体查看设备协议*/
int DeviceOpen(int handle)
&&& /*&填写相关代码,具体查看设备协议&*/
/*&最后不要忘记关闭设备&*/
void Device_close(int handle)
&&& /*&调用usb_close */
阅读(...) 评论()【胜为USB 2.0延长线】胜为(shengwei)UC-2030 USB延长线公对母 3米 透明 电脑usb加长线/延长线 USB2.0连接线 无线网卡U盘延长线【行情 报价 价格 评测】-京东
胜为USB 2.0延长线
PLUS会员专享价
您购买此商品可享受专属价
选择新地址
¥暂无报价
规格与包装
商品名称:胜为USB 2.0延长线
商品编号:148952
商品毛重:10.00g
商品产地:中国大陆
类型:数据线
连接线:usb延长线
品牌shengwei
种类USB延长线
名称胜为 高速USB 2.0延长线
接口USB针对孔(公对母)
其它特性无氧铜导体+双层屏蔽 标准USB 2.0 480Mbps高速传输 镀金触点
usb2.0延长线(3米) x1
权利声明:京东上的所有商品信息、客户评价、商品咨询、网友讨论等内容,是京东重要的经营资源,未经许可,禁止非法转载使用。
注:本站商品信息均来自于合作方,其真实性、准确性和合法性由信息拥有者(合作方)负责。本站不提供任何保证,并不承担任何法律责任。
价格说明:
京东价:京东价为商品的销售价,是您最终决定是否购买商品的依据。
划线价:商品展示的划横线价格为参考价,并非原价,该价格可能是品牌专柜标价、商品吊牌价或由品牌供应商提供的正品零售价(如厂商指导价、建议零售价等)或该商品在京东平台上曾经展示过的销售价;由于地区、时间的差异性和市场行情波动,品牌专柜标价、商品吊牌价等可能会与您购物时展示的不一致,该价格仅供您参考。
折扣:如无特殊说明,折扣指销售商在原价、或划线价(如品牌专柜标价、商品吊牌价、厂商指导价、厂商建议零售价)等某一价格基础上计算出的优惠比例或优惠金额;如有疑问,您可在购买前联系销售商进行咨询。
异常问题:商品促销信息以商品详情页“促销”栏中的信息为准;商品的具体售价以订单结算页价格为准;如您发现活动商品售价或促销信息有异常,建议购买前先联系销售商咨询。
您好!是连接什么设备,感谢您对京东的支持!祝您购物愉快!
您好!可以的,感谢您对京东的支持!祝您购物愉快!
您好!可以使用的,感谢您对京东的支持!祝您购物愉快!
您好!这种是延长线,是可以使用来做延长的。感谢您对京东的支持!祝您购物愉快!
您好!插拔一下,或者接一下USB键盘鼠标测试一下感谢您对京东的支持!祝您购物愉快!
您好!支持感谢您对京东的支持!祝您购物愉快!
您好!UC-1030支持感谢您对京东的支持!祝您购物愉快!
您好!粗细一样,长度不同感谢您对京东的支持!祝您购物愉快!
您好!US-201切换器感谢您对京东的支持!祝您购物愉快!
您好!请耐心等待!感谢您对京东的支持!祝您购物愉快!
心中疑惑就问问买过此商品的同学吧~
iframe(src='//www.googletagmanager.com/ns.html?id=GTM-T947SH', height='0', width='0', style='display: visibility:')VC++USB及串口通信程序
为公司开发产品测试程序,实际上是基于VC++的USB通信及串口通信。当初编写程序时,网上找了很多资料及程序,感觉大都只是说了一点点,没有一个完整的工程以供其他开发者借鉴,完全要靠开发者东拼西凑,最后凑成一个整体工程,还要在这个工程基础上进行相当艰苦的排查问题、解决问题的调试过程。本人对这一过程极其厌烦,现将走完的以上的&艰苦历程&之后的成果列出,以供后来者借鉴。
这一工程中包含了以下知识点:
1. VC++ USB通信;
2. VC++串口通信;
3. 文件(设备)同步异步操作;
4. 动态改变自体颜色
// VRGate_Product_TestDlg.cpp : 实现文件
#include &stdafx.h&
#include &VRGate_Product_Test.h&
#include &VRGate_Product_TestDlg.h&
#include &afxdialogex.h&
#include &setupapi.h&
extern &C& {
#include &hidsdi.h&
#pragma comment( lib, &setupapi.lib& )
#pragma comment( lib, &hid.lib& )
#ifdef _DEBUG
#define new DEBUG_NEW
BOOL Read8250RegFlag = FALSE;
// 用于应用程序&关于&菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
protected:
DECLARE_MESSAGE_MAP()
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
CDialogEx::DoDataExchange(pDX);
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CVRGate_Product_TestDlg 对话框
CVRGate_Product_TestDlg::CVRGate_Product_TestDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CVRGate_Product_TestDlg::IDD, pParent)
m_hIcon = AfxGetApp()-&LoadIcon(IDR_MAINFRAME);
devicePathName = _T(&&);
InputReportLength = 0;
OutputReportLength = 0;
void CVRGate_Product_TestDlg::DoDataExchange(CDataExchange* pDX)
CDialogEx::DoDataExchange(pDX);
BEGIN_MESSAGE_MAP(CVRGate_Product_TestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_FIND, &CVRGate_Product_TestDlg::OnBnClickedFind)
//ON_BN_CLICKED(IDOK, &CVRGate_Product_TestDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_OPEN, &CVRGate_Product_TestDlg::OnBnClickedOpen)
ON_BN_CLICKED(IDC_CLOSE, &CVRGate_Product_TestDlg::OnBnClickedClose)
ON_BN_CLICKED(IDC_OPEN2, &CVRGate_Product_TestDlg::OnBnClickedOpen2)
ON_BN_CLICKED(IDC_CLOSE2, &CVRGate_Product_TestDlg::OnBnClickedClose2)
ON_BN_CLICKED(IDC_ENTER_DEBUG_MODE, &CVRGate_Product_TestDlg::OnBnClickedEnterDebugMode)
ON_BN_CLICKED(IDC_EXIT_DEBUG_MODE, &CVRGate_Product_TestDlg::OnBnClickedExitDebugMode)
ON_BN_CLICKED(IDC_GET_PROTOCOL_VERSION, &CVRGate_Product_TestDlg::OnBnClickedGetProtocolVersion)
ON_BN_CLICKED(IDC_GET_HARDWARE_VERSION, &CVRGate_Product_TestDlg::OnBnClickedGetHardwareVersion)
ON_BN_CLICKED(IDC_GET_SOFTWARE_VERSION, &CVRGate_Product_TestDlg::OnBnClickedGetSoftwareVersion)
ON_BN_CLICKED(IDC_READ_EDID, &CVRGate_Product_TestDlg::OnBnClickedReadEdid)
ON_BN_CLICKED(IDC_READ_8520_REGISTER, &CVRGate_Product_TestDlg::OnBnClickedRead8520Register)
ON_BN_CLICKED(IDC_READ_HDMI_TIMECHK, &CVRGate_Product_TestDlg::OnBnClickedReadHdmiTimechk)
ON_BN_CLICKED(IDC_READ_SENSOR, &CVRGate_Product_TestDlg::OnBnClickedReadSensor)
ON_BN_CLICKED(IDC_OPEN_BACKLIGHT, &CVRGate_Product_TestDlg::OnBnClickedOpenBacklight)
ON_BN_CLICKED(IDC_CLOSE_BACKLIGHT, &CVRGate_Product_TestDlg::OnBnClickedCloseBacklight)
ON_BN_CLICKED(IDC_CLOSE_PWM, &CVRGate_Product_TestDlg::OnBnClickedClosePwm)
ON_BN_CLICKED(IDC_SET_SENSOR_SPEED, &CVRGate_Product_TestDlg::OnBnClickedSetSensorSpeed)
ON_BN_CLICKED(IDC_ENTER_DEBUG_MODE2, &CVRGate_Product_TestDlg::OnBnClickedEnterDebugMode2)
ON_BN_CLICKED(IDC_EXIT_DEBUG_MODE2, &CVRGate_Product_TestDlg::OnBnClickedExitDebugMode2)
ON_BN_CLICKED(IDC_GET_HARDWARE_VERSION2, &CVRGate_Product_TestDlg::OnBnClickedGetHardwareVersion2)
ON_BN_CLICKED(IDC_GET_SOFTWARE_VERSION2, &CVRGate_Product_TestDlg::OnBnClickedGetSoftwareVersion2)
ON_BN_CLICKED(IDC_GET_PROTOCOL_VERSION2, &CVRGate_Product_TestDlg::OnBnClickedGetProtocolVersion2)
ON_BN_CLICKED(IDC_READ_EDID2, &CVRGate_Product_TestDlg::OnBnClickedReadEdid2)
ON_BN_CLICKED(IDC_READ_8520_REGISTER2, &CVRGate_Product_TestDlg::OnBnClickedRead8520Register2)
ON_BN_CLICKED(IDC_READ_HDMI_TIMECHK2, &CVRGate_Product_TestDlg::OnBnClickedReadHdmiTimechk2)
ON_BN_CLICKED(IDC_READ_SENSOR2, &CVRGate_Product_TestDlg::OnBnClickedReadSensor2)
ON_BN_CLICKED(IDC_OPEN_BACKLIGHT2, &CVRGate_Product_TestDlg::OnBnClickedOpenBacklight2)
ON_BN_CLICKED(IDC_CLOSE_PWM2, &CVRGate_Product_TestDlg::OnBnClickedClosePwm2)
ON_BN_CLICKED(IDC_CLOSE_BACKLIGHT2, &CVRGate_Product_TestDlg::OnBnClickedCloseBacklight2)
ON_BN_CLICKED(IDC_SET_SENSOR_SPEED2, &CVRGate_Product_TestDlg::OnBnClickedSetSensorSpeed2)
ON_WM_CTLCOLOR()
ON_BN_CLICKED(IDC_UPDATE_FIRMWARE, &CVRGate_Product_TestDlg::OnBnClickedUpdateFirmware)
END_MESSAGE_MAP()
// CVRGate_Product_TestDlg 消息处理程序
BOOL CVRGate_Product_TestDlg::OnInitDialog()
CDialogEx::OnInitDialog();
// 将&关于...&菜单项添加到菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX & 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
BOOL bNameV
CString strAboutM
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
pSysMenu-&AppendMenu(MF_SEPARATOR);
pSysMenu-&AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE);// 设置大图标
SetIcon(m_hIcon, FALSE);// 设置小图标
ShowWindow(SW_MAXIMIZE);
// TODO: 在此添加额外的初始化代码
//初始化状态栏字体
/*m_Font.CreateFont(-11, 0, 0, 0, 100, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_SWISS, _T(&Arial&));
CEdit *m_Edit = (CEdit *)GetDlgItem(IDC_STATUS);
m_Edit-&SetFont(&m_Font,FALSE);
m_Font2.CreateFont(-11, 0, 0, 0, 100, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_SWISS, _T(&Arial&));
CEdit *m_Edit2 = (CEdit *)GetDlgItem(IDC_STATUS2);
m_Edit2-&SetFont(&m_Font2,FALSE); */
//设置状态栏初始字体颜色
m_color = RGB(0, 0, 0);
//设置对话框初始状态
GetDlgItem(IDC_FIND)-&EnableWindow(1);
GetDlgItem(IDC_OPEN)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE)-&EnableWindow(0);
GetDlgItem(IDC_ENTER_DEBUG_MODE)-&EnableWindow(0);
GetDlgItem(IDC_EXIT_DEBUG_MODE)-&EnableWindow(0);
GetDlgItem(IDC_UPDATE_FIRMWARE)-&EnableWindow(FALSE);
GetDlgItem(IDC_GET_HARDWARE_VERSION)-&EnableWindow(0);
GetDlgItem(IDC_GET_SOFTWARE_VERSION)-&EnableWindow(0);
GetDlgItem(IDC_GET_PROTOCOL_VERSION)-&EnableWindow(0);
GetDlgItem(IDC_READ_EDID)-&EnableWindow(0);
GetDlgItem(IDC_READ_8520_REGISTER)-&EnableWindow(0);
GetDlgItem(IDC_READ_HDMI_TIMECHK)-&EnableWindow(0);
GetDlgItem(IDC_READ_SENSOR)-&EnableWindow(0);
GetDlgItem(IDC_OPEN_BACKLIGHT)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE_PWM)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE_BACKLIGHT)-&EnableWindow(0);
GetDlgItem(IDC_RADIO1)-&EnableWindow(0);
GetDlgItem(IDC_RADIO2)-&EnableWindow(0);
GetDlgItem(IDC_RADIO3)-&EnableWindow(0);
GetDlgItem(IDC_SET_SENSOR_SPEED)-&EnableWindow(0);
GetDlgItem(IDC_OPEN2)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE2)-&EnableWindow(0);
GetDlgItem(IDC_ENTER_DEBUG_MODE2)-&EnableWindow(0);
GetDlgItem(IDC_EXIT_DEBUG_MODE2)-&EnableWindow(0);
GetDlgItem(IDC_GET_HARDWARE_VERSION2)-&EnableWindow(0);
GetDlgItem(IDC_GET_SOFTWARE_VERSION2)-&EnableWindow(0);
GetDlgItem(IDC_GET_PROTOCOL_VERSION2)-&EnableWindow(0);
GetDlgItem(IDC_READ_EDID2)-&EnableWindow(0);
GetDlgItem(IDC_READ_8520_REGISTER2)-&EnableWindow(0);
GetDlgItem(IDC_READ_HDMI_TIMECHK2)-&EnableWindow(0);
GetDlgItem(IDC_READ_SENSOR2)-&EnableWindow(0);
GetDlgItem(IDC_OPEN_BACKLIGHT2)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE_PWM2)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE_BACKLIGHT2)-&EnableWindow(0);
GetDlgItem(IDC_RADIO4)-&EnableWindow(0);
GetDlgItem(IDC_RADIO5)-&EnableWindow(0);
GetDlgItem(IDC_RADIO6)-&EnableWindow(0);
GetDlgItem(IDC_SET_SENSOR_SPEED2)-&EnableWindow(0);
bHaveCom = FALSE;
bComOpened = FALSE;
if(CheckSerialPort() != FALSE)
bHaveCom = TRUE;
GetDlgItem(IDC_OPEN2)-&EnableWindow(1);
((CComboBox*)GetDlgItem(IDC_COMBO1))-&ResetContent();
for (int i = 0; i & sizeof(m_nComArray)/sizeof(int); i++)
if(-1 == m_nComArray[i])
CString string1;
string1.Format(_T(&COM%d&), m_nComArray[i]);
((CComboBox*)GetDlgItem(IDC_COMBO1))-&AddString(string1);
((CComboBox*)GetDlgItem(IDC_COMBO1))-&SetCurSel(0);
UpdateData(false);
bHaveCom = FALSE;
AfxMessageBox(_T(&PC机没有COM口.....&));
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
void CVRGate_Product_TestDlg::OnSysCommand(UINT nID, LPARAM lParam)
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
CAboutDlg dlgA
dlgAbout.DoModal();
CDialogEx::OnSysCommand(nID, lParam);
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CVRGate_Product_TestDlg::OnPaint()
if (IsIconic())
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
CDialogEx::OnPaint();
//当用户拖动最小化窗口时系统调用此函数取得光标
HCURSOR CVRGate_Product_TestDlg::OnQueryDragIcon()
return static_cast(m_hIcon);
BOOL CVRGate_Product_TestDlg::USBReceivePacket(void)
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD dwBytesRead = InputReportL
ResetEvent(USBReadOverlapped.hEvent);
bResult = ReadFile(HidHandle, USBRxBuff, dwBytesRead, &dwBytesRead, &USBReadOverlapped);
if (!bResult)
if (ERROR_IO_PENDING == GetLastError()) //函数返回ERROR_IO_PENDING,表明USB正在进行读操作
WaitForSingleObject(USBReadOverlapped.hEvent, 2000); //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟.当USB读操作进行完毕后,USBReadOverlapped的hEvent事件会变为有信号
ResetEvent(USBReadOverlapped.hEvent);
AfxMessageBox(_T(&USB接收数据失败!&));
return FALSE;
if((USBRxBuff[1] = 0xAA) && (USBRxBuff[2] = 0x55) && (USBRxBuff[8+USBRxBuff[3]] == 0x0D) && (USBRxBuff[8+USBRxBuff[3]+1] == 0x0A)) //判断帧头帧尾
switch(USBRxBuff[5])
//Debug使用
case 0xA0:
if((USBRxBuff[8] == 'D') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'b') && (USBRxBuff[11] == 'u') && (USBRxBuff[12] == 'g') && (USBRxBuff[13] == ' ') \
&& (USBRxBuff[14] == 'M') && (USBRxBuff[15] == 'o') && (USBRxBuff[16] == 'd') && (USBRxBuff[17] == 'e'))
bResult = TRUE;
InfoMsg = _T(&\r\n调试模式&);
else if((USBRxBuff[8] == 'N') && (USBRxBuff[9] == 'o') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 'm') && (USBRxBuff[12] == 'a') && (USBRxBuff[13] == 'l') && (USBRxBuff[14] == ' ') \
&& (USBRxBuff[15] == 'M') && (USBRxBuff[16] == 'o') && (USBRxBuff[17] == 'd') && (USBRxBuff[18] == 'e'))
bResult = TRUE;
InfoMsg = _T(&\r\n正常模式&);
else if((USBRxBuff[8] == 'U') && (USBRxBuff[9] == 'p') && (USBRxBuff[10] == 'd') && (USBRxBuff[11] == 'a') && (USBRxBuff[12] == 't') && (USBRxBuff[13] == 'e') && (USBRxBuff[14] == ' ') \
&& (USBRxBuff[15] == 'M') && (USBRxBuff[16] == 'o') && (USBRxBuff[17] == 'd') && (USBRxBuff[18] == 'e'))
bResult = TRUE;
InfoMsg = _T(&\r\n升级模式&);
else if ((USBRxBuff[8] == 'E') && (USBRxBuff[9] == 'r') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 'o') && (USBRxBuff[12] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//获取版本信息类
case 0xC0:
if((USBRxBuff[8] == 'V') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'i') && (USBRxBuff[13] == 'o') && (USBRxBuff[14] == 'n') && (USBRxBuff[15] == '_') \
&& (USBRxBuff[16] == 'H') && (USBRxBuff[17] == 'a') && (USBRxBuff[18] == 'r') && (USBRxBuff[19] == 'd') && (USBRxBuff[20] == 'w') && (USBRxBuff[21] == 'a') && (USBRxBuff[22] == 'r') && (USBRxBuff[23] == 'e') \
&& (USBRxBuff[24] == '_') && (USBRxBuff[25] == 'V'))
bResult = TRUE;
tmpstr.Format(_T(&%c%c&), USBRxBuff[26],USBRxBuff[27]);
InfoMsg = _T(&\r\n硬件板卡版本号: &) +
else if((USBRxBuff[8] == 'V') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'i') && (USBRxBuff[13] == 'o') && (USBRxBuff[14] == 'n') && (USBRxBuff[15] == '_') \
&& (USBRxBuff[16] == 'S') && (USBRxBuff[17] == 'o') && (USBRxBuff[18] == 'f') && (USBRxBuff[19] == 't') && (USBRxBuff[20] == 'w') && (USBRxBuff[21] == 'a') && (USBRxBuff[22] == 'r') && (USBRxBuff[23] == 'e') \
&& (USBRxBuff[24] == '_') && (USBRxBuff[25] == 'V'))
bResult = TRUE;
tmpstr.Format(_T(&%c%c&), USBRxBuff[26],USBRxBuff[27]);
InfoMsg = _T(&\r\n固件版本号: &) +
else if((USBRxBuff[8] == 'V') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'i') && (USBRxBuff[13] == 'o') && (USBRxBuff[14] == 'n') && (USBRxBuff[15] == '_') \
&& (USBRxBuff[16] == 'P') && (USBRxBuff[17] == 'r') && (USBRxBuff[18] == 'o') && (USBRxBuff[19] == 't') && (USBRxBuff[20] == 'o') && (USBRxBuff[21] == 'c') && (USBRxBuff[22] == 'o') && (USBRxBuff[23] == 'l') \
&& (USBRxBuff[24] == '_') && (USBRxBuff[25] == 'V'))
bResult = TRUE;
tmpstr.Format(_T(&%c%c&), USBRxBuff[26],USBRxBuff[27]);
InfoMsg = _T(&\r\n通讯协议版本号: &) +
else if ((USBRxBuff[8] == 'E') && (USBRxBuff[9] == 'r') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 'o') && (USBRxBuff[12] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//测试通讯类收发类
case 0xD0:
if((USBRxBuff[8] == 0x00) && (USBRxBuff[9] == 0xFF) && (USBRxBuff[10] == 0xFF) && (USBRxBuff[11] == 0xFF) && (USBRxBuff[12] == 0xFF) && (USBRxBuff[13] == 0xFF) && (USBRxBuff[14] == 0xFF) && (USBRxBuff[15] == 0x00)) //EDID数据头
bResult = TRUE;
tmpstr.Format(_T(&0x%x%x&), USBRxBuff[16], USBRxBuff[17]);
InfoMsg = _T(&\r\n厂商ID: &) +
tmpstr.Format(_T(&0x%x%x&), USBRxBuff[18], USBRxBuff[19]);
InfoMsg += _T(&\r\n产品ID: &) +
tmpstr.Format(_T(&0x%x%x%x%x&), USBRxBuff[20], USBRxBuff[21], USBRxBuff[22], USBRxBuff[23]);
InfoMsg += _T(&\r\n序列号: &) +
tmpstr.Format(_T(&%d&), USBRxBuff[25]+1990);
InfoMsg += _T(&\r\n制造年份: &) +
tmpstr.Format(_T(&%d&), USBRxBuff[24]);
InfoMsg += _T(&\r\n制造周别: &) +
tmpstr.Format(_T(&%c.%c&), USBRxBuff[26], USBRxBuff[27]);
InfoMsg += _T(&\r\nEDIT版本: &) +
else if(Read8250RegFlag == TRUE)
Read8250RegFlag = FALSE;
bResult = TRUE;
tmpstr.Format(_T(&0x%x&), USBRxBuff[8]);
InfoMsg = _T(&\r\n8520寄存器值: &) +
else if((USBRxBuff[8] == 'T') && (USBRxBuff[9] == 'C') && (USBRxBuff[10] == '3') && (USBRxBuff[11] == '5') && (USBRxBuff[12] == '8') && (USBRxBuff[13] == '8') && (USBRxBuff[14] == '7') && (USBRxBuff[15] == '0') \
&& (USBRxBuff[16] == '_') && (USBRxBuff[17] == 'H') && (USBRxBuff[18] == 'D') && (USBRxBuff[19] == 'M') && (USBRxBuff[20] == 'I') && (USBRxBuff[21] == 'T') && (USBRxBuff[22] == 'i') && (USBRxBuff[23] == 'm') \
&& (USBRxBuff[24] == 'C') && (USBRxBuff[25] == 'h') && (USBRxBuff[26] == 'k') && (USBRxBuff[27] == ':') && (USBRxBuff[28] == ' '))
bResult = TRUE;
InfoMsg = _T(&TC358870_HDMITimChk: & + USBRxBuff[29] + USBRxBuff[30] + USBRxBuff[31] + USBRxBuff[32] + USBRxBuff[33] + USBRxBuff[34] + USBRxBuff[35]);
else if((USBRxBuff[8] == 'S') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'n') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'o') && (USBRxBuff[13] == 'r') && (USBRxBuff[14] == ' ') \
&& (USBRxBuff[15] == ':') && (USBRxBuff[16] == ' '))
bResult = TRUE;
InfoMsg = _T(&Sensor: & + USBRxBuff[17] + USBRxBuff[18] + USBRxBuff[19] + USBRxBuff[20]+ USBRxBuff[21] + USBRxBuff[22] + USBRxBuff[23] + USBRxBuff[24]+ USBRxBuff[25]);
else if ((USBRxBuff[8] == 'E') && (USBRxBuff[9] == 'r') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 'o') && (USBRxBuff[12] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//测试使能控制开关类
case 0xE0:
if((USBRxBuff[8] == 'C') && (USBRxBuff[9] == 'L') && (USBRxBuff[10] == 'S') && (USBRxBuff[11] == '_') && (USBRxBuff[12] == 'P') && (USBRxBuff[13] == 'W') && (USBRxBuff[14] == 'M') \
&& (USBRxBuff[15] == '_') && (USBRxBuff[16] == 'B') && (USBRxBuff[17] == 'a') && (USBRxBuff[18] == 'c') && (USBRxBuff[19] == 'k') && (USBRxBuff[20] == 'L') && (USBRxBuff[21] == 'i') && (USBRxBuff[22] == 'g') && (USBRxBuff[23] == 'h') && (USBRxBuff[24] == 't'))
bResult = TRUE;
InfoMsg = _T(&\r\n屏幕背光-关闭背光&);
else if((USBRxBuff[8] == 'E') && (USBRxBuff[9] == 'N') && (USBRxBuff[10] == '_') && (USBRxBuff[11] == 'P') && (USBRxBuff[12] == 'W') && (USBRxBuff[13] == 'M') \
&& (USBRxBuff[14] == '_') && (USBRxBuff[15] == 'B') && (USBRxBuff[16] == 'a') && (USBRxBuff[17] == 'c') && (USBRxBuff[18] == 'k') && (USBRxBuff[19] == 'L') && (USBRxBuff[20] == 'i') && (USBRxBuff[21] == 'g') && (USBRxBuff[22] == 'h') && (USBRxBuff[23] == 't'))
bResult = TRUE;
InfoMsg = _T(&\r\n屏幕背光-普通亮度&);
else if((USBRxBuff[8] == 'M') && (USBRxBuff[9] == 'A') && (USBRxBuff[10] == 'X') && (USBRxBuff[11] == '_') && (USBRxBuff[12] == 'P') && (USBRxBuff[13] == 'W') && (USBRxBuff[14] == 'M') \
&& (USBRxBuff[15] == '_') && (USBRxBuff[16] == 'B') && (USBRxBuff[17] == 'a') && (USBRxBuff[18] == 'c') && (USBRxBuff[19] == 'k') && (USBRxBuff[20] == 'L') && (USBRxBuff[21] == 'i') && (USBRxBuff[22] == 'g') && (USBRxBuff[23] == 'h') && (USBRxBuff[24] == 't'))
bResult = TRUE;
InfoMsg = _T(&\r\n屏幕背光-最大亮度&);
else if ((USBRxBuff[8] == 'E') && (USBRxBuff[9] == 'r') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 'o') && (USBRxBuff[12] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//设置陀螺仪等Sensor的传输速度
case 0xE1:
if((USBRxBuff[8] == 'S') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'n') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'o') && (USBRxBuff[13] == 'r') && (USBRxBuff[14] == ' ') \
&& (USBRxBuff[15] == '1') && (USBRxBuff[16] == '0') && (USBRxBuff[17] == '0') && (USBRxBuff[18] == '0') && (USBRxBuff[19] == 'H') && (USBRxBuff[20] == 'z'))
bResult = TRUE;
InfoMsg = _T(&\r\n传感器采样率:1000Hz&);
else if((USBRxBuff[8] == 'S') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'n') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'o') && (USBRxBuff[13] == 'r') && (USBRxBuff[14] == ' ') \
&& (USBRxBuff[15] == '5') && (USBRxBuff[16] == '0') && (USBRxBuff[17] == '0') && (USBRxBuff[18] == 'H') && (USBRxBuff[19] == 'z'))
bResult = TRUE;
InfoMsg = _T(&\r\n传感器采样率:500Hz&);
else if((USBRxBuff[8] == 'S') && (USBRxBuff[9] == 'e') && (USBRxBuff[10] == 'n') && (USBRxBuff[11] == 's') && (USBRxBuff[12] == 'o') && (USBRxBuff[13] == 'r') && (USBRxBuff[14] == ' ') \
&& (USBRxBuff[15] == '1') && (USBRxBuff[16] == '0') && (USBRxBuff[17] == '0') && (USBRxBuff[18] == 'H') && (USBRxBuff[19] == 'z'))
bResult = TRUE;
InfoMsg = _T(&\r\n传感器采样率:100Hz&);
else if ((USBRxBuff[8] == 'E') && (USBRxBuff[9] == 'r') && (USBRxBuff[10] == 'r') && (USBRxBuff[11] == 'o') && (USBRxBuff[12] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误: 未定义指令&);
bResult = FALSE;
ErrMsg = _T(&\r\n帧数据校验错误&);
ResetEvent(USBReadOverlapped.hEvent);
BOOL CVRGate_Product_TestDlg::ComReceivePacket(void)
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD dwBytesRead = sizeof(ComRxBuff);
memset(ComRxBuff, 0x00 ,sizeof(ComRxBuff));
/*不能有这段程序,否则直接清空了串口输入缓冲区,导致数据收不到
ResetEvent(ComReadOverlapped.hEvent);
//清空串口的输入缓冲区
PurgeComm(ComHandle, PURGE_RXABORT | PURGE_RXCLEAR); //立即中断所有读操作并立即返回,即使读操作还没有完成 | 清空输入缓冲区
bResult = ClearCommError(ComHandle, &dwError, &ComReadStat); //在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误.该函数获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志以便继续输入、输出操作
if (ComReadStat.cbInQue == 0) //输入缓冲区有多少数据
return FALSE;
dwBytesRead = min(dwBytesRead, (DWORD)ComReadStat.cbInQue);
if(!dwBytesRead)
return FALSE;
bResult = ReadFile(ComHandle, ComRxBuff, dwBytesRead, &dwBytesRead, &ComReadOverlapped);
if (!bResult)
if (ERROR_IO_PENDING == GetLastError()) //函数返回ERROR_IO_PENDING,表明串口正在进行读操作
WaitForSingleObject(ComReadOverlapped.hEvent, 2000); ////使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟.当串口读操作进行完毕后,m_ov的hEvent事件会变为有信号
ClearCommError(ComHandle, &dwError, &ComReadStat);
PurgeComm(ComHandle, PURGE_RXABORT | PURGE_RXCLEAR); //立即中断所有读操作并立即返回,即使读操作还没有完成 | 清空输入缓冲区
ResetEvent(ComReadOverlapped.hEvent);
AfxMessageBox(_T(&串口接收数据失败!&));
return FALSE;
if((ComRxBuff[0] = 0xAA) && (ComRxBuff[1] = 0x55) && (ComRxBuff[8+ComRxBuff[2]-1] == 0x0D) && (ComRxBuff[8+ComRxBuff[2]] == 0x0A)) //判断帧头帧尾
switch(ComRxBuff[4])
//Debug使用
case 0xA0:
if((ComRxBuff[7] == 'D') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'b') && (ComRxBuff[10] == 'u') && (ComRxBuff[11] == 'g') && (ComRxBuff[12] == ' ') \
&& (ComRxBuff[13] == 'M') && (ComRxBuff[14] == 'o') && (ComRxBuff[15] == 'd') && (ComRxBuff[16] == 'e'))
bResult = TRUE;
InfoMsg = _T(&\r\n调试模式&);
else if((ComRxBuff[7] == 'N') && (ComRxBuff[8] == 'o') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 'm') && (ComRxBuff[11] == 'a') && (ComRxBuff[12] == 'l') && (ComRxBuff[13] == ' ') \
&& (ComRxBuff[14] == 'M') && (ComRxBuff[15] == 'o') && (ComRxBuff[16] == 'd') && (ComRxBuff[17] == 'e'))
bResult = TRUE;
InfoMsg = _T(&\r\n正常模式&);
else if ((ComRxBuff[7] == 'E') && (ComRxBuff[8] == 'r') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 'o') && (ComRxBuff[11] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//获取版本信息类
case 0xC0:
if((ComRxBuff[7] == 'V') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'i') && (ComRxBuff[12] == 'o') && (ComRxBuff[13] == 'n') && (ComRxBuff[14] == '_') \
&& (ComRxBuff[15] == 'H') && (ComRxBuff[16] == 'a') && (ComRxBuff[17] == 'r') && (ComRxBuff[18] == 'd') && (ComRxBuff[19] == 'w') && (ComRxBuff[20] == 'a') && (ComRxBuff[21] == 'r') && (ComRxBuff[22] == 'e') \
&& (ComRxBuff[23] == '_') && (ComRxBuff[24] == 'V'))
bResult = TRUE;
tmpstr.Format(_T(&%c%c&), ComRxBuff[25],ComRxBuff[26]);
InfoMsg = _T(&\r\n硬件板卡版本号: &) +
else if((ComRxBuff[7] == 'V') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'i') && (ComRxBuff[12] == 'o') && (ComRxBuff[13] == 'n') && (ComRxBuff[14] == '_') \
&& (ComRxBuff[15] == 'S') && (ComRxBuff[16] == 'o') && (ComRxBuff[17] == 'f') && (ComRxBuff[18] == 't') && (ComRxBuff[19] == 'w') && (ComRxBuff[20] == 'a') && (ComRxBuff[21] == 'r') && (ComRxBuff[22] == 'e') \
&& (ComRxBuff[23] == '_') && (ComRxBuff[24] == 'V'))
bResult = TRUE;
tmpstr.Format(_T(&%c%c&), ComRxBuff[25],ComRxBuff[26]);
InfoMsg = _T(&\r\n固件版本号: &) +
else if((ComRxBuff[7] == 'V') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'i') && (ComRxBuff[12] == 'o') && (ComRxBuff[13] == 'n') && (ComRxBuff[14] == '_') \
&& (ComRxBuff[15] == 'P') && (ComRxBuff[16] == 'r') && (ComRxBuff[17] == 'o') && (ComRxBuff[18] == 't') && (ComRxBuff[19] == 'o') && (ComRxBuff[20] == 'c') && (ComRxBuff[21] == 'o') && (ComRxBuff[22] == 'l') \
&& (ComRxBuff[23] == '_') && (ComRxBuff[24] == 'V'))
bResult = TRUE;
tmpstr.Format(_T(&%c%c&), ComRxBuff[25],ComRxBuff[26]);
InfoMsg = _T(&\r\n通讯协议版本号: &) +
else if ((ComRxBuff[7] == 'E') && (ComRxBuff[8] == 'r') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 'o') && (ComRxBuff[11] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//测试通讯类收发类
case 0xD0:
if((ComRxBuff[7] == 0x00) && (ComRxBuff[8] == 0xFF) && (ComRxBuff[9] == 0xFF) && (ComRxBuff[10] == 0xFF) && (ComRxBuff[11] == 0xFF) && (ComRxBuff[12] == 0xFF) && (ComRxBuff[13] == 0xFF) && (ComRxBuff[14] == 0x00))
bResult = TRUE;
tmpstr.Format(_T(&0x%x%x&), ComRxBuff[15], ComRxBuff[16]);
InfoMsg = _T(&\r\n厂商ID: &) +
tmpstr.Format(_T(&0x%x%x&), ComRxBuff[17], ComRxBuff[18]);
InfoMsg += _T(&\r\n产品ID: &) +
tmpstr.Format(_T(&0x%x%x%x%x&), ComRxBuff[19], ComRxBuff[20], ComRxBuff[21], ComRxBuff[22]);
InfoMsg += _T(&\r\n序列号: &) +
tmpstr.Format(_T(&%d&), ComRxBuff[24]+1990);
InfoMsg += _T(&\r\n制造年份: &) +
tmpstr.Format(_T(&%d&), ComRxBuff[23]);
InfoMsg += _T(&\r\n制造周别: &) +
tmpstr.Format(_T(&%c.%c&), ComRxBuff[25], ComRxBuff[26]);
InfoMsg += _T(&\r\nEDIT版本: &) +
else if(Read8250RegFlag == TRUE)
Read8250RegFlag = FALSE;
bResult = TRUE;
tmpstr.Format(_T(&0x%x&), ComRxBuff[7]);
InfoMsg = _T(&\r\n8520寄存器值: &) +
else if((ComRxBuff[7] == 'T') && (ComRxBuff[8] == 'C') && (ComRxBuff[9] == '3') && (ComRxBuff[10] == '5') && (ComRxBuff[11] == '8') && (ComRxBuff[12] == '8') && (ComRxBuff[13] == '7') && (ComRxBuff[14] == '0') \
&& (ComRxBuff[15] == '_') && (ComRxBuff[16] == 'H') && (ComRxBuff[17] == 'D') && (ComRxBuff[18] == 'M') && (ComRxBuff[19] == 'I') && (ComRxBuff[20] == 'T') && (ComRxBuff[21] == 'i') && (ComRxBuff[22] == 'm') \
&& (ComRxBuff[23] == 'C') && (ComRxBuff[24] == 'h') && (ComRxBuff[25] == 'k') && (ComRxBuff[26] == ':') && (ComRxBuff[27] == ' '))
bResult = TRUE;
InfoMsg = _T(&TC358870_HDMITimChk: & + ComRxBuff[28] + ComRxBuff[29] + ComRxBuff[30] + ComRxBuff[31] + ComRxBuff[32] + ComRxBuff[33] + ComRxBuff[34]);
else if((ComRxBuff[7] == 'S') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'n') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'o') && (ComRxBuff[12] == 'r') && (ComRxBuff[13] == ' ') \
&& (ComRxBuff[14] == ':') && (ComRxBuff[15] == ' '))
bResult = TRUE;
InfoMsg = _T(&Sensor: & + ComRxBuff[16] + ComRxBuff[17] + ComRxBuff[18] + ComRxBuff[19] + ComRxBuff[20] + ComRxBuff[21] + ComRxBuff[22] + ComRxBuff[23] + ComRxBuff[24]);
else if ((ComRxBuff[7] == 'E') && (ComRxBuff[8] == 'r') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 'o') && (ComRxBuff[11] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//测试使能控制开关类
case 0xE0:
if((ComRxBuff[7] == 'C') && (ComRxBuff[8] == 'L') && (ComRxBuff[9] == 'S') && (ComRxBuff[10] == '_') && (ComRxBuff[11] == 'P') && (ComRxBuff[12] == 'W') && (ComRxBuff[13] == 'M') \
&& (ComRxBuff[14] == '_') && (ComRxBuff[15] == 'B') && (ComRxBuff[16] == 'a') && (ComRxBuff[17] == 'c') && (ComRxBuff[18] == 'k') && (ComRxBuff[19] == 'L') && (ComRxBuff[20] == 'i') && (ComRxBuff[21] == 'g') && (ComRxBuff[22] == 'h') && (ComRxBuff[23] == 't'))
bResult = TRUE;
InfoMsg = _T(&\r\n屏幕背光-关闭背光&);
else if((ComRxBuff[7] == 'E') && (ComRxBuff[8] == 'N') && (ComRxBuff[9] == '_') && (ComRxBuff[10] == 'P') && (ComRxBuff[11] == 'W') && (ComRxBuff[12] == 'M') \
&& (ComRxBuff[13] == '_') && (ComRxBuff[14] == 'B') && (ComRxBuff[15] == 'a') && (ComRxBuff[16] == 'c') && (ComRxBuff[17] == 'k') && (ComRxBuff[18] == 'L') && (ComRxBuff[19] == 'i') && (ComRxBuff[20] == 'g') && (ComRxBuff[21] == 'h') && (ComRxBuff[22] == 't'))
bResult = TRUE;
InfoMsg = _T(&\r\n屏幕背光-普通亮度&);
else if((ComRxBuff[7] == 'M') && (ComRxBuff[8] == 'A') && (ComRxBuff[9] == 'X') && (ComRxBuff[10] == '_') && (ComRxBuff[11] == 'P') && (ComRxBuff[12] == 'W') && (ComRxBuff[13] == 'M') \
&& (ComRxBuff[14] == '_') && (ComRxBuff[15] == 'B') && (ComRxBuff[16] == 'a') && (ComRxBuff[17] == 'c') && (ComRxBuff[18] == 'k') && (ComRxBuff[19] == 'L') && (ComRxBuff[20] == 'i') && (ComRxBuff[21] == 'g') && (ComRxBuff[22] == 'h') && (ComRxBuff[23] == 't'))
bResult = TRUE;
InfoMsg = _T(&\r\n屏幕背光-最大亮度&);
else if ((ComRxBuff[7] == 'E') && (ComRxBuff[8] == 'r') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 'o') && (ComRxBuff[11] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
//设置陀螺仪等Sensor的传输速度
case 0xE1:
if((ComRxBuff[7] == 'S') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'n') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'o') && (ComRxBuff[12] == 'r') && (ComRxBuff[13] == ' ') \
&& (ComRxBuff[14] == '1') && (ComRxBuff[15] == '0') && (ComRxBuff[16] == '0') && (ComRxBuff[17] == '0') && (ComRxBuff[18] == 'H') && (ComRxBuff[19] == 'z'))
bResult = TRUE;
InfoMsg = _T(&\r\n传感器采样率:1000Hz&);
else if((ComRxBuff[7] == 'S') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'n') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'o') && (ComRxBuff[12] == 'r') && (ComRxBuff[13] == ' ') \
&& (ComRxBuff[14] == '5') && (ComRxBuff[15] == '0') && (ComRxBuff[16] == '0') && (ComRxBuff[17] == 'H') && (ComRxBuff[18] == 'z'))
bResult = TRUE;
InfoMsg = _T(&\r\n传感器采样率:500Hz&);
else if((ComRxBuff[7] == 'S') && (ComRxBuff[8] == 'e') && (ComRxBuff[9] == 'n') && (ComRxBuff[10] == 's') && (ComRxBuff[11] == 'o') && (ComRxBuff[12] == 'r') && (ComRxBuff[13] == ' ') \
&& (ComRxBuff[14] == '1') && (ComRxBuff[15] == '0') && (ComRxBuff[16] == '0') && (ComRxBuff[17] == 'H') && (ComRxBuff[18] == 'z'))
bResult = TRUE;
InfoMsg = _T(&\r\n传感器采样率:100Hz&);
else if ((ComRxBuff[7] == 'E') && (ComRxBuff[8] == 'r') && (ComRxBuff[9] == 'r') && (ComRxBuff[10] == 'o') && (ComRxBuff[11] == 'r'))
bResult = FALSE;
ErrMsg = _T(&\r\n下位机返回Error&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误&);
bResult = FALSE;
ErrMsg = _T(&\r\n其他错误: 未定义指令&);
bResult = FALSE;
ErrMsg = _T(&\r\n帧数据校验错误&);
ClearCommError(ComHandle, &dwError, &ComReadStat);
//清空串口的输入缓冲区
PurgeComm(ComHandle, PURGE_RXABORT | PURGE_RXCLEAR); //立即中断所有读操作并立即返回,即使读操作还没有完成 | 清空输入缓冲区
ResetEvent(ComReadOverlapped.hEvent);
BOOL CVRGate_Product_TestDlg::USBSendPacket(unsigned char *sendbuffer)
DWORD dwBytesWrite = OutputReportL
BOOL bWriteS
if(!sendbuffer)
return FALSE;
ResetEvent(USBWriteOverlapped.hEvent);
bWriteStat = WriteFile(HidHandle, sendbuffer, dwBytesWrite, &dwBytesWrite, &USBWriteOverlapped);
if(!bWriteStat)
if(GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(USBWriteOverlapped.hEvent,2000);
ResetEvent(USBWriteOverlapped.hEvent);
AfxMessageBox(_T(&USB发送数据失败!&));
return FALSE;
ResetEvent(USBWriteOverlapped.hEvent);
return TRUE;
BOOL CVRGate_Product_TestDlg::ComSendPacket(unsigned char *sendbuffer, int length)
DWORD dwBytesWrite =
DWORD dwErrorF
BOOL bWriteS
if(!sendbuffer)
return FALSE;
ResetEvent(ComWriteOverlapped.hEvent);
//清空串口的输出缓冲区
PurgeComm(ComHandle, PURGE_TXABORT | PURGE_TXCLEAR); //立即中断所有写操作并立即返回,即使写操作还没有完成 | 清空输出缓冲区
ClearCommError(ComHandle, &dwErrorFlags, &ComWriteStat);
bWriteStat = WriteFile(ComHandle, sendbuffer, dwBytesWrite, &dwBytesWrite, &ComWriteOverlapped);
if(!bWriteStat)
if(GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(ComWriteOverlapped.hEvent,2000);
ClearCommError(ComHandle, &dwErrorFlags, &ComWriteStat);
//清空串口的输出缓冲区
PurgeComm(ComHandle, PURGE_TXABORT | PURGE_TXCLEAR); //立即中断所有写操作并立即返回,即使写操作还没有完成 | 清空输出缓冲区
ResetEvent(ComWriteOverlapped.hEvent);
AfxMessageBox(_T(&串口发送数据失败!&));
return FALSE;
ClearCommError(ComHandle, &dwErrorFlags, &ComWriteStat);
//清空串口的输出缓冲区
PurgeComm(ComHandle, PURGE_TXABORT | PURGE_TXCLEAR); //立即中断所有写操作并立即返回,即使写操作还没有完成 | 清空输出缓冲区
ResetEvent(ComWriteOverlapped.hEvent);
return TRUE;
DWORD WINAPI USBReadThread(LPVOID pParam)
while(bIsUSBThreadWorking)
USBReceivePacket();
bIsUSBThreadStop = 1;//到这里表示已经跳出循环了
CString CVRGate_Product_TestDlg::FindUSBDevice(CString Vid, CString Pid)
//查找本系统中HID类的GUID标识
GUID guidHID;
HidD_GetHidGuid(&guidHID);
//查找符合HID规范的USB设备
HDEVINFO hDevInfo = SetupDiGetClassDevs(&guidHID, NULL, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
return NULL;
int InterfaceIndex = 0;
while (TRUE)
//查找USB设备接口
SP_DEVICE_INTERFACE_DATA strtInterfaceD
strtInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); //必须有这句,否则下边枚举会失败!
//枚举接口,TRUE表示成功
BOOL result = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guidHID, InterfaceIndex, &strtInterfaceData);
if (!result)
InterfaceIndex++;
int bufferSize = 0;
//若找到了接口,则读取设备(接口)路径名
SP_DEVINFO_DATA strtDevInfoD
strtDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
//第一次调用出错,但可以返回正确的Size
result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &strtInterfaceData, NULL, 0, (PDWORD)&bufferSize, &strtDevInfoData);
//第二次调用传递返回值,调用即可成功
/* Allocate memory for Device Detailed Data */
PSP_DEVICE_INTERFACE_DETAIL_DATA strtDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(bufferSize); //此处必须用动态分配而不能定义局部变量,因为要在此结构体后边存放很大的内容,而局部变量没有如此大的空间!
/* Set cbSize in the DevDetail structure */
strtDetailData-&cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &strtInterfaceData, strtDetailData, bufferSize, (PDWORD)&bufferSize, &strtDevInfoData);
if (result == FALSE)
free(strtDetailData);
strtDetailData = NULL;
//获取设备路径
wchar_t *pdevicePathName = strtDetailData-&DeviceP
CString tmpDevicePathName = CString(pdevicePathName);
free(strtDetailData);
strtDetailData = NULL;
pdevicePathName = NULL;
CString tmpstr = _T(&hid#&);
tmpstr += _T(&vid_&) + Vid.MakeLower() + '&' + _T(&pid_&) + Pid.MakeLower(); //tmpstr should be: &hid#vid_046d&pid_c077&
int idx = -1;
idx = tmpDevicePathName.Find(tmpstr);
if (idx &= 0)
//释放设备资源(hDevInfo是SetupDiGetClassDevs获取的)
if (hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
return tmpDevicePathN
} //End of while
//释放设备资源(hDevInfo是SetupDiGetClassDevs获取的)
if (hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
return NULL;
BOOL CVRGate_Product_TestDlg::OpenUSBDevice(CString DeviceName)
//Create File for Device Read/Write
HidHandle = CreateFile(DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //文件属性与标志,用于指定USB是否进行异步操作,该值为FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作
//0, //同步方式,
if (HidHandle == INVALID_HANDLE_VALUE)
return FALSE;
//Set Input Buffer Size
int NumInputBuffers = 2;
BOOL ret = HidD_SetNumInputBuffers(HidHandle, NumInputBuffers);
return FALSE;
//Get Preparsed Data
PHIDP_PREPARSED_DATA PreparsedD
ret = HidD_GetPreparsedData(HidHandle, &PreparsedData);
return FALSE;
//Get Device's Capabilities
HIDP_CAPS C
HidP_GetCaps(PreparsedData, &Capabilities);
InputReportLength = Capabilities.InputReportByteL
OutputReportLength = Capabilities.OutputReportByteL
//释放HidD_GetPreparsedData使用的资源
HidD_FreePreparsedData(PreparsedData);
return TRUE;
void CVRGate_Product_TestDlg::CloseUSBDevice(void)
if (HidHandle != INVALID_HANDLE_VALUE)
CloseHandle(HidHandle);
HidHandle = NULL;
BOOL CVRGate_Product_TestDlg::SetupDCB(void)
memset(&dcb,0,sizeof(dcb));
if(!GetCommState(ComHandle,&dcb)) //获取当前DCB配置
AfxMessageBox(_T(&获取DCB配置失败!&));
return FALSE;
dcb.DCBlength = sizeof(DCB);
//serial port config
dcb.BaudRate = 115200; //波特率
dcb.ByteSize = 8; //数据位
dcb.fParity = FALSE; //TRUE; //是否奇偶校验
dcb.Parity = NOPARITY; //ODDPARITY; //奇偶校验方式
dcb.StopBits = ONESTOPBIT; //停止位
dcb.fOutxCtsFlow = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 0;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutX = 0;
dcb.fInX = 0;
//misc parameters
dcb.fErrorChar = 0;
dcb.fBinary = 1; //是否允许传二进制
dcb.fNull = 0;
dcb.fAbortOnError = 0;
dcb.wReserved = 0;
dcb.XonLim = 2;
dcb.XoffLim = 4;
dcb.XonChar = 0x13;
dcb.XoffChar = 0x19;
dcb.EvtChar = 0;
if(!SetCommState(ComHandle, &dcb)) //设置DCB
AfxMessageBox(_T(&设置DCB失败!&));
return FALSE;
return TRUE;
BOOL CVRGate_Product_TestDlg::CheckSerialPort(void)
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(&HARDWARE\\DEVICEMAP\\SERIALCOMM&), 0, KEY_READ, &hKey) )
TCHAR achClass[MAX_PATH] = TEXT(&&); //buffer for class name
DWORD cchClassName = MAX_PATH; //size of class string
DWORD cSubKeys=0; //number of subkeys
DWORD cbMaxSubK //longest subkey size
DWORD cchMaxC //longest class string
DWORD cV //number of values for key
DWORD cchMaxV //longest value name
DWORD cbMaxValueD //longest value data
DWORD cbSecurityD //size of security descriptor
FILETIME ftLastWriteT //last write time
DWORD i, retC
TCHAR achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;
//Get the class name and the value count
retCode = RegQueryInfoKey(
hKey,//key handle
achClass,//buffer for class name
&cchClassName,//size of class string
NULL,//reserved
&cSubKeys,//number of subkeys
&cbMaxSubKey,//longest subkey size
&cchMaxClass,//longest class string
&cValues,//number of values for this key
&cchMaxValue,//longest value name
&cbMaxValueData,//longest value data
&cbSecurityDescriptor,//security descriptor
&ftLastWriteTime);//last write time
if (cValues & 0)
for (i=0; i {
m_nComArray[i] = -1;
for (i=0, retCode=ERROR_SUCCESS; i {
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
if (ERROR_SUCCESS == RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL))
CString szName(achValue);
if (-1 != szName.Find(_T(&Serial&)) || -1 != szName.Find(_T(&VCom&)) || -1 != szName.Find(_T(&VCP&)))
BYTE strDSName[10];
memset(strDSName, 0, 10);
DWORD nValueType = 0, nBuffLen = 10;
if (ERROR_SUCCESS == RegQueryValueEx(hKey, (LPCTSTR)achValue, NULL, &nValueType, strDSName, &nBuffLen))
int nIndex = -1;
while(++nIndex & sizeof(m_nComArray)/sizeof(int))
if (-1 == m_nComArray[nIndex])
m_nComArray[nIndex] = atoi((char*)(strDSName + sizeof(TCHAR)*3));
//AfxMessageBox(_T(&PC机没有COM口.....&));
return FALSE;
RegCloseKey(hKey);
return TRUE;
BOOL CVRGate_Product_TestDlg::SetupTimeout(DWORD ReadInterval, DWORD ReadTotalMultiplier, DWORD ReadTotalconstant, DWORD WriteTotalMultiplier, DWORD WriteTotalconstant)
COMMTIMEOUTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//读写串口的超时有两种:间隔超时和总超时。
//间隔超时是指在接收时两个字符之间的最大时延。总超时是指读写操作总共花费的最大时间。
//写操作只支持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读写操作的超时。
//COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:
//总超时=时间系数&要求读/写的字符数+时间常量
//例如,要读入10个字符,那么读操作的总超时的计算公式为:
//读总超时=ReadTotalTimeoutMultiplier&10+ReadTotalTimeoutConstant
//如果所有写超时参数均为0,那么就不使用写超时
//如果ReadIntervalTimeout为0,那么就不使用读间隔超时
//如果ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都为0,则不使用读总超时
//如果读间隔超时被设置成MAXDWORD并且读时间系数和读时间常量都为0,那么在读一次输入缓冲区的内容后读操作就立即返回,而不管是否读入了要求的字符
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//设定读超时
timeouts.ReadIntervalTimeout = ReadI //读间隔超时
timeouts.ReadTotalTimeoutConstant = ReadT //读时间系数
timeouts.ReadTotalTimeoutMultiplier = ReadTotalM //读时间常量
//设定写超时
timeouts.WriteTotalTimeoutConstant = WriteT //写时间系数
timeouts.WriteTotalTimeoutMultiplier = WriteTotalM //写时间常量
if(!SetCommTimeouts(ComHandle, &timeouts))
AfxMessageBox(_T(&设置超时时间失败!&));
return FALSE;
return TRUE;
BOOL CVRGate_Product_TestDlg::OpenSerialDevice(int PortNum)
CString szC
szCom.Format(_T(&\\\\.\\COM%d&), PortNum);
ComHandle = CreateFile(szCom.GetBuffer(50), //逻辑串口号,用字符串&COMX&表示,&X&是串口序号,关于电脑中的逻辑串口号,在注册表HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP目录下,包含字符&Serial&或&VCom&项下面的值就是,可以有多个
GENERIC_READ | GENERIC_WRITE, //是对串口的访问权限,串口只有读/写(GENERIC_READ/GENERIC_WRITE)权限,可以同时设置成读/写权限,也可以单独只设置读或写权限
0, //共享模式,有读/写/删除共享,对串口通信只能独占模式,即是0
NULL, //文件安全属性,对串口设置成NULL
OPEN_EXISTING, //创建方式,有CREATE_ALWAYS/ CREATE_NEW/ OPEN_EXISTING等方式,但是对串口只能是OPEN_EXISTING,只能打开存在的串口,不像文件一样可创建之类
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //文件属性与标志,用于指定该串口是否进行异步操作,该值为FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作
//0, //同步方式
NULL //文件句柄,新文件从该句柄复制或扩展,如果函数执行成功,返回新的句柄,对串口通信,设置成NULL
if(ComHandle == INVALID_HANDLE_VALUE)
AfxMessageBox(_T(&串口打开失败!&));
return FALSE;
SetupComm(ComHandle, ); //输入缓冲区和输出缓冲区的大小均设为1024
SetupDCB();
SetupTimeout(0,0,0,0,0); //设置读写超时时间
PurgeComm(ComHandle, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //清除输入缓冲区 | 清除输出缓冲区 | 中断所有读操作并立即返回,即使读操作还没有完成 |立即中断所有写操作并立即返回,即使写操作还没有完成
return TRUE;
void CVRGate_Product_TestDlg::CloseSerialDevice(void)
//禁止串行端口所有事件
SetCommMask(ComHandle, 0);
//清除数据终端就绪信号
EscapeCommFunction(ComHandle, CLRDTR);
//丢弃通信资源的输出或输入缓冲区字符并终止在通信资源上挂起的读、写操操作
PurgeComm(ComHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
CloseHandle(ComHandle);
ComHandle = NULL;
void CVRGate_Product_TestDlg::OnBnClickedFind()
// TODO: 在此添加控件通知处理程序代码
devicePathName = FindUSBDevice(_T(&0483&), _T(&5750&));
if (devicePathName.IsEmpty())
AfxMessageBox(_T(&找不到指定USB设备!&));
GetDlgItem(IDC_OPEN)-&EnableWindow(0);
GetDlgItem(IDC_CLOSE)-&EnableWindow(0);
if(bComOpened != TRUE)
GetDlgItem(IDC_OPEN)-&EnableWindow(1);
MessageBox(_T(&找到了指定USB设备!&));
DWORD WINAPI SerialReadThread(LPVOID pParam)
while(bIsComThreadWorking)
SerialReceivePacket();
bIsComThreadStop = 1;//到这里表示已经跳出循环了
void CVRGate_Product_TestDlg::OnBnClickedOpen()
// TODO: 在此添加控件通知处理程序代码
if(OpenUSBDevice(devicePathName) != FALSE)
GetDlgItem(IDC_OPEN)-&EnableWindow(FALSE);
GetDlgItem(IDC_CLOSE)-&EnableWindow(TRUE);
GetDlgItem(IDC_ENTER_DEBUG_MODE)-&EnableWindow(TRUE);
GetDlgItem(IDC_OPEN2)-&EnableWindow(FALSE);
GetDlgItem(IDC_CLOSE2)-&EnableWindow(FALSE);
GetDlgItem(IDC_ENTER_DEBUG_MODE2)-&EnableWindow(FALSE);
GetDlgItem(IDC_EXIT_DEBUG_MODE2)-&EnableWindow(FALSE);
GetDlgItem(IDC_GET_HARDWARE_VERSION2)-&EnableWindow(FALSE);
GetDlgItem(IDC_GET_SOFTWARE_VERSION2)-&EnableWindow(FALSE);
GetDlgItem(IDC_GET_PROTOCOL_VERSION2)-&EnableWindow(FALSE);
GetDlgItem(IDC_READ_EDID2)-&EnableWindow(FALSE);
GetDlgItem(IDC_READ_8520_REGISTER2)-&EnableWindow(FALSE);
GetDlgItem(IDC_READ_HDMI_TIMECHK2)-&EnableWindow(FALSE);
GetDlgItem(IDC_READ

我要回帖

更多关于 充电桩标准 的文章

 

随机推荐