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:
189
src/can/CanMessage.cpp
Normal file
189
src/can/CanMessage.cpp
Normal 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
|
||||
Reference in New Issue
Block a user