C++写控制台HID收发程序:
1循环查找厂商号:2E3C 产品号:5745的设备,超时3秒,超时或没找到就退出
2找到就连接
3发送Hex指令:5AA5000200A1000801FFFFFF0000DF45
4接收有超时3秒,如果收到hex:5AA5000200A10001AAC1DD0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000就退出返回0
5发送与接收可以写成一个函数
6有详细的提示
#include "./hidapi-win/include/hidapi.h" //#include 是以当前文件所在路径为当前目录
#pragma comment(lib,"./hidapi-win/x86/hidapi.lib") //#pragma comment 是以当前工程所在路径为当前目录 多线程静态MT
#include <iostream>
#include <iomanip>
#include <vector>
#include <chrono>
#include <thread>
#include <fstream>
#include <cstring>
using namespace std;
#define VID 0x2E3C
#define PID 0x5745
#define DEVICE_TYPE 0x0002
// ---------------- CRC16-CCITT ----------------
uint16_t CRC16CCITT(const uint8_t* buf, size_t len) {
uint32_t i, j;
uint16_t CrcReg = 0xFFFF;
uint16_t CurVal;
for (i = 0; i < len; i++) {
CurVal = buf[i] << 8;
for (j = 0; j < 8; j++) {
if ((short)(CrcReg ^ CurVal) < 0)
CrcReg = (CrcReg << 1) ^ 0x1021;
else
CrcReg <<= 1;
CurVal <<= 1;
}
}
return CrcReg;
}
// ---------------- 工具函数 ----------------
void print_hex(const string& prefix, const vector<uint8_t>& data) {
cout << prefix;
for (auto b : data)
cout << hex << setw(2) << setfill('0') << (int)b << " ";
cout << dec << endl;
}
// 封装发送
bool sendPacket(hid_device* dev, uint16_t cmd, const vector<uint8_t>& data) {
vector<uint8_t> pkt;
// header
pkt.push_back(0x5A);
pkt.push_back(0xA5);
// device type
pkt.push_back((DEVICE_TYPE >> 8) & 0xFF);
pkt.push_back(DEVICE_TYPE & 0xFF);
// cmd
pkt.push_back((cmd >> 8) & 0xFF);
pkt.push_back(cmd & 0xFF);
// length
uint16_t len = data.size();
pkt.push_back((len >> 8) & 0xFF);
pkt.push_back(len & 0xFF);
// data
pkt.insert(pkt.end(), data.begin(), data.end());
// crc
uint16_t crc = CRC16CCITT(pkt.data() + 2, pkt.size() - 2);
pkt.push_back((crc >> 8) & 0xFF);
pkt.push_back(crc & 0xFF);
print_hex("待发送: ", pkt);
// 拆分发送,每帧 64 字节数据
size_t offset = 0;
while (offset < pkt.size()) {
size_t chunkSize = min((size_t)64, pkt.size() - offset);
vector<uint8_t> buf(65, 0); // report ID + 64字节
memcpy(buf.data() + 1, pkt.data() + offset, chunkSize);
int res = hid_write(dev, buf.data(), buf.size());
if (res < 0) {
cerr << "发送失败: " << hid_error(dev) << endl;
return false;
}
cout << "发送帧: " << (offset / 64) + 1 << " (" << res << "字节)" << endl;
offset += chunkSize;
}
return true;
}
// 接收
bool recvPacket(hid_device* dev, vector<uint8_t>& out, int timeout_ms) {
vector<uint8_t> buf(65);
int res = hid_read_timeout(dev, buf.data(), buf.size(), timeout_ms);
if (res <= 0) {
cerr << "接收超时/错误" << endl;
return false;
}
out.assign(buf.begin(), buf.begin() + res);
print_hex("接收: ", out);
return true;
}
// ---------------- 协议功能 ----------------
string getVersion(hid_device* dev) {
sendPacket(dev, 0x0000, {});
vector<uint8_t> resp;
if (!recvPacket(dev, resp, 3000)) return "";
// 简单解析:去掉头尾,提取ASCII
uint16_t len = (resp[6] << 8) | resp[7];
string ver(resp.begin() + 8, resp.begin() + 8+len);
cout << "版本信息: " << ver << endl;
return ver;
}
bool rebootDevice(hid_device* dev) {
sendPacket(dev, 0x0005, {});
vector<uint8_t> resp;
if (!recvPacket(dev, resp, 3000)) return false;
return resp[8] == 0xAA;
}
bool setColor(hid_device* dev, uint8_t r, uint8_t g, uint8_t b, uint8_t mode, uint8_t period) {
vector<uint8_t> data = { 0x01, r, g, b, mode, period };
sendPacket(dev, 0x00A1, data);
vector<uint8_t> resp;
if (!recvPacket(dev, resp, 3000)) return false;
return resp[8] == 0xAA;
}
bool saveColor(hid_device* dev) {
sendPacket(dev, 0x00A2, {});
vector<uint8_t> resp;
if (!recvPacket(dev, resp, 3000)) return false;
return resp[8] == 0xAA;
}
bool setBrightness(hid_device* dev, uint8_t val) {
vector<uint8_t> data = { val };
sendPacket(dev, 0x00A3, data);
vector<uint8_t> resp;
if (!recvPacket(dev, resp, 3000)) return false;
return resp[8] == 0xAA;
}
bool upgradeFirmware(hid_device* dev, const string& filepath) {
ifstream fin(filepath, ios::binary);
if (!fin) {
cerr << "无法打开固件文件: " << filepath << endl;
return false;
}
vector<uint8_t> fw((istreambuf_iterator<char>(fin)), {});
size_t packet_size = 1024; // 可调,每包需4字节对齐
uint16_t total = (fw.size() + packet_size - 1) / packet_size;
cout << "固件大小=" << fw.size() << " 总包数=" << total << endl;
for (uint16_t i = 0; i < total; i++) {
size_t off = i * packet_size;
vector<uint8_t> chunk(fw.begin() + off, fw.begin() + min(off + packet_size, fw.size()));
while (chunk.size() % 4) chunk.push_back(0xFF);
vector<uint8_t> data;
data.push_back((total >> 8) & 0xFF);
data.push_back(total & 0xFF);
data.push_back((i >> 8) & 0xFF);
data.push_back(i & 0xFF);
data.push_back(0x01); // 固定类型
data.insert(data.end(), chunk.begin(), chunk.end());
cout << "发送升级包 " << i + 1 << "/" << total << endl;
sendPacket(dev, 0x0003, data);
vector<uint8_t> resp;
if (!recvPacket(dev, resp, 5000)) return false;
// 校验包号
uint16_t ack = (resp[8] << 8) | resp[9];
if (ack != i) {
cerr << "升级失败: 返回包号错误" << endl;
return false;
}
}
cout << "升级传输完成" << endl;
return true;
}
// ---------------- 主函数 ----------------
int main() {
if (hid_init()) {
cerr << "hidapi 初始化失败" << endl;
return -1;
}
cout << "查找设备..." << endl;
hid_device* dev = hid_open(VID, PID, nullptr);
if (!dev) {
cerr << "未找到设备" << endl;
return -1;
}
cout << "=== 测试获取版本 ===" << endl;
string ver = getVersion(dev);
cout << "=== 测试升级流程 ===" << endl;
cout << "重启设备进入Boot..." << endl;
if (!rebootDevice(dev)) { cerr << "重启设备失败" << endl; hid_exit(); return -1; }
hid_close(dev);
this_thread::sleep_for(chrono::seconds(3));
cout << "等待设备重连..." << endl;
dev = nullptr;
for (int i = 0; i < 10; i++) {
dev = hid_open(VID, PID, nullptr);
if (dev) break;
this_thread::sleep_for(chrono::seconds(1));
}
if (!dev) {
cerr << "重连失败" << endl;
return -1;
}
cout << "开始升级..." << endl;
if (!upgradeFirmware(dev, "Light_HID_(X001)_20250917_V1.00_upgrade.bin")) { cerr << "升级失败" << endl; /*hid_exit(); return -1;*/ }
loop:
cout << "延时10秒 等待设备进入APP..." << endl;
hid_close(dev);
this_thread::sleep_for(chrono::seconds(10));
dev = hid_open(VID, PID, nullptr);
if (dev) {
string newver = getVersion(dev);
if (newver.find("Boot") != string::npos) {
cerr << "设备仍处于Boot模式: " << newver << endl;
goto loop;
}
else {
cout << "升级成功,新版本: " << newver << endl;
}
}
cout << "=== 测试设置颜色 (红色常亮) ===" << endl;
if (!setColor(dev, 255, 0, 0, 0, 0)) { cerr << "设置颜色失败" << endl; hid_exit(); return -1; }
cout << "=== 设置亮度=80 ===" << endl;
setBrightness(dev, 80);
cout << "=== 保存设置 ===" << endl;
saveColor(dev);
hid_exit();
cout << "=== 正常退出 ===" << endl;
return 0;
}

2572

被折叠的 条评论
为什么被折叠?



