STM32CubeMX实现STM32 USBHID双向64字节通信(Qt上位机部分)附源代码

1.软件界面

在这里插入图片描述

2.软件功能

  • 自动搜寻usbhid设备并添加到下拉列表中
  • 64字节USBHID的发送功能
  • 10ms一次的定时查询有无新的USBHID消息,并显示出来

3.程序结构

在这里插入图片描述

4.程序代码

Qt_USB-HID_timer.pro
#-------------------------------------------------
#
# Project created by QtCreator 2020-02-26T15:36:22
#
#-------------------------------------------------

QT       += core gui
QT       += serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Qt_USB-HID_demo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

LIBS += -L$$_PRO_FILE_PWD_/  -lhidapi

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "hidapi.h"
#include <QDateTime>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    QByteArray HexStringToByteArray(QString HexString);
    QString ByteArrayToHexString(QByteArray data);
    void Receive_USBHID_message();

private slots:
    void on_pushButton_detectusb_clicked();

    void on_pushButton_usblock_clicked();

    void on_comboBox_usbhid_currentTextChanged();

    void on_pushButton_ClearSend_clicked();

    void on_pushButton_ClearReceive_clicked();

    void on_checkBox_HexReceive_clicked();

    void on_checkBox_HexSend_clicked();

    void on_pushButton_HIDSend_clicked();

private:
    Ui::MainWindow *ui;
    /*usbhid*/
    hid_device *handle;
    unsigned short vendor_id;
    unsigned short product_id;
    bool USBHID_Rev_Enable;
    unsigned char usb_data[65];
};

#endif // MAINWINDOW_H

main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.setWindowTitle("USB-HID 发送与接收64Byte");
    w.show();

    return a.exec();
}

mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>
#include <QTimer>


using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->pushButton_HIDSend->setEnabled(false);
    ui->checkBox_HexReceive->setCheckState(Qt::Checked);
    ui->checkBox_HexSend->setCheckState(Qt::Checked);
    ui->checkBox_HexReceive->setEnabled(false);

    USBHID_Rev_Enable = false;

    QTimer *timer1 = new QTimer(this);
    connect(timer1, &QTimer::timeout, this, &MainWindow::Receive_USBHID_message);
    timer1->start(10);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_detectusb_clicked()
{
    hid_init();
    struct hid_device_info * P_device;

    P_device = hid_enumerate(0, 0);

    //清空usbhid设备框
    ui->comboBox_usbhid->clear();

    if(P_device != NULL)
        statusBar()->showMessage("检测到USBHID设备",3000);

    while(P_device != NULL)
    {
        ui->comboBox_usbhid->addItem(QString::fromWCharArray(P_device->product_string));
        P_device = P_device->next;
    }

    hid_free_enumeration(P_device);
    hid_exit();
}

void MainWindow::on_pushButton_usblock_clicked()
{
    char s[100];

    if(ui->pushButton_usblock->text()==QString("打开"))
    {
        hid_init();
        struct hid_device_info * P_device;

        P_device = hid_enumerate(0, 0);
        while(P_device != NULL)
        {
            if((ui->comboBox_usbhid->currentText()) == (QString::fromWCharArray(P_device->product_string)))
            {
                this->vendor_id = P_device->vendor_id;
                this->product_id = P_device->product_id;
                break;
            }
            P_device = P_device->next;
        }

        //已经获得选中项的vid&pid,释放设备链表
        hid_free_enumeration(P_device);

        this->handle = hid_open(this->vendor_id , this->product_id, NULL);

        if(NULL != this->handle)
        {
            USBHID_Rev_Enable = true;
            qDebug("成功打开vid=0x%04x,pid=0x%04x 的usbhid设备!", this->vendor_id, this->product_id);
            sprintf(s,"成功打开vid=0x%04x,pid=0x%04x 的usbhid设备!", this->vendor_id, this->product_id);
            statusBar()->showMessage(QString(s),3000);
            ui->pushButton_usblock->setText(QString("关闭"));      //usb进入打开状态

            //在界面显示vid和pid
            char s[40];
            sprintf(s,"VID:0x%04X", this->vendor_id);
            QString vid_str = s;
            ui->label_vid->setText(vid_str);
            sprintf(s,"PID:0x%04X", this->product_id);
            QString pid_str = s;
            ui->label_pid->setText(pid_str);

            //以下控件失效
            ui->pushButton_detectusb->setEnabled(false);
            ui->comboBox_usbhid->setEnabled(false);
            //以下控件使能
            ui->pushButton_HIDSend->setEnabled(true);
        }else
        {
            qDebug("打开vid=0x%04x,pid=0x%04x 的usbhid设备失败!", this->vendor_id, this->product_id);
            sprintf(s,"打开vid=0x%04x,pid=0x%04x 的usbhid设备失败!", this->vendor_id, this->product_id);
            statusBar()->showMessage(QString(s),3000);
            return;
        }
    }
    else
    {
        hid_close(this->handle);
        USBHID_Rev_Enable = false;
        qDebug("成功关闭vid=0x%04x,pid=0x%04x 的usbhid设备!", this->vendor_id, this->product_id);
        sprintf(s,"成功关闭vid=0x%04x,pid=0x%04x 的usbhid设备!", this->vendor_id, this->product_id);
        statusBar()->showMessage(QString(s),3000);

        hid_exit();
        ui->pushButton_usblock->setText(QString("打开"));      //usb进入关闭状态

        QString vid_str = "VID:";
        QString pid_str = "PID:";
        ui->label_vid->setText(vid_str);
        ui->label_pid->setText(pid_str);

        //以下控件使能
        ui->pushButton_detectusb->setEnabled(true);
        ui->comboBox_usbhid->setEnabled(true);
        //以下控件失效
        ui->pushButton_HIDSend->setEnabled(false);
    }
}

void MainWindow::on_comboBox_usbhid_currentTextChanged()
{
    hid_init();
    struct hid_device_info * P_device;

    P_device = hid_enumerate(0, 0);
    while(P_device != NULL)
    {
        if((ui->comboBox_usbhid->currentText()) == (QString::fromWCharArray(P_device->product_string)))
        {
            this->vendor_id = P_device->vendor_id;
            this->product_id = P_device->product_id;
            break;
        }
        P_device = P_device->next;
    }

    //已经获得选中项的vid&pid,释放设备链表
    hid_free_enumeration(P_device);

    char s[100];
    sprintf(s,"VID:0x%04X", this->vendor_id);
    QString vid_str = s;
    ui->label_vid->setText(vid_str);
    sprintf(s,"PID:0x%04X", this->product_id);
    QString pid_str = s;
    ui->label_pid->setText(pid_str);

    sprintf(s,"设备属性:vid=0x%04x,pid=0x%04x", this->vendor_id, this->product_id);
    statusBar()->showMessage(QString(s),3000);
}

void MainWindow::on_pushButton_ClearSend_clicked()
{
    ui->textEdit_send->clear();
    statusBar()->showMessage("清空发送区成功",3000);
}

void MainWindow::on_pushButton_ClearReceive_clicked()
{
    ui->textEdit_receive->clear();
    statusBar()->showMessage("清空接收区成功",3000);
}

void MainWindow::on_checkBox_HexReceive_clicked()
{
    if(ui->checkBox_HexReceive->isChecked()==true)
    {
        qDebug("以16进制显示");
        statusBar()->showMessage("以16进制显示",3000);
    }else if(ui->checkBox_HexReceive->isChecked()==false)
    {
        qDebug("取消以16进制显示");
        statusBar()->showMessage("取消以16进制显示",3000);
    }
}

void MainWindow::on_checkBox_HexSend_clicked()
{
    if(ui->checkBox_HexSend->isChecked()==true)
    {
        qDebug("以16进制发送");
        statusBar()->showMessage("以16进制发送",3000);
    }else if(ui->checkBox_HexSend->isChecked()==false)
    {
        qDebug("取消以16进制发送");
        statusBar()->showMessage("取消以16进制发送",3000);
    }
}

/*
 * @breif 将16进制字符串转换为对应的字节序列
 */
QByteArray MainWindow::HexStringToByteArray(QString HexString)
{
    bool ok;
    QByteArray ret;
    HexString = HexString.trimmed();
    HexString = HexString.simplified();
    QStringList sl = HexString.split(" ");

    foreach (QString s, sl) {
        if(!s.isEmpty())
        {
            char c = s.toInt(&ok,16)&0xFF;
            if(ok){
                ret.append(c);
            }else{
                qDebug()<<"非法的16进制字符:"<<s;
                QMessageBox::warning(0,tr("错误:"),QString("非法的16进制字符: \"%1\"").arg(s));
            }
        }
    }
    //qDebug()<<ret;
    return ret;
}

/*
 * @breif 将字节序列转换为对应的16进制字符串
 */
QString MainWindow::ByteArrayToHexString(QByteArray data){
    QString ret(data.toHex().toUpper());
    int len = ret.length()/2;
    qDebug()<<len;
    for(int i=1;i<len;i++)
    {
        //qDebug()<<i;
        ret.insert(2*i+i-1," ");
    }

    return ret;
}

void MainWindow::Receive_USBHID_message()
{

    if(USBHID_Rev_Enable)
    {
        int res = hid_read_timeout(this->handle, usb_data, 64, 1);

        if(res>0)
        {
            QDateTime time = QDateTime::currentDateTime();
            QString time_qstr = time.toString("yyyy-MM-dd hh:mm:ss");

            QString qstr = "接收时间:"+time_qstr+"\r\n----------------------\r\n";


            for(int i=0; i<64; i++)
            {
                qstr += QString(QByteArray((char *)&usb_data[i],1).toHex()).toUpper();
                qstr += " ";
            }

            qstr = qstr + "\r\n\r\n" + ui->textEdit_receive->toPlainText() ;
            ui->textEdit_receive->setText(qstr);
            statusBar()->showMessage("USBHID收到新数据! "+time_qstr,3000);
        }
    }
}

void MainWindow::on_pushButton_HIDSend_clicked()
{
    unsigned char usb_data[65];
    char s[100];

    //获取界面上的数据并转换成utf8格式的字节流
    QString sendMsg = ui->textEdit_send->toPlainText();
    QByteArray data = sendMsg.toLatin1();

    //如果以16进制发送
    if(ui->checkBox_HexSend->isChecked() == true)
    {
        data = HexStringToByteArray(sendMsg);
    }

    for(int i=1; i<65; i++)
    {
        if(i<data.length()+1)
            usb_data[i]=data.data()[i-1];
        else
            usb_data[i]=0xff;
    }

    int res = hid_write(this->handle, usb_data, 65);    //至少写入64字节,协议64字节,第一个字节作废

    qDebug("写入结果res = %d", res);
    if(-1 == res)
    {
        qDebug("USBHID写入字节错误!");
        statusBar()->showMessage("USBHID写入字节错误!",3000);
        return;
    }
    else
    {
        qDebug("USBHID写入成功,实际写入了 %d 个字节!", res-1);
        sprintf(s,"USBHID写入成功,实际写入了 %d 个字节!", res-1);
        statusBar()->showMessage(QString(s),3000);
    }
}

相关链接:
1.STM32CubeMX实现STM32 USBHID双向64字节通信(下位机部分)
2.STM32CubeMX实现STM32 USBHID双向64字节通信(下位机部分)源代码
3.Qt_USB-HID_timer 源代码

猜你喜欢

转载自blog.csdn.net/u014779536/article/details/104534462