×
单片机 > 单片机程序设计 > 详情

完成stm32上HID的应用

发布时间:2020-05-30 发布时间:
|
这个是公司的项目,以前基于usb的虚拟串口来做上下位机通信,由于usb平时也就刷参数和调试之用,也不很常用,外面反应usb有时会连不上stm32控制器,心里一直认为不是大问题,后来反应的多了,就重视这个事情了,虽然usb平时不用,但是用的时候只要出现异常掉线,就再也连不上去了,特别影响用户对我们产品的信心。
 
在网上找了很多资料,到现在也只能隐约确定是stm32官方的虚拟串口库有问题,我发现不同的电源板都会影响到usb虚拟串口的枚举,于是下定决心使用其他方式来做上下位机的连接,排除了usb虚拟串口,眼前的选择只有两个
1)usblib,这个是针对usb的上位机库,可以玩很多的花样,但是需要开发者稍稍熟悉usb协议,而且这个需要在上位机上安装usb驱动程序。
2)hid设备,这个是windows自身支持的usb设备,只支持中断传输,最大的速率也就64Kb/s,上位机采用windows api编程
 
我估算了一下,hid方式满足我的要求,而且是免驱动,又不用学习usblib,所以就使用hid方式实现了usb通信。
 
hid几个注意事项:
1)对于windows API来说,读和写hid设备的数据包都是大小确定了,也就是说如果stm32 端口设备的hid属性是64的话,那么读写都是64字节的。读写的最大帧是64字节,我在代码中是基于64字节做应用层协议的。
2)hid写速度不能太快,所以我一般在写前会等待2ms左右,确保不会写出错。
确认是是HIDAPI的代码问题,我对写函数修改如下,结果就好了,可以一直写无需等待
 
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
{
DWORD bytes_written;
BOOL res;
BOOL bResult;
 
OVERLAPPED ol;
HANDLE ReportEvent;
 
ReportEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(ReportEvent);
 
memset(&ol, 0, sizeof(ol));
ol.hEvent = ReportEvent;
 
//res = WriteFile(dev->device_handle, data, 23, NULL, &ol);
res = WriteFile(dev->device_handle, data, length, NULL, &ol);
if (!res) {
 
int errcode = GetLastError();
if (errcode != ERROR_IO_PENDING) {
// WriteFile() failed. Return error.
register_error(dev, "WriteFile");
return -1;
}
}
 
bResult = WaitForSingleObject(ReportEvent, 50);
if(bResult == WAIT_TIMEOUT || bResult == WAIT_ABANDONED)
{
register_error(dev, "WriteFile");
CancelIo(&(dev->device_handle));
return -1;
}
// Wait here until the write is done. This makes
// hid_write() synchronous.
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE);
if (!res) {
// The Write operation failed.
register_error(dev, "WriteFile");
return -1;
}
 
return bytes_written;
}
3)上位机上的读写之间不能释放hid的句柄,这个我参考百合的hid教材的时候,吃了不少苦头。
4)我使用了HIDAPI这个库来操作hid设备。
 
具体细节的东西大家可以看看网上找到的hid教程,我的代码和可执行代码下载链接如下
 
http://pan.baidu.com/s/1qzTJw
注意:上面链接中的写函数我没有修正,请读者自己修改


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会