(python)发送消息转换成Can报文格式

目录

前言

1.报文消息格式介绍

1.1 术语定义

1.2 帧类型

​编辑

2.代码格式化处理待发送的消息

2.1 单帧

2.2 首帧

2.3 连续帧


前言

        can总线通讯时,需要按照can报文格式进行消息的发送.发送的消息长度不同,格式会不一样.

下面用代码完成消息转换成报文.

1.报文消息格式介绍

1.1 术语定义

术语简写术语描述
SI  服务标识符
PCI  协议控制信息
DID  数据标识符
SF  单帧
FF  首帧
FC  流控制
CF  连续帧
FF_DL  首帧字节长度
SF_DL  单帧字节长度
BS 块大小
STmin 时间间隙
SN  连续帧编号
NRC  消极应答码
DTC  故障码
PH  物理层
PDU 协议数据单元

1.2 帧类型

 帧类型的介绍见下面链接

【车载开发系列】CAN总线通信---总线报文格式_can报文格式_进击的横打的博客-CSDN博客

2.代码格式化处理待发送的消息

2.1 单帧

发送的消息不超过7个字节.

# 单帧-SingleFrame
def func_sf_format(data):
    """
    发送数据前,添加一个字节的帧类型+数据长度
    data_new = 0{数据长度}{data_raw}
    :param data: str    '500300' -> 0{3}{500300}     500300为三个字节
    :return:
    """
    # 首字节 高4bit值 0000 是SingleFrame标志 低4bit值为DataLength
    _data_length = int(len(data) / 2)
    _data = f"0{hex(_data_length).replace('0x', '')}{data}"
    return _data

2.2 首帧

发送的消息不超过6个字节.

def get_ff_format(data):
    """

    :param data: str
    :return:
    """
    _data_length = int(len(data) / 2)
    # 数据长度 已包含 (传送数据服务请求id)
    _ff_data = f"10{hex(_data_length).replace('0x', '').zfill(2)}{data}"
    return _ff_data

2.3 连续帧

(['10', '82', '36', '01', '18', '08', '00', '20'], 'FF', '30')
[['21', '9D', '41', '00', '00', '8D', '50', '00'], 'SN', None]
[['22', '00', '79', '50', '00', '00', '00', '00'], 'SN', None]
[['23', '00', '00', '00', '00', '00', '00', '00'], 'SN', None]

当发送的消息超过6个字节时,需要用连续帧的报文格式进行发送.

注意:

2.3.1 发送多帧数据时, 报文消息体包含两类数据帧: 首帧 + 连续帧

首帧构成 数据帧类型 + 数据长度 + 服务ID + 数据块大编号(01-FF) + 消息体

连续帧构成 数据帧类型  + 数据块小编号(0-F) + 消息体

def func_mf_format(data, id):
      """
        
        :param data: str 
        :return:
        """
    data_list = re.findall(".{2}", data)
    data_group = []
    group_num = 0
    temp = []

    def get_ff_data(_data_list, _group_sn):
        if id == "36":
            # 数据长度 + 2 (传送数据服务请求id 占一个字节 + 数据块编号 占一个字节)
            _ff_data = ["10", f"{hex(len(_data_list) + 2).replace('0x', '').zfill(2)}", id, _group_sn]
        else:
            # 数据长度 已包含 (传送数据服务请求id)
            _ff_data = ["10", f"{hex(len(_data_list)).replace('0x', '').zfill(2)}"]
        # 首帧的信息由 数据帧类型+数据长度+id + (循环的次数) 剩余位置 用有效数据补
        rest_length = 8 - len(_ff_data)
        _ff_data.extend(_data_list[:rest_length])
        return (_ff_data, "FF", "30"), _data_list[rest_length:]

    def get_sn_data(_data_list, _group_sn, is_check=True):
        """
        在首帧 占用了序号0 之后,连续帧就从 1开始到 F
        :param _data_list: list 有效数据 ['00', '01', '02']
        :return:
        """
        sn_num = 1
        _sn_data_list = []
        step = 7
        for i in range(0, len(_data_list), step):
            sn = f"2{hex(sn_num).replace('0x', '')}"
            _cf_data = _data_list[i:i + step]
            _cf_data.insert(0, sn)
            # sn 最大为 f,
            _sn_data_list.append([_cf_data, "SN", None])
            if sn_num >= 15:
                sn_num = 0
            else:
                sn_num += 1
        if is_check:
            _sn_data_list[-1][-1] = "76"
        return _sn_data_list

    def _set_command(data_list, _group_sn):
        loop_data_list = []
        # 构造首帧
        ff_data, rest_data = get_ff_data(data_list, _group_sn)
        loop_data_list.append(ff_data)
        # 构造连续帧  (剩余有效数据,构造成 连续帧
        sn_data_list = get_sn_data(rest_data, _group_sn)
        loop_data_list.extend(sn_data_list)
        return loop_data_list

    command_big_list = []
    # 每128个字节(有效数据)为一组 一个小循环
    # 一个小循环分 首帧 6个 其余 122个,7个为一组, 分成9组, 不足一组用 55 补齐
    group_step = 128
    _group_num = 1
    for j in range(0, len(data_list), group_step):
        _group_sn = f"{hex(_group_num).replace('0x', '').zfill(2)}"
        temp = data_list[j:j + group_step]
        if len(temp) >= 7:
            command_list = _set_command(temp, _group_sn)
        else:
            # 少于7个 发单帧   长度增加2   服务id + 编号
            base_temp = [f"0{hex(len(temp) + 2).replace('0x', '')}", "36", _group_sn]
            base_temp.extend(temp)
            command_list = [(base_temp, "SF", "76")]
        command_big_list.extend(command_list)
        _group_num += 1
        # 分组累加到 256(FF) 时,从0开始
        if _group_num == 255:
            _group_num = 0
    return command_big_list

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Marst·Developer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值