CAN协议信号位-大小端学习
进入汽车行业 虽然是软件开发 但是对底层的信号传递还是很感兴趣的,深入的学习了一下CAN协议中提到的大小端内容。还挺有意思的。我抽几个信号进行学习推断。有很多信号的推断我直接附上手绘图片仅记录一下分析过程。
前提条件:
了解 DBC数据库文件 能看懂
了解 can协议大端、小端
了解 一些术语 如 信号位、起始位、高低字节、高低地址。
了解 当一个信号的数据长度超过1 个字节(8 位)或者 数据长度不超过一个字节但是采用跨字节方式实现
分两步进行:
抽取部分汽车DBC数据库文件 先进行理论推断和演示
借助 CANoe 或是 CANalyzer 进行实际的验证理论推断
我这分析 Intel 小端模式、Motorola 大端(MSB)
motorola_MSB大端 练习
我们现在获取整体一个id信号 motorola_MSB大端 练习
Dbc文件信息:
BO_ D: 8 U
llwMaxPwrCnse : 7|16@0+ (0.02,0) [0|1310.7] “kW” GW
llwMaxFbPwr : 23|16@0+ (0.02,0) [0|1310.7] “kW” GW
sAllwMaxPwrCnse : 34|11@0+ (0.01,0) [0|20] “kW” ECC,GW
yRecovModReq : 35|1@0+ (1,0) [0|1] “” ECC,GW
shDIRSigPWMPct : 55|7@0+ (1,0) [0|100] “%” GW
DIRSigPWMPeriod : 48|9@0+ (1,0) [0|500] “ms” GW
Canalyer data =
Byte0=EA
Byte1=60
Byte2=EA
Byte3=60
Byte4=E
Byte5=A4
Byte6=C1
Byte6=F3
具体单个信号解析:
BO_ D: 8 U
wMaxPwrCnse : 7|16@0+ (0.02,0) [0|1310.7] “kW” GW
BO: 8 V
sAllwMaxFbPwr : 23|16@0+ (0.02,0) [0|1310.7] “kW” GW
BO_ D: 8U
IRSigPWMPeriod : 48|9@0+ (1,0) [0|500] “ms” GW
再次举例 Motorola 大端(MSB)
示例一
信号 BDC文件中
BO_U_PSPercVld : 31|2@0+ (1,0) [0|3] “” GW
Canalyer中
Raw = 2(16进制)
Pys = 2(10进制)
Data byte3 = 80
Byte3 31位填 1 30位填0 后六位补000000
所以10000000(2进制)=80(16进制)
如下图:
信号4
DBC文件
BO_ 4: 8 U
SG_ tgyGearSig : 19|4@0+ (1,0) [0|15] “” MCU_F,MCU_
Canalyer中
Raw = a(16进制)
Pys = 无所谓(10进制)
A(16进制)=1010(2进制)
Data byte2 = a
Byte2 19位填 1 18位填 0 17位填 1 16位填 0
所以1010(2进制)=a(16进制)
如下图:
结合 这两个信号
DBC文件
SG_gGearSig : 19|4@0+ (1,0) [0|15] “” MCU_F,MCU_
SG_ htMisoper : 21|1@0+ (1,0) [0|1] “” GWCanalyer中
Data byte2 = 2a
Byte2 = 0010 1010 = 2a(16进制)
0010 = 2(16进制)
1010 = a(16进制)
信号6 找一个 跨byte的练习 这三个信号 跨byte 练习
DBC文件
BO_ U: 8
SG_DistbnRat : 45|14@0+ (0.01,0) [0|100] “” GW
Canalyer中
Raw =26ac(16进制)
Pys = 99(10进制) 因为有0.01的系数 =9900(实际物理值)
9900(10进制)=26ac(16进制)=100110 10101100(2进制)
从左往右写
26(16进制)=100110(2进制)
ac(16进制)=10101100(2进制)
所以 byte5里面写入
47=0、46=0、45=1、44=0、43=0、42=1、41=1、40=0
所以 byte6里面写入
55=1、54=0、53=1、52=0、51=1、50=1、49=0、48=0
信号7 找一个 跨byte的练习 这三个信号 跨byte 练习
DBC文件
BO_ 0D: 8
SG_ DIRSigPWMPeriod : 48|9@0+ (1,0) [0|500] “ms” GW
Canalyer中
Raw =1f3(16进制)
Pys = 499(10进制)
499(10进制)=1f3(16进制)=111110011(2进制)
从左往右写
1(16进制)=1(2进制)
F3(16进制)=11110011(2进制)
48位开头 从左往右写(手写习惯)
Byte6的48位=1
Byte7的 63位=1、62位=1、61位=1、60位=1、59位=0、58位=0、57位=1、56位=1
所以
byte6 = 1(2进制)=1(16进制)
Byte7 = 11110011(2进制)=f3(16进制)
Intel小端 模式
注意:Intel下端要注意 补位0的问题
小端 编写技巧:
从 byte高字节 开始 从左往右写
从 byte低字节 开始 从左往右写
选哪一个 哪种对选哪一种
从 byte高字节 开始 从左往右写
如:十进制 65534 = 十六进制 fffe = 二进制 11111111 11111110
Byte1 从左往右写 11111111
Byte0 从左往右写 11111110
在 canalyer data = fe ff(byte0=fe、byte1=ff)
我认为的 11111111 为信号高位、11111110为信号低位
就是 手写习惯 从左到右 按号一次写
从左往右写
但手写开始位 = 信号起始位DBC中 + 信号位长(2进制数)-1
如
DBC文件
BO_ : 8 Vector__XXX
rride_Control_Mode : 0|2@1+ (1,0) [0|3] “” Vector__XXX
uested_Speed_Control_C : 2|2@1+ (1,0) [0|3] “” Vector__XXX
ntrol_Mode_Priority : 4|2@1+ (1,0) [0|3] “” Vector__XXX
uested_Speed_Speed_Lim : 8|16@1+ (1,0) [0|65535] “” Vector__XXX
头三个总结 补位 0
verride_Control_Mode : 0|2@1+ (1,0) [0|3] “” Vector__XXX
equested_Speed_Control_C : 2|2@1+ (1,0) [0|3] “” Vector__XXX
Sontrol_Mode_Priority : 4|2@1+ (1,0) [0|3] “” Vector__XXX
verride_Control_Mode : 0|2@1+ (1,0) [0|3] “” Vector__XXX
ested_Speed_Control_C : 2|2@1+ (1,0) [0|3] “” Vector__XXX
_Mode_Priority : 4|2@1+ (1,0) [0|3] “” Vector__XXX
第四个信号开始
equested_Speed_Speed_Lim : 8|16@1+ (1,0) [0|65535] “” Vector__XXX
十个信号总结:
BO_ 21: 8 Vector__XXX
verride_Control_Mode : 0|2@1+ (1,0) [0|3] “” Vector__XXX
equested_Speed_Control_C : 2|2@1+ (1,0) [0|3] “” Vector__XXX
Sontrol_Mode_Priority : 4|2@1+ (1,0) [0|3] “” Vector__XXX
equested_Speed_Speed_Lim : 8|16@1+ (1,0) [0|65535] “” Vector__XXX
verride_Control_Mode : 0|2@1+ (1,0) [0|3] “” Vector__XXX
Raw = 3 phys=3
3(16进制)=11(2进制)
0位=1、1位=1
equested_Speed_Control_C : 2|2@1+ (1,0) [0|3] “” Vector__XXX
Raw = 2 phys=
2(16进制)=10(2进制)
2位=0、3位=1
_Mode_Priority : 4|2@1+ (1,0) [0|3] “” Vector__XXX
Raw = 1 phys=1
1(16进制)=1(2进制)
4位=1、5位=0
7、6位 补位 0
equested_Speed_Speed_Lim : 8|16@1+ (1,0) [0|65535] “” Vector__XXX
Raw = fffd phys=65533
Fffd(16进制)=1111111111111101(2进制)
23位=1、22位=1、21位=1、20位=1、19位=1、18位=1、17位=1、16位=1
15位=1、14位=1、13位=1、12位=1、11位=1、10位=1、9位=0、8位=1