基于Vector硬件驱动的数据采集工具软件
数据采集工具软件(1.0)
数据采集工具软件可以采集视频数据、CAN/CAN-FD数据以及以太网数据,可实现如下功能:
- 同时可以支持8路CAN/CAN-FD通道,4路视频通道和2路以太网通道。
- 支持数据的保存。视频数据保存为avi格式;其他数据为blf格式。
- 支持dbc的挂载及解析。
- 支持CAN/CAN-FD通道波特率及类型的选取。
- 支持在线查看video数据以及CAN/CAN-FD及ETH数据及解析。
- 支持采集数据的同步
硬件(驱动)依赖
- vector硬件盒子(case),有无license都行;
- vector硬件驱动,所使用硬件盒子的驱动。
- pcap驱动。
开发环境
Qt 5.14.2 + windows 10
功能介绍
数据采集工具软件主界面中,整体功能模块被分为四个区域,分别为Camera视频流显示区、CAN/CAN-FD/Eth数据显示区、控制区和状态区。
控制区
该区域各个控制按键的功能从左至右依次如下:
- 硬件初始化按键。初始化Vector硬件设备。
- 设置按键。配置CAN/CAN-FD波特率、database加载/删除、保存文件的配置等信息。
- 观测按键。让工具run起来,但是不保存数据。
- 停止观测按键。停止观测。
- log按键。开始/结束保存数据。
- 时间戳。保存数据的时间长度,仅在开始log数据时非00:00:00.
- 通道映射。配置各通道的映射关系。CAN/CAN-FD、Eth、Camera通道的选取都在此界面进行配置。
- Vector Hardware按键。打开Vector通道映射平台。
状态栏
状态栏的目的是输出当前系统的状态,最主要的状态为程序运行模式。观测模式和log模式。
当点击log按键后,会进入保存文件模式。状态区将变为红色,且状态区左侧会显示Recording…的提示信息,且时间将开始非00:00:00.
当点击观测按键后,会进入观测模式。该模式下状态区将会变为蓝色,且状态区左侧会显示Measuring…的提示信息。
CAN/CAN-FD/Ethernet数据显示区
数据显示区支持8路CAN/CAN-FD通道显示和2路Ethernet通道显示。在配置好CAN/CAN-FD类型及波特率后,紧接着配置好硬件信息的映射关系。点击观测按键或log按键既可以查看所配置通道的数据信息。
CAN/CAN-FD数据显示区同一个ID仅显示一次,若有新的数据则会更新同一ID的数据。显示信息包含时间戳、ID、Message名字、DLC、CAN/CAN-FD数据和Signals数据解析(挂载dbc情况下)。
Ethernet数据显示区最多显示1000条网络数据。超过1000条则会删除最老的数据。包含时间戳、发送端IP、目的地IP、协议、数据长度等提示信息。
Camera视频显示区
目前Camera数据显示区最多支持4路摄像头的显示。可以在通道映射界面中选择要打开的摄像头。在点击OK之后就会打开所想打开的摄像头硬件设备,同时在所打开的摄像头显示区后显示该Camera的名字。单击观测或log按键时将输出视频流。
关键函数及结构体
CAN
struct s_xl_can_msg { /* 32 Bytes */
unsigned long id;
unsigned short flags;
unsigned short dlc;
XLuint64 res1;
unsigned char data [MAX_MSG_LEN];
XLuint64 res2;
};
union s_xl_tag_data {
struct s_xl_can_msg msg;
struct s_xl_chip_state chipState;
union s_xl_lin_msg_api linMsgApi;
struct s_xl_sync_pulse syncPulse;
struct s_xl_daio_data daioData;
struct s_xl_transceiver transceiver;
struct s_xl_daio_piggy_data daioPiggyData;
};
struct s_xl_event {
XLeventTag tag; // 1
unsigned char chanIndex; // 1
unsigned short transId; // 2
unsigned short portHandle; // 2 internal use only !!!!
unsigned char flags; // 1 (e.g. XL_EVENT_FLAG_OVERRUN)
unsigned char reserved; // 1
XLuint64 timeStamp; // 8
union s_xl_tag_data tagData; // 32 Bytes
};
xlReceive(XLportHandle portHandle, unsigned int *pEventCount, XLevent *pEvents);
@ parameter 1:使能通道的句柄
@ parameter 2:值始终为1.
@ parameter 3:结构体指针,用于填充can报文数据
#use example
XLstatus xlStatus = XL_ERROR;
XLevent xlEvent;
uint32_t msg_rx = 1;
xlStatus = xlReceive(xlPortHandle, &msg_rx, &xlEvent);
CAN-FD
typedef struct {
unsigned int canId;
unsigned int msgFlags;
unsigned int crc;
unsigned char reserved1[12];
unsigned short totalBitCnt;
unsigned char dlc;
unsigned char reserved[5];
unsigned char data[XL_CAN_MAX_DATA_LEN];
} XL_CAN_EV_RX_MSG;
typedef struct {
unsigned int size; // 4 - overall size of the complete event
unsigned short tag; // 2 - type of the event
unsigned short channelIndex; // 2
unsigned int userHandle; // 4 (lower 12 bit available for CAN)
unsigned short flagsChip; // 2 queue overflow (upper 8bit)
unsigned short reserved0; // 2
XLuint64 reserved1; // 8
XLuint64 timeStampSync; // 8 - timestamp which is synchronized by the driver
union {
unsigned char raw[XL_CANFD_MAX_EVENT_SIZE - XL_CANFD_RX_EVENT_HEADER_SIZE];
XL_CAN_EV_RX_MSG canRxOkMsg;
XL_CAN_EV_RX_MSG canTxOkMsg;
XL_CAN_EV_TX_REQUEST canTxRequest;
XL_CAN_EV_ERROR canError;
XL_CAN_EV_CHIP_STATE canChipState;
XL_CAN_EV_SYNC_PULSE canSyncPulse;
} tagData;
} XLcanRxEvent;
xlCanReceive(XLportHandle portHandle, XLcanRxEvent* pXlCanRxEvt);
@ parameter 1:使能通道的句柄
@ parameter 2:结构体指针,用于填充can-fd报文数据.
Ethernet
以太网数据的获取采用pcap库进行操作。关键函数如下:
1.获取PC上的网络适配器信息
typedef struct pcap_if pcap_if_t;
/*
* Item in a list of interfaces.
*/
struct pcap_if {
struct pcap_if *next;
char *name; /* name to hand to "pcap_open_live()" */
char *description; /* textual description of interface, or NULL */
struct pcap_addr *addresses;
bpf_u_int32 flags; /* PCAP_IF_ interface flags */
};
int pcap_findalldevs(pcap_if_t **, char *);
# use example
pcap_if_t *alldevs;
pcap_if_t *dev;
char errbuf[PCAP_ERRBUF_SIZE+1];
if(pcap_findalldevs(&alldevs, errbuf) == -1){
exit(1);
}
for(dev=alldevs; dev; dev=dev->next)
{
std::cout << dev->name << " " << dev->description << std::endl;
}
pcap_freealldevs(alldevs);
2.打开所选择的网络适配器
pcap_t *pcap_open_live(const char *, int, int, int, char *);
@ return: 打开网络适配器的句柄。
@ parameter 1:所要打开网络适配器的名字,struct pcap_if {***}里的name。
@ parameter 2:要捕获的最大字节数。在大多数网络中,值65535足以捕获数据包中可用的所有数据。
@ parameter 3:是否将接口设置为混杂模式。
@ parameter 4:超时时间。
@ parameter 5:错误或警告文本
#use example
char errbuf[PCAP_ERRBUF_SIZE];
adhandle = pcap_open_live(if_info.at(adapter_index).name, 65536, 1, 1000, errbuf);
if(adhandle != NULL){
}else{
std::cerr << "Unable to open the adapter. " << std::endl;
}
3.抓包
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length of this packet (off wire) */
};
int pcap_next_ex(pcap_t* p,struct pcap_pkthdr** pkt_header,const u_char** pkt_data);
@ parameter 1:打开网络适配器的句柄
@ parameter 2:报文头
@ parameter 3:报文内容数据
#use example
struct pcap_pkthdr *header;
const u_char *pkt_data;
pcap_next_ex(adhandle, &header, &pkt_data);