Kvaser、C++、Qt编写监控界面(三)

1、在利用Python和Kvaser进行二次开发时,Kvaser官方提供了可以解析原始CAN报文的Python模块 canlib.kvadblib,使用方法如下:

	// python
    mydbc = kvadblib.Dbc("mydbc.dbc")
    ...
    frame = ch.read(timeout=int(timeout * 1000))
    bmsg = db.interpret(frame)
    for bsig in bmsg:
   		bsig.name    #  信号名
   		bsig.value   #  信号物理值

       但是,在利用C++进行开发时,我并没有找到可以实现对原始CAN报文进行解析的接口函数(如果您知道相应的接口,还望留言告知),所以自己写了一个。

2、解析原始CAN报文的C++类定义

// 定义原始CAN报文 (沿用Kvaser例程中的定义)
typedef struct {
  unsigned char data[8];
  unsigned int dlc;
  unsigned int flag;
  unsigned long time;
  long id;
} CanMessage;

// 定义翻译后的CAN报文
struct translatedMsg
{
    string id; // 报文的ID
    vector can_signals; // 报文中的信号名称列表
    vector values; // 与信号名称列表对应的,信号的物理值
};

// 定义DBC文件中的message信息
struct message {
    string msgName; // 报文的名称
    string ID; // 报文的ID
    vector can_signals; // 报文中的所有信号
    void reset() {
        msgName = "";
        ID = "";
        can_signals = {};
    }
};

// 定义message中的Signal
class Signal {
public:
    // Parameters
    string SigName; // 信号的名称
    string Unit; // 单位
    uint8 StartBit; // 起始bit位
    uint8 BitLength; // 长度
    bool ByteOrder; // true: @0 Motorola; false: @1 Intel
    bool ValueType; // true: + Unsigned; false: - Signed
    double Factor;
    double Offset;
    double PhyValue;
    uint RawValue;
    uint8 msb;
    uint8 lsb;
    // Functions
    // 默认构造函数
    Signal() = default;
    // 利用信号的名称、长度、起始位、byteOrder类型、信号类型(signed/unsigned)、精度、offset等构造Signal对象
    Signal(string name, uint8 length, uint8 startBit, bool byteOrder, bool valueType, double factor, double offset);
    // 给定原始data数据,翻译出Signal的物理值PhyValue
    void getPhyValue(uint8 data[8]);

private:
    // Parameters
    uint8 StartByte; // startbit所在的Byte,MsbByte或LsbByte
    uint8 MsbByte; // MSB所在的Byte
    uint8 LsbByte; // LSB所在的Byte
    uint8 MsbBit_in_byte; // msb在该Byte中的位置
    uint8 LsbBit_in_byte; // lsb在该Byte中的位置
    uint8 LSBByteBitUsed;  // msb所在Byte中,有MsbBit_in_byte个bit被该Signal占用
    uint8 MSBByteBitUsed;  // lsb所在Byte中,有LsbBit_in_byte个bit被该Signal占用
    // Functions
    void getMsbLsb();
    uint8 getByteLocation(uint8 bit);
    uint getRawValue(uint8 data[8]);
    uint8 getBit_inByte(uint8 bitLocation, uint8 byteLocation);
    uint8 getByteRaw(uint8 ByteDate, uint8 StartBit, int8 EndBit);
};

// 定义DBC类,该类可以利用给定的DBC文件,对原始的CAN报文进行解析
class DBC : public QThread  // DBC继承自QThread,以便在单独的线程中进行报文解析
{
	Q_OBJECT  // 为了使用Qt的信号和槽机制,必须在定义类的初始位置添加此语句
public:
	DBC() = default;
	DBC(string File); // File形如"D:\\mydbc.dbc"
	string file; // DBC文件的绝对路径,形如"D:\\mydbc.dbc"
	void run();
	void stopRunning();
	void getInfo(); //用于获得DBC文件的信息
	
	string file;
    vector Messages; // DBC文件中包含的所有message
    translatedMsg tMsg;
    
public slots:
	void translateRawMsg(CanMessage msg); // 槽函数,用于翻译接收到的原始CAN报文
private:
	void translate(string id, uint8 data[8], translatedMsg & tMsg); // 内部函数,被槽函数translateRawMsg调用,并将翻译后的CAN信息拷贝给tMsg。
signals:
	void sentTranslatedMsg(translatedMsg tMsg); // 该信号,负责将tMsg传递给该信号所连接的槽函数
}


你可能感兴趣的:(学习笔记,Qt)