2017-09-26 80 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; 
}