You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
5.1 KiB
166 lines
5.1 KiB
#include "waveshare_can.hpp"
|
|
|
|
#include "libzqt\zexception.hpp"
|
|
#include "logger.hpp"
|
|
|
|
using namespace iflytop;
|
|
using namespace std;
|
|
#define CANUSB_TTY_BAUD_RATE_DEFAULT 2000000
|
|
|
|
#define TAG "WaveshareCan"
|
|
|
|
static int generate_checksum(const unsigned char* data, int data_len) {
|
|
int i, checksum;
|
|
|
|
checksum = 0;
|
|
for (i = 0; i < data_len; i++) {
|
|
checksum += data[i];
|
|
}
|
|
|
|
return checksum & 0xff;
|
|
}
|
|
|
|
static bool isHeader(uint8_t* data) {
|
|
if (data[0] == 0xAA && data[1] == 0x55) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool WaveshareCan::init(IDataChannel* ch, frame_callback_t framecb) {
|
|
m_frame_callback = framecb;
|
|
m_ch = ch;
|
|
|
|
m_ch->regRxListener([this](uint8_t* data, size_t len) {
|
|
{
|
|
lock_guard<mutex> lock(lock_);
|
|
if (len + m_rxlen > sizeof(m_rxcache)) {
|
|
m_rxlen = 0;
|
|
}
|
|
memcpy(m_rxcache + m_rxlen, data, len);
|
|
m_rxlen += len;
|
|
}
|
|
});
|
|
m_thread.reset(new thread([this]() {
|
|
while (true) {
|
|
this_thread::sleep_for(chrono::milliseconds(1));
|
|
|
|
{
|
|
lock_guard<mutex> lock(lock_);
|
|
// 1.找头部
|
|
int32_t headerpos = -1;
|
|
for (int32_t i = 0; i < m_rxlen - 1; i++) {
|
|
if (isHeader(m_rxcache + i)) {
|
|
headerpos = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (headerpos == -1) {
|
|
continue;
|
|
}
|
|
|
|
// 将包头移动到缓存头部
|
|
if (headerpos != 0) {
|
|
memmove(m_rxcache, m_rxcache + headerpos, m_rxlen - headerpos);
|
|
m_rxlen = m_rxlen - headerpos;
|
|
continue;
|
|
}
|
|
|
|
if (m_rxlen < 20) continue;
|
|
|
|
onReceivePacket(m_rxcache, 20);
|
|
memmove(m_rxcache, m_rxcache + 20, m_rxlen - 20);
|
|
m_rxlen = m_rxlen - 20;
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
void WaveshareCan::setCanpPrameter(CANUSB_SPEED speed, CANUSB_MODE mode, CANUSB_FRAME frame) {
|
|
int cmd_frame_len;
|
|
unsigned char cmd_frame[20];
|
|
|
|
cmd_frame_len = 0;
|
|
cmd_frame[0] = 0xaa;
|
|
cmd_frame[1] = 0x55;
|
|
cmd_frame[2] = 0x02; // 0x02:用固定20字节协议收发数据 0x12-设置用可变协议收发数据
|
|
cmd_frame[3] = speed; // speed
|
|
cmd_frame[4] = frame; // 帧类型
|
|
cmd_frame[5] = 0; /* Filter ID not handled. */
|
|
cmd_frame[6] = 0; /* Filter ID not handled. */
|
|
cmd_frame[7] = 0; /* Filter ID not handled. */
|
|
cmd_frame[8] = 0; /* Filter ID not handled. */
|
|
cmd_frame[9] = 0; /* Mask ID not handled. */
|
|
cmd_frame[10] = 0; /* Mask ID not handled. */
|
|
cmd_frame[11] = 0; /* Mask ID not handled. */
|
|
cmd_frame[12] = 0; /* Mask ID not handled. */
|
|
cmd_frame[13] = mode; // 模式
|
|
cmd_frame[14] = 0x01; // 是否自动重发
|
|
cmd_frame[15] = 0; // 占位,备用
|
|
cmd_frame[16] = 0; // 占位,备用
|
|
cmd_frame[17] = 0; // 占位,备用
|
|
cmd_frame[18] = 0; // 占位,备用
|
|
cmd_frame[19] = generate_checksum(&cmd_frame[2], 17);
|
|
|
|
if (!m_ch || !m_ch->isOpen()) {
|
|
throw zexception(ke_channel_is_close, "channel is not open");
|
|
}
|
|
m_ch->send(cmd_frame, 20);
|
|
}
|
|
|
|
bool WaveshareCan::sendframe(CANUSB_FRAME frametype, uint32_t id, unsigned char data[], int data_length_code) {
|
|
int data_frame_len = 0;
|
|
unsigned char data_frame[20] = {0x00};
|
|
waveshare_can_packet_t* packet = (waveshare_can_packet_t*)data_frame;
|
|
|
|
packet->packet_header0 = 0xaa;
|
|
packet->packet_header1 = 0x55;
|
|
packet->type = 0x01; // 数据
|
|
packet->frame_type = frametype;
|
|
packet->frame_format = 0x01; // 数据帧
|
|
packet->frame_id_data_1 = id & 0xff;
|
|
packet->frame_id_data_2 = (id >> 8) & 0xff;
|
|
packet->frame_id_data_3 = (id >> 16) & 0xff;
|
|
packet->frame_id_data_4 = (id >> 24) & 0xff;
|
|
packet->frame_data_length = data_length_code;
|
|
packet->frame_data_1 = data[0];
|
|
packet->frame_data_2 = data[1];
|
|
packet->frame_data_3 = data[2];
|
|
packet->frame_data_4 = data[3];
|
|
packet->frame_data_5 = data[4];
|
|
packet->frame_data_6 = data[5];
|
|
packet->frame_data_7 = data[6];
|
|
packet->frame_data_8 = data[7];
|
|
packet->reserve = 0;
|
|
packet->check_code = generate_checksum(&data_frame[2], 17);
|
|
|
|
if (!m_ch || !m_ch->isOpen()) {
|
|
throw zexception(ke_channel_is_close, "channel is not open");
|
|
}
|
|
|
|
ZLOGI(TAG, "tx 0x%08x, %s", id, zhex2str(data, data_length_code).c_str());
|
|
m_ch->send(data_frame, 20);
|
|
|
|
return true;
|
|
}
|
|
|
|
int WaveshareCan::onReceivePacket(uint8_t* data, size_t len) {
|
|
waveshare_can_packet_t* rxpacket = (waveshare_can_packet_t*)data;
|
|
|
|
can_rx_frame_t canframe;
|
|
canframe.dlc = rxpacket->frame_data_length;
|
|
canframe.id = rxpacket->frame_id_data_1 | ((uint32_t)rxpacket->frame_id_data_2 << 8) | ((uint32_t)rxpacket->frame_id_data_3 << 16) | ((uint32_t)rxpacket->frame_id_data_4 << 24);
|
|
|
|
canframe.data[0] = rxpacket->frame_data_1;
|
|
canframe.data[1] = rxpacket->frame_data_2;
|
|
canframe.data[2] = rxpacket->frame_data_3;
|
|
canframe.data[3] = rxpacket->frame_data_4;
|
|
canframe.data[4] = rxpacket->frame_data_5;
|
|
canframe.data[5] = rxpacket->frame_data_6;
|
|
canframe.data[6] = rxpacket->frame_data_7;
|
|
canframe.data[7] = rxpacket->frame_data_8;
|
|
|
|
if (m_frame_callback) {
|
|
m_frame_callback(&canframe);
|
|
}
|
|
}
|