2017-09-26 43 views
-2

使用CAN通信和DBC作为数据库,有两种不同的方式将整数信号编码为64位(8字节)消息数据:Intel和Motorola。
要将8字节的消息数据转换为不同的信号,我首先要使用位掩码来“范围”仅有趣的位,然后进行一些移位操作以获取信号所代表的数字。
在这里,我只对位掩码的生成感兴趣:
英特尔(也被称为little-endian)是非常直接的:你把startbit和迭代到startBit + length设置64位掩码中的每一位为1,你来了:CAN消息上的位掩码算法

uint64_t generateBitmask(Signal* signal) { 
    uint64_t bitmask = 0; 
    uint64_t one = 1; 
    int startBit = signal->startbit; 
    int endBit = startBit + signal->length; 

    if(signal->byteOrder == INTEL) { 
     for(int i = startBit; i < endBit; ++i) 
     { 
      bitmask |= (one << i); 
     } 
    } 
    return bitmask; 
} 

与摩托罗拉(大端)的数字是一个比较复杂:
因为字节顺序(不是bitorder)被交换时,(根据指数)最低字节可能包含“缺口“,而最高(索引)字节可能在字节的低端有一个”间隙“(见图中的信号MOTO_20;位22/23和32/33不是t的一部分)他表示,虽然他们是由位的sourrounded)。

我正在寻找一种方法来计算此位掩码根据相应信号的起始位和长度。请在下面的图片中找到两个基于摩托罗拉信号放置在CAN帧中的示例。开始位和长度在图像下给出。

位掩码应该对应于使用dbc的CAN总线消息布局的样子(以图像为例):图像中标记的信号的每个位都应为1:
示例MOTO_20:00000000 00000000 00000000 11111000 11111111 01111111 00000000 00000000
例如MOTO_16:00000000 00000000 00000000 00000000 00000000 00000000 11111111 11111111
信号MOTO_20已起始位34和长度为20
信号MOTO_16已起始位8和长度16

Message Layout

+0

你要我们写代码的吗? –

+0

这里有什么问题? – scohe001

+0

@IlyaBursov不,但我想要一个关于如何用高效而优雅的算法来解决这个问题的问题。我试了一整天,每次我最终都有多个if/else子句仍然缺少一个我没有涉及的特殊情况 – mxcd

回答

-1

我想通了专注于位域范围内形成了“缺口”,只有把一1的结果时,有没有差距:

uint64_t generateBitmask(int startBit, int length) { 
    uint64_t result = 0; 
    int startByte = startBit/8; 
    int byteLength = length % 8 == 0 ? length/8 : length/8 + 1; 
    int lowerGapStart = startBit % 8; 
    int upperGapStart = (7 + (length - ((byteLength * 8) - (lowerGapStart)))) % 8; 

    for (int i = startByte; i > startByte - byteLength; --i) { 
     for (int j = 0; j < 8; ++j) { 
      if (i == startByte && j < lowerGapStart || 
       i == startByte - byteLength + 1 && j > upperGapStart) { 
       continue; 
      } else { 
       bitmask |= (one << (i * 8) + j); 
      } 
     } 
    } 
    return result; 
}