qt 之usb(hid)与单片机通信

前言:

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模块模仿下位机与电脑通讯,如图所示

qt 之usb(hid)与单片机通信_第1张图片

这个每个模块,应该说是每个芯片 都有对应固定的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和其他的工具

qt 之usb(hid)与单片机通信_第2张图片

资源如下

上面例程源码(win8+64  qt5.7):https://download.csdn.net/download/qq_37603131/12006089

图片中各项资源链接:https://download.csdn.net/download/qq_37603131/12008565

你可能感兴趣的:(qt 之usb(hid)与单片机通信)