Initial commit: Complete USB2CAN cross-platform framework

Features:
- Cross-platform support (Windows/Linux/macOS)
- CAN and CANFD protocol support
- USB communication (WinUSB/libusb)
- Device management and configuration
- Message transmission and reception
- Filter configuration
- CMake build system
- Comprehensive examples and tests
This commit is contained in:
2025-09-11 17:56:26 +08:00
commit 81bee50cd9
37 changed files with 5536 additions and 0 deletions

189
src/can/CanMessage.cpp Normal file
View File

@@ -0,0 +1,189 @@
/**
* @file CanMessage.cpp
* @brief CAN协议层实现
*/
#include "../../include/can/CanMessage.h"
#include <cstring>
#include <iomanip>
#include <sstream>
namespace usb2can {
namespace can {
CanConfig::CanConfig()
: bitrate(500000), mode(CanMode::Normal), filterId(0), filterMask(0xFFFFFFFF) {
}
CanMessage::CanMessage()
: id(0), dlc(0), extended(false), rtr(false), timestamp(0) {
std::memset(data, 0, sizeof(data));
}
CanMessage::CanMessage(uint32_t id, const uint8_t* data, uint8_t dlc, bool extended, bool rtr)
: id(id), dlc(dlc), extended(extended), rtr(rtr), timestamp(0) {
if (data && dlc > 0) {
std::memcpy(this->data, data, std::min(static_cast<size_t>(dlc), sizeof(this->data)));
} else {
std::memset(this->data, 0, sizeof(this->data));
}
}
CanMessage::CanMessage(const CanMessage& other) {
id = other.id;
dlc = other.dlc;
extended = other.extended;
rtr = other.rtr;
timestamp = other.timestamp;
std::memcpy(data, other.data, sizeof(data));
}
CanMessage& CanMessage::operator=(const CanMessage& other) {
if (this != &other) {
id = other.id;
dlc = other.dlc;
extended = other.extended;
rtr = other.rtr;
timestamp = other.timestamp;
std::memcpy(data, other.data, sizeof(data));
}
return *this;
}
bool CanMessage::operator==(const CanMessage& other) const {
if (id != other.id || dlc != other.dlc || extended != other.extended || rtr != other.rtr) {
return false;
}
return std::memcmp(data, other.data, sizeof(data)) == 0;
}
std::string CanMessage::toString() const {
std::stringstream ss;
ss << "ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << id
<< " DLC: " << std::dec << static_cast<int>(dlc)
<< " [";
for (int i = 0; i < dlc; i++) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]);
if (i < dlc - 1) {
ss << " ";
}
}
ss << "]";
if (extended) {
ss << " Extended";
}
if (rtr) {
ss << " RTR";
}
return ss.str();
}
CanFdConfig::CanFdConfig()
: bitrate(500000), dataBitrate(2000000), mode(CanMode::Normal),
filterId(0), filterMask(0xFFFFFFFF), enableFd(true), enableBrs(true) {
}
CanFdMessage::CanFdMessage()
: id(0), dlc(0), extended(false), rtr(false), fd(false), brs(false), esi(false), timestamp(0) {
std::memset(data, 0, sizeof(data));
}
CanFdMessage::CanFdMessage(uint32_t id, const uint8_t* data, uint8_t dlc,
bool extended, bool rtr, bool fd, bool brs, bool esi)
: id(id), dlc(dlc), extended(extended), rtr(rtr), fd(fd), brs(brs), esi(esi), timestamp(0) {
if (data && dlc > 0) {
std::memcpy(this->data, data, std::min(static_cast<size_t>(dlc), sizeof(this->data)));
} else {
std::memset(this->data, 0, sizeof(this->data));
}
}
CanFdMessage::CanFdMessage(const CanFdMessage& other) {
id = other.id;
dlc = other.dlc;
extended = other.extended;
rtr = other.rtr;
fd = other.fd;
brs = other.brs;
esi = other.esi;
timestamp = other.timestamp;
std::memcpy(data, other.data, sizeof(data));
}
CanFdMessage& CanFdMessage::operator=(const CanFdMessage& other) {
if (this != &other) {
id = other.id;
dlc = other.dlc;
extended = other.extended;
rtr = other.rtr;
fd = other.fd;
brs = other.brs;
esi = other.esi;
timestamp = other.timestamp;
std::memcpy(data, other.data, sizeof(data));
}
return *this;
}
bool CanFdMessage::operator==(const CanFdMessage& other) const {
if (id != other.id || dlc != other.dlc || extended != other.extended ||
rtr != other.rtr || fd != other.fd || brs != other.brs || esi != other.esi) {
return false;
}
return std::memcmp(data, other.data, sizeof(data)) == 0;
}
std::string CanFdMessage::toString() const {
std::stringstream ss;
ss << "ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << id
<< " DLC: " << std::dec << static_cast<int>(dlc)
<< " [";
for (int i = 0; i < dlc; i++) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]);
if (i < dlc - 1) {
ss << " ";
}
}
ss << "]";
if (extended) {
ss << " Extended";
}
if (rtr) {
ss << " RTR";
}
if (fd) {
ss << " FD";
}
if (brs) {
ss << " BRS";
}
if (esi) {
ss << " ESI";
}
return ss.str();
}
CanStatus::CanStatus()
: busOff(false), errorPassive(false), errorWarning(false),
rxErrorCounter(0), txErrorCounter(0) {
}
} // namespace can
} // namespace usb2can