CAN总线Payload和SignalValues互转

242 阅读3分钟

帧数据结构

Frame = {
    "Id": 0x21,
    "Dlc": 8,
    "Byte_Order": "Intel",  # Intel或Motorola
    "Signals": [
        {"StartBit": 0, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff, "Name": "信号1", "offset": 0, "factor": 1},  # byte 0
        {"StartBit": 8, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x01, "Name": "信号2", "offset": 0, "factor": 1},  # byte 1
        {"StartBit": 16, "BitLen": 10, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x0a, "Name": "信号3", "offset": 0, "factor": 1},  # byte2
        {"StartBit": 32, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xfe, "Name": "信号4", "offset": 0, "factor": 1},  # byte4
        {"StartBit": 40, "BitLen": 10, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff + 1, "Name": "信号5", "offset": 0, "factor": 1}
    ]
}

根据信号值(offset factor)计算物理值

# 物理值计算
physical_value = 0xff
Offset = 0
Factor = 10
raw_value = (physical_value - Offset) / Factor
physical_value = (raw_value*Factor)+Offset
print("车速物理值为:", raw_value)
print("车速信号值为:", physical_value)

根据ByteOrder生成和转换信号值

  • CAN ByteOrder Intel或Motorola,
  • 代表信号从start_bit开始正序还是反序修改数据。
  • Intel是正序,Motorola是反序。
  • 例如signal的start_bit=62,长度12
    • ByteOrder=Intel则跨byte的bit值依次是[62-71]

    • ByteOrder=Motorola跨Byte的bit值次序是[62-53]

根据信号获取payload值

  • python版本
# 根据信号获取payload值

def f2b(dlc):
    # 转换成二进制数据
    fb = {}
    for i in range(0, dlc * 8):
        fb[i] = 0
    return fb


def iv2b(value):
    # 根据信号给的值做的转换
    value = bin(value)[2:]
    value = [int(i) for i in list(value)]
    value = value[::-1]
    print(value)
    return value


def e2i(dlc, value):
    result = []
    for i in range(dlc):
        data = str(value[i * 8 + 7]) + str(value[i * 8 + 6]) + str(value[i * 8 + 5]) + str(value[i * 8 + 4]) + str(
            value[i * 8 + 3]) + str(value[i * 8 + 2]) + str(value[i * 8 + 1]) + str(value[i * 8])
        data = int(data, 2)
        result.append(data)
    return result


def get_payload(frame):
    dlc = frame.get("Dlc")
    signals = frame.get("Signals")
    fb = f2b(dlc)
    for sig in signals:
        start_bit = sig.get("StartBit")
        bit_len = sig.get("BitLen")
        initial_value = sig.get("Initiavalue")
        ib = iv2b(initial_value)
        for bit_id in ib:
            fb[start_bit] = bit_id
            start_bit += 1
    print(fb)
    payload = e2i(dlc, fb)
    print("发送的frame数据为:", payload)
    return payload


def get_singles(frame_id):
    pass


Frame = {
    "Id": 0x21,
    "Dlc": 8,
    "Signals": [
        {"StartBit": 0, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff},  # byte 0
        {"StartBit": 8, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x01},  # byte 1
        {"StartBit": 16, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x0a},  # byte2
        {"StartBit": 32, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xfe},  # byte4
        {"StartBit": 40, "BitLen": 10, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff + 1},
        # byte5+6 应该是第9位是1,也就是byte6=1
        ##最后结果[0xff, 0x01, 0x0a, 0x00, 0xfe, 0x00, 0x01, 0x00]
        ##      [255, 1, 10, 0, 254, 0, 1, 0]
    ]
}

if __name__ == '__main__':
    get_payload(Frame)
    Id = 0x21
    # get_singles(frame_id=Id)
    # iv2b(lens=8, value=0xa)

# [0xff, 0x01, 0x0a, 0x00, 0xfe, 0x00, 0x01, 0x00]
# [255, 1, 10, 0, 254, 0, 1, 0]

根据payload获取信号值

  • python版本
# 根据payload获取信号值

def f2b(dlc):
    # 转换成二进制数据
    fb = {}
    for i in range(0, dlc * 8):
        fb[i] = 0
    return fb


def iv2b(value):
    # 根据信号给的值做的转换
    value = bin(value)[2:]
    value = [int(i) for i in list(value)]
    value = value[::-1]
    print(value)
    return value


def e2i(dlc, value):
    result = []
    for i in range(dlc):
        data = str(value[i * 8 + 7]) + str(value[i * 8 + 6]) + str(value[i * 8 + 5]) + str(value[i * 8 + 4]) + str(
            value[i * 8 + 3]) + str(value[i * 8 + 2]) + str(value[i * 8 + 1]) + str(value[i * 8])
        data = int(data, 2)
        result.append(data)
    return result


def get_payload(frame):
    dlc = frame.get("Dlc")
    signals = frame.get("Signals")
    fb = f2b(dlc)
    for sig in signals:
        start_bit = sig.get("StartBit")
        bit_len = sig.get("BitLen")
        initial_value = sig.get("Initiavalue")
        ib = iv2b(initial_value)
        for bit_id in ib:
            fb[start_bit] = bit_id
            start_bit += 1
    print(fb)
    payload = e2i(dlc, fb)
    print("发送的frame数据为:", payload)
    return payload


def get_singles(frame_id, payload):
    # 省略从frame_id获取frame的过程
    frame = ""
    for fm in frames:
        if fm.get("Id") == frame_id:
            frame = fm
            break
    signals = frame.get("Signals")
    print(f"signals is:", signals)
    bit_dict = {}
    for i in range(0, len(payload)):
        data = [int(i) for i in (bin(payload[i])[2:])]
        data = data[::-1]
        if len(data) < 8:
            data = data + [0 for x in range(0, 8 - len(data))]
        bit_dict[i * 8] = data[0]
        bit_dict[i * 8 + 1] = data[1]
        bit_dict[i * 8 + 2] = data[2]
        bit_dict[i * 8 + 3] = data[3]
        bit_dict[i * 8 + 4] = data[4]
        bit_dict[i * 8 + 5] = data[5]
        bit_dict[i * 8 + 6] = data[6]
        bit_dict[i * 8 + 7] = data[7]
    print(f"bit dict is:{bit_dict}")
    for sig in signals:
        start_bit = sig.get("StartBit")
        bit_len = sig.get("BitLen")
        bit_str = ""
        for i in range(start_bit, start_bit + bit_len):
            bit_str += str(bit_dict[i])
        value = int(bit_str[::-1], 2)
        print(f"信号{sig.get('Name')}的值为: ", value)
        initial_value = sig.get("Initiavalue")
    pass


Frame = {
    "Id": 0x21,
    "Dlc": 8,
    "Byte_Order": "Intel",  # Intel或Motorola
    "Signals": [
        {"StartBit": 0, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff, "Name": "信号1", "offset": 0, "factor": 1},  # byte 0
        {"StartBit": 8, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x01, "Name": "信号2", "offset": 0, "factor": 1},  # byte 1
        {"StartBit": 16, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x0a, "Name": "信号3", "offset": 0, "factor": 1},  # byte2
        {"StartBit": 32, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xfe, "Name": "信号4", "offset": 0, "factor": 1},  # byte4
        {"StartBit": 40, "BitLen": 10, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff + 1, "Name": "信号5", "offset": 0, "factor": 1},
        # byte5+6 应该是第9位是1,也就是byte6=1
        ##最后结果[0xff, 0x01, 0x0a, 0x00, 0xfe, 0x00, 0x01, 0x00]
        ##      [255, 1, 10, 0, 254, 0, 1, 0]
    ]
}
Frame1 = {
    "Id": 0xa,
    "Dlc": 8,
    "Signals": [
        {"StartBit": 0, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff},  # byte 0
        {"StartBit": 8, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x01},  # byte 1
        {"StartBit": 16, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0x0b},  # byte2
        {"StartBit": 32, "BitLen": 8, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xfe},  # byte4
        {"StartBit": 40, "BitLen": 10, "Minimum": 0, "Maximum": 10, "Initiavalue": 0xff + 1},
        # byte5+6 应该是第9位是1,也就是byte6=1
        ##最后结果[0xff, 0x01, 0x0a, 0x00, 0xfe, 0x00, 0x01, 0x00]
        ##      [255, 1, 10, 0, 254, 0, 1, 0]
    ]
}

frames = [Frame, Frame1]

if __name__ == '__main__':
    # get_payload(Frame) # 发送数据验证
    Id = 0x21
    get_singles(frame_id=Id, payload=[0xff, 0x01, 0x0a, 0x00, 0xfe, 0x00, 0x01, 0x00])

# [0xff, 0x01, 0x0a, 0x00, 0xfe, 0x00, 0x01, 0x00]
# [255, 1, 10, 0, 254, 0, 1, 0]

#
# signals is: [{'StartBit': 0, 'BitLen': 8, 'Minimum': 0, 'Maximum': 10, 'Initiavalue': 255, 'Name': '信号1'}, {'StartBit': 8, 'BitLen': 8, 'Minimum': 0, 'Maximum': 10, 'Initiavalue': 1, 'Name': '信号2'}, {'StartBit': 16, 'BitLen': 8, 'Minimum': 0, 'Maximum': 10, 'Initiavalue': 10, 'Name': '信号3'}, {'StartBit': 32, 'BitLen': 8, 'Minimum': 0, 'Maximum': 10, 'Initiavalue': 254, 'Name': '信号4'}, {'StartBit': 40, 'BitLen': 10, 'Minimum': 0, 'Maximum': 10, 'Initiavalue': 256, 'Name': '信号5'}]
# bit dict is:{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 0, 17: 1, 18: 0, 19: 1, 20: 0, 21: 0, 22: 0, 23: 0, 24: 0, 25: 0, 26: 0, 27: 0, 28: 0, 29: 0, 30: 0, 31: 0, 32: 0, 33: 1, 34: 1, 35: 1, 36: 1, 37: 1, 38: 1, 39: 1, 40: 0, 41: 0, 42: 0, 43: 0, 44: 0, 45: 0, 46: 0, 47: 0, 48: 1, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0, 58: 0, 59: 0, 60: 0, 61: 0, 62: 0, 63: 0}
# 信号信号1的值为:  255
# 信号信号2的值为:  1
# 信号信号3的值为:  10
# 信号信号4的值为:  254
# 信号信号5的值为:  256

C#版本payload和信号值signalValues互转

using DbcParserLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SolarTest.Database
{
    public class FramePayload
    {
        public Dictionary<ushort, byte> F2b(ushort dlc)
        {
            Dictionary<ushort, byte> frame_dict = new Dictionary<ushort, byte>();
            for (ushort key = 0; key < dlc*8; key++)
            {
                frame_dict[key] = 0;
            }
            return frame_dict;
        }
        public List<byte> Iv2b(double value)
        {
            List<byte> iv = new List<byte>();
            string vs = Convert.ToString((byte)value, 2);
//            Console.WriteLine($"vs is {vs}");
            var x = vs.ToArray().Reverse();
            foreach (var v in x)
            {
                iv.Add(byte.Parse(v.ToString()));
            }
            return iv;
        }
        public List<byte> E2i(ushort dlc, Dictionary<ushort, byte> fb)
        {
            List<byte> res = new List<byte>();
            for (ushort i = 0; i < dlc; i++)
            {
                int j = i;
                ushort key0 = (ushort)(j * 8 + 7);
                ushort key1 = (ushort)(j * 8 + 6);
                ushort key2 = (ushort)(j * 8 + 5);
                ushort key3 = (ushort)(j * 8 + 4);
                ushort key4 = (ushort)(j * 8 + 3);
                ushort key5 = (ushort)(j * 8 + 2);
                ushort key6 = (ushort)(j * 8 + 1);
                ushort key7 = (ushort)(j * 8);
//                Console.WriteLine($"i = {i}, j = {j * 8 + 7}, key7 is : {key7}");
//                Console.WriteLine($"key7 value is : {fb[key7]}");
//                Console.WriteLine($"key63 value is : {fb[63]}");
//                Console.WriteLine($"key0 value is : {fb[key0].ToString()}");
//                Console.WriteLine($"key0 value type is : {fb[key0].ToString().GetType()}");
//                Console.WriteLine($"key0 value type is : {fb[key0].GetType()}");
                string data = fb[key0].ToString() + fb[key1].ToString() + fb[key2].ToString() + fb[key3].ToString() + fb[key4].ToString() + fb[key5].ToString() + fb[key6].ToString() + fb[key7].ToString();
                Int32 num = Convert.ToInt32(data, 2);
                byte frame_byte = (byte)num;
                res.Add(frame_byte);
            }
//            Console.WriteLine($"frame payload is {res}");
            foreach (var i in res)
            {
                Console.WriteLine(i);
            }
            return res;
        }
        public List<byte> GetPayloadByFrame(Frame frame)
        {
            List<byte> payload = new List<byte> { };
            ushort dlc = frame.Dlc;
            List<Signal> signals = frame.Signals;
            Dictionary<ushort, byte> frame_dict = F2b(dlc);
            foreach(var sig in signals)
            {
                ushort start_bit = sig.StartBit;
                ushort bit_len = sig.BitLen;
                double initial_value = sig.InitialValue;
                List<byte> ib = Iv2b(initial_value);
                foreach(byte bit_value  in ib)
                {
                    frame_dict[start_bit] = bit_value;
                    start_bit++;
                }
            }
//            Console.WriteLine($"frame dict is{frame_dict}");
            payload = E2i(dlc, frame_dict);
            return payload;
        }
        public List<Signal> GetSignalsByPayload(Frame frame, List<byte> payload)
        {
            List<Signal> signals = frame.Signals;
            //Dictionary<ushort, byte> bit_dict = new Dictionary<ushort, byte> { };
            Dictionary<ushort, byte> bit_dict = F2b((ushort)payload.Count);
//            Console.WriteLine($"payload count is :{payload.Count}");
            for (var i = 0; i < payload.Count;i++)
            {
                List<byte> bit_list = new List<byte>();
                string bit_data = Convert.ToString(payload[i], 2).PadLeft(8, '0');
//                Console.WriteLine($"bit_data is :{bit_data}");
                var bits = bit_data.ToArray();
//                Console.WriteLine($"bits is :{bits.ToString()}");
                foreach (var bit in bits)
                {
                    if ((byte)bit == 48) {
                        bit_list.Add(0);
                    }
                    else
                    {
                        bit_list.Add(1);
                    }
                }

                var key0 = (ushort)(i * 8);
                var key1 = (ushort)(i * 8 + 1);
                var key2 = (ushort)(i * 8 + 2);
                var key3 = (ushort)(i * 8 + 3);
                var key4 = (ushort)(i * 8 + 4);
                var key5 = (ushort)(i * 8 + 5);
                var key6 = (ushort)(i * 8 + 6);
                var key7 = (ushort)(i * 8 + 7);
                bit_dict[key0] = bit_list[0];
                bit_dict[key1] = bit_list[1];
                bit_dict[key2] = bit_list[2];
                bit_dict[key3] = bit_list[3];
                bit_dict[key4] = bit_list[4];
                bit_dict[key5] = bit_list[5];
                bit_dict[key6] = bit_list[6];
                bit_dict[key7] = bit_list[7];
//                Console.WriteLine($"bit{i*8}-{i*8+7}={bit_dict[key0]};{bit_dict[key1]};{bit_dict[key2]};{bit_dict[key3]};{bit_dict[key4]};{bit_dict[key5]};{bit_dict[key6]};{bit_dict[key7]}");
            };
//            Console.WriteLine($"bit_dict is {bit_dict.Values.ToString()}");
            foreach (var sig in signals)
            {
                ushort start_bit = sig.StartBit;
                ushort bit_len = sig.BitLen;
                string bit_str = "";
                for (var i = start_bit; i < start_bit + bit_len; i++)
                {
                    bit_str += bit_dict[i].ToString();
//                    Console.WriteLine($"{i}bit_str is now: {bit_str}");
                }
//                Console.WriteLine($"bit_str is {bit_str}");
                var num = Convert.ToInt16(bit_str, 2);
                double Initiavalue = (double)num;
                sig.InitialValue = Initiavalue;
            }
            Console.WriteLine("");
            return signals;
        }
    }
}