本文提供一種可以解析CAN信號各信號值的一種方法並進行說明。
一般情況下,高端一點的設備會計算每一個信號的值,但是接受到CAN信號的報文實際上有各種情況,如何通過設定的起始位和數據長度來獲取某一信號的值,詳情請參考,本文方法比較笨拙,如有更好的辦法,歡迎指教。
假設,我們獲取到的數據長度為8byte,即DLC為8。CAN Matrix表格如下:
我們約定,一種表示信號的方式如下:
- lsb起始位
- 數據長度
按照上面的圖來說,該信號起始位為40,長度為10。所以,該信號表示值的范圍在0-1023之間,至於具體表示的物理量的含義需要有其他的文件規定。
獲取到一幀數據以后,如何通過一系列的運算來得到信號值呢?
這里提供一種思路:
- 根據起始位和長度信息確定信息跨越的byte位
- 根據起始位確定LSB所在的bit位
- 根據跨越的byte位組合為數據
- 把以上組合的數據進行位與,得到信號值。
大概分為以上的4部分,以下分別說明:
設定:lsbbit,lsbbyte,msbbyte,start,length.按照以上的例子就是:
- lsbbit = 0
- lsbbyte = 5
- msbbyte = 4
- start = 40
- length = 10
計算lsbbit:
lsbbit = start & 7
計算lsbbyte:
lsbbyte = start >> 3
計算msbbyte:
由於數據是向byte減少的方向進行的。所以:
msbbyte = lsbbyte - x
x為跨越的位數,也就是:lsbbit + length - 1所占的長度,如果大於7說明為另一行,即:
msbbyte = lsbbyte - ((lsbbit + length - 1) >> 3)
組合data:
我們知道數據介於msbbyte-lsbbyte之間,那么我們可以組合這兩個數據:
for(index = msbbyte -> (lsbbyte+1)):
data_merge += data[index] << (( lsbbyte - index ) << 3)
獲取數據value:
去尾:value = data_merge >> lsbbit
按位與:value = value & ((1 << length) - 1)
所以,最終得到的結果為篩選出來的信號值,然后根據該信號值關聯上實際的物理值,就可以得到具體的物理數據了。
代碼實現的方式有很多,大體思路為此。
很久以前寫的,今天用的時候居然發現了一個bug,所以記錄下來,表示注意。