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 源代碼