cantools模块生成DBC文件的代码示例:
import cantools
from cantools import database
from cantools.database.can.message import Message
from cantools.database.can.signal import Signal
signals = []
# 添加信号到消息中
rpm_signal = Signal(
name='RPM',
start=0, # 信号在消息中的起始位
length=16, # 信号长度(位)
minimum=0.0, # 信号最小值
maximum=8000.0, # 信号最大值
unit='rpm', # 单位
is_signed=True, # 信号是否有符号
is_multiplexer=False, # 是否为多路复用器信号
)
signals.append(rpm_signal)
coolant_temp_signal = Signal(
name='CoolantTemp',
start=16,
length=8,
minimum=-40.0,
maximum=215.0,
unit='°C',
is_signed=True,
is_multiplexer=False,
)
signals.append(coolant_temp_signal)
# 创建一个消息对象
msg = Message(
frame_id=123, # CAN帧ID
name='EngineStatus', # 消息名称
length=8,
signals=signals,
)
db = database.Database(messages=[msg])
cantools.database.dump_file(db, 'Example.dbc')
由上述代码生成的DBC文件内容如下:
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_:
BO_ 123 EngineStatus: 8 Vector__XXX
SG_ CoolantTemp : 16|8@1- (1,0) [-40.0|215.0] "°C" Vector__XXX
SG_ RPM : 0|16@1- (1,0) [0.0|8000.0] "rpm" Vector__XXX
从上面对生成DBC文件的格式分析可知:信号的分辨率都是1,偏移量都是0。通过分析cantools包的Signal模块可以知道信号数值转换conversion取的是默认值None,当conversion为None时参与计算的self.conversion取IdentityConversion(is_float=False)。
分析IdentityConversion类可知,分辨率scale写死了取值就是1,偏移量offset也写死了取值是0。
IdentityConversion类是从cantools.database.conversion导入的,conversion模块里面封装的类都是用来定义信号的分辨率和偏移量,用来计算信号物理量到数字量数值转换的,分析conversion模块中的类发现都是继承的基类BaseConversion,可以根据定义信号的特征选择适合的转换函数定义信号的分辨率和偏移量。
我这里选择的是LinearConversion类进行信号的数值转换,在类的实例化声明分辨率和偏移量即可signal_value_conversion = LinearConversion(scale=0.5, offset=10, is_float=False),然后Signal类的实例化conversion选择这个实例化的LinearConversion类signal_value_conversion
完整代码如下:
import cantools
from cantools import database
from cantools.database.conversion import LinearConversion
from cantools.database.can.message import Message
from cantools.database.can.signal import Signal
signals = []
# 添加信号到消息中
signal_value_conversion = LinearConversion(scale=0.5, offset=10, is_float=False)
rpm_signal = Signal(
name="RPM",
start=0, # 信号在消息中的起始位
length=16, # 信号长度(位)
conversion=signal_value_conversion,
minimum=0.0, # 信号最小值
maximum=8000.0, # 信号最大值
unit="rpm", # 单位
is_signed=True, # 信号是否有符号
is_multiplexer=False, # 是否为多路复用器信号
)
signals.append(rpm_signal)
signal_value_conversion = LinearConversion(scale=0.1, offset=40, is_float=False)
coolant_temp_signal = Signal(
name="CoolantTemp",
start=16,
length=8,
conversion=signal_value_conversion,
minimum=-40.0,
maximum=215.0,
unit="°C",
is_signed=True,
is_multiplexer=False,
)
signals.append(coolant_temp_signal)
# 创建一个消息对象
msg = Message(
frame_id=123, # CAN帧ID
name="EngineStatus", # 消息名称
length=8,
signals=signals,
)
db = database.Database(messages=[msg])
cantools.database.dump_file(db, "Example.dbc")
采用上述方法,实例化LinearConversion类定义好分辨率和偏移量之后,生成的DBC文件信号格式如下,可以看出这时候分辨率和偏移量取值都是对的。