Quantex GmbH
您的地区:欧洲

PassThruLogicalConnect v5.0

在物理连接之上创建逻辑通信通道

最后修改:

说明

该函数在指定的 pass-thru 设备上创建与车辆的逻辑通信通道。逻辑通道在现有的物理通信通道之上叠加额外的协议方案。

执行成功时函数返回 STATUS_NOERROR,指针 pChannelID 所指向的值用作所创建通道的描述符(handle)。通道处于已初始化状态。

每个物理通信通道最多允许 10 个逻辑通道。创建逻辑通道不会影响物理通道及与其关联的其他逻辑通道的运行。

long PassThruLogicalConnect(
    unsigned long PhysicalChannelID,
    unsigned long ProtocolID,
    unsigned long Flags,
    void *pChannelDescriptor,
    unsigned long *pChannelID
)

通道的已初始化状态

所创建的逻辑通道具有以下初始状态:

参数

PhysicalChannelID

输入参数。调用 PassThruConnect() 时获得的物理通道标识符。

ProtocolID

输入参数。逻辑通信通道的协议标识符。它决定逻辑通道如何与车辆交互,以及 pChannelDescriptor 结构体的类型。

ProtocolID 说明
ISO15765_LOGICAL 带流控(flow control)的 ISO 15765-2

Flags

输入参数。逻辑通道的配置标志。各标志可通过 OR 组合。

标志 说明 取值
FULL_DUPLEX 通道的双工模式。仅适用于 ISO 15765。 0 = 半双工
1 = 全双工
ISO15765_ON_J1939 针对采用 29 位标识符的 ISO 15765 消息,对 CAN ID 中的优先级位(28-26)进行屏蔽(依据 ISO 15765-2 Annex A 和 SAE J1939-21)。仅适用于 ISO 15765。 0 = 关闭屏蔽(标准 ISO 15765 处理)
1 = 开启屏蔽

pChannelDescriptor

输入参数。指向描述逻辑连接端点的结构体的指针。若指针为 NULL,函数将返回 ERR_NULL_PARAMETER

pChannelID

输入参数。指向由应用程序分配的 unsigned long 变量的指针。执行成功时,该变量将包含逻辑通道标识符,供后续函数调用使用。

ISO15765_CHANNEL_DESCRIPTOR 结构体

对于协议 ISO15765_LOGICAL,使用 ISO15765_CHANNEL_DESCRIPTOR 结构体来定义逻辑连接的端点:

typedef struct {
    unsigned long LocalTxFlags;     // LocalAddress 的 TxFlags
    unsigned long RemoteTxFlags;    // RemoteAddress 的 TxFlags
    unsigned char LocalAddress[5];  // CAN ID + extended address(本地端)
    unsigned char RemoteAddress[5]; // CAN ID + extended address(远端)
} ISO15765_CHANNEL_DESCRIPTOR;

LocalTxFlags 和 RemoteTxFlags

ISO 15765 通道描述符的有效标志:

标志 适用于 说明
CAN_29BIT_ID LocalAddress, RemoteAddress 使用 29 位 CAN ID(而非 11 位)
ISO15765_ADDR_TYPE LocalAddress, RemoteAddress 使用扩展寻址(extended address)
ISO15765_FRAME_PAD RemoteAddress 发送时对 flow control 帧启用填充(padding)

LocalAddress 和 RemoteAddress 的格式

重要 地址 LocalAddressRemoteAddress 必须唯一。任何一个地址都不得与该物理通道下其他现有逻辑通道的地址相同。带扩展地址的 CAN ID 不得与不带扩展地址的 CAN ID 相同。

返回的错误码

代码 说明
STATUS_NOERROR 函数执行成功
ERR_CONCURRENT_API_CALL 在上一次 J2534 API 调用完成之前再次调用了该函数
ERR_DEVICE_NOT_OPEN 未成功调用 PassThruOpen()
ERR_INVALID_CHANNEL_ID PhysicalChannelID 取值无效
ERR_DEVICE_NOT_CONNECTED 与 pass-thru 设备的通信出错。设备已断开连接。
ERR_NOT_SUPPORTED DLL 不支持该函数
ERR_LOG_CHAN_NOT_ALLOWED 对该物理通道与 ProtocolID 的组合不允许逻辑通道
ERR_PROTOCOL_ID_NOT_SUPPORTED ProtocolID 取值不受支持(无效或未知)
ERR_FLAG_NOT_SUPPORTED Flags 取值无效、未知或不适用于当前通道
ERR_INVALID_CHANNEL_DESCRIPTOR pChannelDescriptor 结构体的一个或多个元素无效或不适用于当前通道
ERR_NULL_REQUIRED 本应为 NULL 的参数未设置为 NULL
ERR_NULL_PARAMETER 在必需指针处传入了 NULL 指针
ERR_NOT_UNIQUE 试图创建的逻辑通道其地址与现有通道的地址重复
ERR_EXCEEDED_LIMIT 超出了该物理通道的逻辑通道最大数量
ERR_FAILED 未定义的错误。请使用 PassThruGetLastError() 获取描述。

示例

C/C++ 示例

#include "j2534_dll.hpp"

unsigned long deviceID = 0;
unsigned long physicalChannelID = 0;
unsigned long logicalChannelID = 0;

// 打开设备
long ret = PassThruOpen("ScanDoc", &deviceID);
if (ret != STATUS_NOERROR) return;

// 创建 CAN 物理连接
ret = PassThruConnect(deviceID, CAN, CAN_29BIT_ID, 500000, &physicalChannelID);
if (ret != STATUS_NOERROR) {
    PassThruClose(deviceID);
    return;
}

// 配置 ISO 15765 逻辑通道描述符
ISO15765_CHANNEL_DESCRIPTOR channelDesc = {0};

// 本地地址(适配器)- 0x18DA00F1(功能寻址请求)
channelDesc.LocalTxFlags = CAN_29BIT_ID;
channelDesc.LocalAddress[0] = 0x18;
channelDesc.LocalAddress[1] = 0xDA;
channelDesc.LocalAddress[2] = 0x00;
channelDesc.LocalAddress[3] = 0xF1;

// 远端地址(ECU)- 0x18DAF100(来自 ECU 的响应)
channelDesc.RemoteTxFlags = CAN_29BIT_ID | ISO15765_FRAME_PAD;
channelDesc.RemoteAddress[0] = 0x18;
channelDesc.RemoteAddress[1] = 0xDA;
channelDesc.RemoteAddress[2] = 0xF1;
channelDesc.RemoteAddress[3] = 0x00;

// 创建逻辑通道
ret = PassThruLogicalConnect(
    physicalChannelID,
    ISO15765_LOGICAL,
    0,  // Flags: 半双工
    &channelDesc,
    &logicalChannelID
);

if (ret == STATUS_NOERROR) {
    printf("逻辑通道已创建: %lu\n", logicalChannelID);

    // 现在可以将 logicalChannelID 用于 PassThruReadMsgs/PassThruQueueMsgs

    // 关闭逻辑通道
    PassThruLogicalDisconnect(logicalChannelID);
}

// 关闭物理通道和设备
PassThruDisconnect(physicalChannelID);
PassThruClose(deviceID);

Python 示例(ctypes)

from ctypes import *

# 加载库
j2534 = cdll.LoadLibrary("libj2534_v05_00.dylib")

# 通道描述符结构体
class ISO15765_CHANNEL_DESCRIPTOR(Structure):
    _fields_ = [
        ("LocalTxFlags", c_ulong),
        ("RemoteTxFlags", c_ulong),
        ("LocalAddress", c_ubyte * 5),
        ("RemoteAddress", c_ubyte * 5)
    ]

device_id = c_ulong()
physical_channel_id = c_ulong()
logical_channel_id = c_ulong()

# 打开设备
ret = j2534.PassThruOpen(b"ScanDoc", byref(device_id))
if ret != 0:
    print(f"PassThruOpen 出错: {ret}")
    exit()

# 创建 CAN 物理连接(500 kbit/s, 29-bit ID)
CAN = 0x05
CAN_29BIT_ID = 0x100
ret = j2534.PassThruConnect(device_id, CAN, CAN_29BIT_ID, 500000, byref(physical_channel_id))
if ret != 0:
    print(f"PassThruConnect 出错: {ret}")
    j2534.PassThruClose(device_id)
    exit()

# 配置通道描述符
ISO15765_LOGICAL = 0x200
ISO15765_FRAME_PAD = 0x40

channel_desc = ISO15765_CHANNEL_DESCRIPTOR()
channel_desc.LocalTxFlags = CAN_29BIT_ID
channel_desc.LocalAddress[0] = 0x18
channel_desc.LocalAddress[1] = 0xDA
channel_desc.LocalAddress[2] = 0x00
channel_desc.LocalAddress[3] = 0xF1

channel_desc.RemoteTxFlags = CAN_29BIT_ID | ISO15765_FRAME_PAD
channel_desc.RemoteAddress[0] = 0x18
channel_desc.RemoteAddress[1] = 0xDA
channel_desc.RemoteAddress[2] = 0xF1
channel_desc.RemoteAddress[3] = 0x00

# 创建逻辑通道
ret = j2534.PassThruLogicalConnect(
    physical_channel_id,
    ISO15765_LOGICAL,
    0,
    byref(channel_desc),
    byref(logical_channel_id)
)

if ret == 0:
    print(f"逻辑通道已创建: {logical_channel_id.value}")
    # ...使用通道...
    j2534.PassThruLogicalDisconnect(logical_channel_id)
else:
    print(f"出错: {ret}")

j2534.PassThruDisconnect(physical_channel_id)
j2534.PassThruClose(device_id)

相关函数