HID设备介绍可以看这里。
usb 不仅仅hid通信方式,还有其余的usb通信方式,但hid的好处就是无需安装驱动,热插拔直接用。
HIDAPI 是一个 USB 和蓝牙的 hid 类设备在 Windows、Linux、FreeBSD 和 Mac 的 C 语言通用库,使用 HIDAPI可以在 Windows、Linux、FreeBSD 和 Mac 平台进行 USB 和蓝牙的 hid 类设备通信,非常简单实用。
文件连接可以去github查看:https://github.com/libusb/hidapi/tree/hidapi-0.12.0

打开window文件夹里的文件就是源码,里面包含的lib、dll为32位,需要64位的需要自己编译。
或者直接下载已经编译好的:https://download.csdn.net/download/cao_jie_xin/86827407
新建一个控制台程序,在配置类型中改成dll,把源代码内容拷贝过来重新编译生成dll.

//非必要函数,调用hid_enumerate()和hid_open()都会自动调用它
hid_init(void);
//释放hidapi
hid_exit(void);
//传入vid和pid可以遍历该id下的所有接口号地址等数据并形成链表返回
//若是vid和pid=0则遍历所有hid usb数据并形成链表返回
hid_enumerate(unsigned short vendor_id, unsigned short product_id);
//指定vid和pid打开,最后一个参数可以是NULL,返回句柄(不建议使用)
//该操作使用默认端口,不能自主选择
hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
//指定路径打开usb设备,返回句柄(建议使用)
hid_open_path(const char *path);
//释放链表,参数为hid_enumerate()返回的链表
hid_free_enumeration(struct hid_device_info *devs);
//写操作
hid_write(hid_device *dev, const unsigned char *data, size_t length);
//设定阻塞读与非阻塞读 0为阻塞 1为非阻塞
hid_set_nonblocking(hid_device *dev, int nonblock);
//读操作
hid_read(hid_device *dev, unsigned char *data, size_t length);
结构如下:
/** hidapi信息结构 */
struct hid_device_info {/** 设备路径 */char *path;/** VID */unsigned short vendor_id;/** PID */unsigned short product_id;/** 序列号 */wchar_t *serial_number;/** 以二进制编码的十进制表示的设备版本号 */unsigned short release_number;/** 制造商字符串 */wchar_t *manufacturer_string;/** 产品字符串 */wchar_t *product_string;/** 此设备/界面的使用页面(仅限Windows/Mac/hidraw) */unsigned short usage_page;/** 此设备/接口的用法(仅限Windows/Mac/hidraw) */unsigned short usage;/** 设备接口号 */int interface_number;/** 连接到下一个 */struct hid_device_info *next;
};
在windows下打开usb应该是需要root权限,建议用管理员模式打开QT不然容易异常退出。
两种方式:
1.自己写的下位机VID和PID自己决定。
2.使用Bus Hound获取,具体使用方式就不说了。

int USB::hid_print(void)
{hid_device_info *hid_info;//usb链表/*打开指定VID PID设备*/hid_info = hid_enumerate(0x5511,0x0011);/*遍历所有信息并打印*/for(;hid_info != nullptr;hid_info = hid_info->next){qDebug("设备接口号:%d",hid_info->interface_number);qDebug("厂商字符串:%ls",hid_info->manufacturer_string);qDebug("设备字符串:%ls",hid_info->product_string);qDebug("版本号:%d",hid_info->release_number);qDebug("地址:%s",hid_info->path);}/*释放链表*/hid_free_enumeration(hid_info);return 0;
}
运行后可以看到以下数据:

和Bus Hound读取到的对比一致,证明读取每出错。

在第五点中我们已经遍历了该USB设备内的所有端口,这些端口被保存在上述USB链表内,因此我们需要找到我们要操作的端口号,并通过hid_open_path()这个函数来打开,这样才能指定端口收发数据。
#define TX_MAXSIZE 64;
int USB::usb_write(void)
{int res;uint8_t buf[TX_MAXSIZE + 1];hid_device *handle;//usb句柄hid_device_info *hid_info;//usb链表/*打开指定VID PID设备*/hid_info = hid_enumerate(0x5511,0x0011);for(;hid_info != nullptr;hid_info = hid_info->next){if(hid_info->interface_number == 2)//接口匹配{qDebug("interface_number:%s",hid_info->path);//打印地址break;}}return 0;
}
int hid_write(hid_device *device, const unsigned char *data, size_t length);
在Windows中使用 hid_write()这个函数时,一定要注意!写入的数据大小一定要再加1bytes,首字节用来存放REPORT ID,并且写入 的数据大小"length"只能固定为设备对应ReportID定义的OUT报告的大小!我的下位机设定了端口收发最大字节为64,所以hid_write()发送的数组长度为64+1;读写的一些注意事项在这。
int USB::usb_write(void)
{int res;uint8_t buf[TX_MAXSIZE + 1];hid_device *handle;//usb句柄hid_device_info *hid_info;//usb链表/*打开指定VID PID设备*/hid_info = hid_enumerate(0x5511,0x0011);for(;hid_info != nullptr;hid_info = hid_info->next){if(hid_info->interface_number == 2)//接口匹配{qDebug("interface_number:%s",hid_info->path);//打印地址break;}}/*打开指定地址的设备*/handle = hid_open_path(hid_info->path);/*释放链表*/hid_free_enumeration(hid_info);buf[0] = 0x3f;//Report ID(自定义)buf[1] = 0x21;//随便一点东西buf[2] = 0x03;buf[3] = 0x00;buf[4] = 0x00;buf[5] = 0x00;res = hid_write(handle, buf, TX_MAXSIZE + 1);if(res < 0){/*返回值查看*/qDebug("err_string = %ls\n",hid_error(handle));}return 0;
}
阻塞式接收代码,不收到消息不会退出:
int USB::usb_read(void)
{int res;uint8_t buf[64+1];hid_device *handle;//usb句柄hid_device_info *hid_info;//usb链表/*打开指定VID PID设备*/hid_info = hid_enumerate(0x5511,0x0011);for(;hid_info != nullptr;hid_info = hid_info->next){if(hid_info->interface_number == 2)//接口匹配{qDebug("interface_number:%s",hid_info->path);//打印地址break;}}/*打开指定地址的设备*/handle = hid_open_path(hid_info->path);/*释放链表*/hid_free_enumeration(hid_info);res = hid_read(handle, buf, 64+1);if(res < 0){/*返回值查看*/qDebug("err_string = %ls\n",hid_error(handle));}/*阻塞*/hid_set_nonblocking(handle, 0);for(int i = 0;i<64;i++){qDebug("buf[%d]:%02x",i,buf[i]);}return 0;
}
使用Bus Hound发送指令,可以看到已经收到下位机返回的消息(当然这个接收指令后返回消息的处理是在下位机写的)

本文就是简单的hidapi收发消息操作,若有错误,欢迎指出。
参考链接:链接1
参考链接:链接2
本文需要的dll ,工具,例程,源码,开源代码,官方例程链接:https://download.csdn.net/download/cao_jie_xin/86827407