usb 不仅仅hid通信方式,还有其余的usb通信方式,但hid的好处就是无需安装驱动,热插拔直接用,等,具体详细介绍自行百度。
下位机与上位机串口通信连接不同usb接口,避免每次自动重新配置连接的串口端口号 三种方式:
1.修改下位机程序,上位机程序不变
下位机程序输出接口改为usb虚拟串口模式,硬件外设采用usb接口,参考正点原子库函数库例程(USB虚拟串口试验),这样不论usb插哪一个接口,均为同一虚拟串口。
2.下位机硬件和程序不变,上位机采用轮询连接当前设备可用串口,连接后通信测试,测试成功代表串口正确。
3.下位机硬件加上ttl转usb芯片,程序不变,上位机添加usb设备识别,即此篇文章的目的。
qt5.7 (msvc2013 32bit)
本文介绍采用hid方式,所以提供的连接都是hid的
参考链接:https://blog.csdn.net/encourage2011/article/details/43603889
参考链接:https://www.cnblogs.com/ChYQ/p/5383828.html
下载资料链接:https://download.csdn.net/download/qq_37603131/11602565
首先是qt上位机部分,我是拿的hid无线鼠标试验的,在设备管理器找到鼠标的vid和pid
已配置设备 HID\VID_1EA7&PID_0064&Col02\6&37799645&0&0001。
代码如下。hid_read函数目前不可用,使用程序就会报异常,目前只能write和获取设备一些信息,但是无法看出来实际的效果,暂时停止进展,等待用单片机做一个串口转hid usb的出来,或者单片机直接写好usb hid 的底层驱动,在具体通信实验。
记录下当前时间:2019年8月23日12:38:58
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
#include "hidapi.h"
#define MAX_STR 255
//#pragma comment(lib, "D:/QT57/workspace/My/untitled1/hidapi.lib")
//#pragma comment(lib, "hidapi.lib")
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
int res;
unsigned char buf[128];
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
// Open the device using the VID, PID,
// and optionally the Serial number.
handle = hid_open(0x1EA7, 0x0064, NULL);
qDebug()<<"handle"<
2019年11月29日16:43:09补更新
距离发帖已经很久了,之前没能解决这个问题,这会趁着空闲,腾出时间抓紧时间又研究了一下这个,发现拿hid的鼠标键盘测试是不靠谱的,还是用了一个ch9326模块,串口转换usb,再用串口转ttl模块模仿下位机与电脑通讯,如图所示
这个每个模块,应该说是每个芯片 都有对应固定的vid和pid,我这个模块对应的id是0x1A86, 0xE010,加了一个线程专门接收usb数据,这个不像是串口有readyread这种中断机制可以调回调函数去处理,下面话不多说上代码
初始化:
hid_init();//不初始化也可以。在open里会初始化
qDebug()<start();
connect(thread1,&USB_Thread::updateString11,this,&MainWindow::updateStr);
}
发送接收:
//自动接收
void MainWindow::updateStr(QString str1)
{
if(!str1.isEmpty())
{
ui->textEdit->setText(str1);
}
}
//手动接收
void MainWindow::on_pushButton_clicked()
{
qDebug("hid read start");
int res;
QString show_text;
for(int i=0;i<32;i++)
buf_IN[i]=0x0b;
start_flag=true;
//while (start_flag) {
QCoreApplication::processEvents();
res = hid_read(handle,buf_IN,32);
for(int i = 0;i < 32;i++){
qDebug("buf[%d]:0x%02x",i,buf_IN[i]);
show_text+=tr("%1,").arg(buf_IN[i]);
}
ui->textEdit->setText(show_text);
show_text.clear();
//}
}
//手动发送
void MainWindow::on_pushButton_3_clicked()
{
int res; // 如果返回-1表示发送失败
unsigned char buf[10];
buf[0] = 0; // 这就是Report ID
buf[1] = 0x0a;
for(int i=0;i<10;i++)
buf[2+i] = i;
//QCoreApplication::processEvents();
res = hid_write(handle, buf, 33);//此处必须是33或这大于一些的数字,不知为什么
qDebug()<
线程:
void USB_Thread::run()
{
unsigned char rbuf[32];
QString str;
while (1)
{
if(isStop)
return;
for(int i=0;i<32;i++)
rbuf[i]=0x0b;
hid_read(handle,rbuf,32);//读一包数据,判断是否有数据进来
sleep(1);//此处延时不可省略,否则接收数据不完全
if(rbuf[0]!=0x0b&&rbuf[31]!=0x0b){//判断包头包尾是否自己写入的
while(1){
for(int i = 1;i < 32;i++){//从1开始,跳过数据长度第一位
str+=tr("%1,").arg(rbuf[i]);
}
//qDebug()<
核心的地方应该算是在线程里处理数据的地方了,在线程中,首先一直判断是否接收到数据,若接收到数据,在嵌入一层逻辑关系去判断什么时候把来的数据接收完毕,这个usb发送数据是一包一包的发送,每包发送32字节,第一字节是长度,其余31字节才是有效数据,数据不足31则补0,在读取数据前像buf里写数是为了判断是否接收到数据。理解还是很容易的,usb发送接收功能都可以实现。
经历了这么长时间的帖子,最后也算是完美收工,结贴!
在 配置过程中可能需要用到一些dll和其他的工具
资源如下
上面例程源码(win8+64 qt5.7):https://download.csdn.net/download/qq_37603131/12006089
图片中各项资源链接:https://download.csdn.net/download/qq_37603131/12008565