因为维护一个比较恶心的CanIDS检测项目遇到的一个问题,写代码的人不知道去哪高就了,只能通过网络研究下.dbc大概的意思。这方面的东西大家可以自行在网上搜索,有一部分写的还算不错吧(我看了几天结合Vector Candb++工具算是基本看明白了)。如果一些基本知识不了解应该是看不懂这篇记录的
以往的项目.dbc文件比较简单而且都是intel格式的,没有被人发现问题,这个辣鸡项目却是Motorola格式。而正好被人发现获取的信号数据不对。所以就有了以下这些代码。
需要说明的是这个代码没有对一些参数做边界值和有效性判断,因为原项目代码就是这么烂,所以就假设输入数据是正确的。
In CAN databases signals can be defined with a byte order for either Motorola or Intel processors. The individual signals within a message may also have different byte orders.
Byte order for Motorola processors (Big Endian)
Byte order for Intel processors (Little Endian)
Bit significance (Bit Order)
Within a byte the significance of bits is the same in both formats:
msb: most significant bit; lsb: least significant bit
比较重要的就是 msb就是最高有效位, lsb就是最低有效位。
我处理的这个dbc文件里提供的核心数据是msb,和信号长度。
BO_ 586 CDC_CHS62: 8 CDC
SG_ EPSFailState : 0|1@0+ (1,0) [0|1] “” ADC
SG_ EPSSteerMode : 5|2@0+ (1,0) [0|3] “” ADC
SG_ EPS_LKS_CtrlAvailable : 9|2@0+ (1,0) [0|3] “” ADC
SG_ EPS_LKS_CtrlActive : 10|1@0+ (1,0) [0|1] “” ADC
SG_ EPS_LKS_AbortReq : 11|1@0+ (1,0) [0|1] “” ADC
SG_ EPS_LKS_AbortSource : 14|3@0+ (1,0) [0|7] “” ADC
SG_ EPSHandsOffDetnSts : 15|1@0+ (1,0) [0|1] “” ADC
SG_ EPS_APA_CtrlAvailable : 25|2@0+ (1,0) [0|3] “” ADC
SG_ EPSHandsOffDetnStsValid : 26|1@0+ (1,0) [0|1] “” ADC
SG_ EPS_APA_AbortReq : 27|1@0+ (1,0) [0|1] “” ADC
SG_ EPS_APA_AbortSource : 30|3@0+ (1,0) [0|7] “” ADC
SG_ EPSLKATorqOvrlDlvd : 23|9@0+ (0.1,-15) [-15|15] “Nm” ADC
SG_ StrCtlReqFdk : 34|1@0+ (1,0) [0|1] “” ADC
SG_ DriverTakeOvStrSta : 35|1@0+ (1,0) [0|1] “” ADC
SG_ EPSLKATorqOvrlDlvdValid : 36|1@0+ (1,0) [0|1] “” ADC
SG_ EPSCtrlState : 39|3@0+ (1,0) [0|7] “” ADC
SG_ EPSDrvInputTrqValue : 46|11@0+ (0.01,-10) [-10|10] “Nm” ADC
SG_ CDC_CHS62_AliveCounter : 51|4@0+ (1,0) [0|15] “” ADC
SG_ CDC_CHS62_CheckSum : 63|8@0+ (1,0) [0|255] “” ADC
获取lsb, lastByteOffset(最后一行和首字节的偏移), line(有效位所占行数);
int getLsb(int msb, int length, int* lsb, int* lastByteOffset, int* line)
{
int startBit;
if (length > 32)
return 0;
// 判断是否是多行
if ((msb % 8 + 1) >= length)
{
startBit = msb - length + 1;
*lsb = startBit;
*lastByteOffset = msb / 8;
*line = 1;
}else {
startBit = msb - msb % 8;
int tempLength = (length - (msb % 8 + 1));
// 减去第一行的长度,决定了endBit位置
if (tempLength % 8 == 0)
{
*lsb = startBit + tempLength / 8 * 8;
*line = tempLength / 8 + 1;
}else {
*lsb = startBit + 8 + tempLength / 8 * 8 + (8 - tempLength % 8);
*line = tempLength / 8 + 2;
}
*lastByteOffset = *lsb / 8;
}
return 1;
}
unsigned int getMask(int bitSize)
{
unsigned int mask = 0;
for (int i = 0; i < bitSize; i++)
{
mask = mask | (0x1 << i);
}
return mask;
}
unsigned int getSigData(unsigned char* input, int inputLength, int lsb, int lastByteOffset, int line, int msb, int length)
{
unsigned int ret = 0;
if (lastByteOffset + 1 > inputLength)
return false;
for (int i = 0; i < line; i++)
{
if (i == 0) {
ret = *(input + lastByteOffset) >> (lsb % 8);
// 存在无效位所以需要去除
if (line == 1 && length < 8 - lsb % 8) {
ret &= getMask(length);
}
}
else {
// 存在无效位所以需要去除
if ((i == line - 1) && msb % 8 < 7) {
ret += (* (input + lastByteOffset - i) & getMask(msb % 8 + 1)) << (8 - (lsb % 8) + (i - 1) * 8);
}else {
ret += *(input + lastByteOffset - i) << (8 - (lsb % 8) + (i - 1) * 8);
}
}
}
return ret;
}
unsigned char data[] = { 0x3E,0x60,0x56,0x78,0x90,0xf3,0x13,0x56 };
while (true) {
int msb, length;
std::cout << "----------------------------" << std::endl;
std::cin >> msb >> length;
int lsb, lastByteOffset, line;
int ret = getLsb(msb, length, &lsb, &lastByteOffset, &line);
if (!ret) {
std::cout << "error style\n";
return 1;
}
std::cout << lsb << std::endl;
std::cout << lastByteOffset << std::endl;
std::cout << line << std::endl;
std::cout << "*****************************"<< std::endl;
std::cout << getSigData(data, sizeof(data), lsb, lastByteOffset, line, msb, length) << std::endl;
std::cout << "----------------------------" << std::endl;
}
以上代码经过简单测试是没问题的,注意使用场景需要是Motorola格式的信号数据,并且.dbc文件需要提供的是msb。(个人猜测有可能有的.dbc文件会提供lsb+长度的数据格式)。