J2534 规范与功能说明 ›
ELM327 规范与命令说明 ›
ELM327 接口仅在 Nano ET 适配器中提供。其他 ScanDoc 适配器使用 J2534 PassThru 协议。
J2534 DLL、ELM327 和 ScanDoc 适配器固件中与集成相关的变化:新功能、协议和参数 - 附使用示例。
下载 J2534 库 2.0.0.213 - Windows x86/x64/ARM64(Windows 7 单独构建)、macOS(universal)、Linux(x64、x86、ARM、ARM64)、Android(arm64-v8a、armeabi-v7a、x86、x86_64)、iOS(XCFramework);docs/ 文件夹内为 SDK 文档(入门、API 参考、配置、错误处理、DoIP、固件更新、日志格式、Android、iOS)。静态 .a 仅随 iOS 和 Linux x64 服务器构建提供,其余平台动态加载库。
修复
CAN_PS、ISO15765_PS、J1939_PS 以及 _PS 通道的引脚设置 - 连接这三种协议时设备返回拒绝;现已与 TP2_0_PS、ISO9141_PS 同等工作。引脚设置按 J2534-2 在三处对齐标准:
PassThruConnect 阶段就已在默认引脚上启动,而 _PS 通道在 SET_CONFIG(J1962_PINS) 之前必须保持静默。现在通道只有在设置引脚后才接入总线。SET_CONFIG(J1962_PINS) 会在会话中途把活动通道切换到其他触点。按标准,每个通道的引脚只设置一次:重复调用返回 ERR_CHANNEL_IN_USE,更换引脚只能在 PassThruDisconnect 之后。ERR_PIN_NOT_SUPPORTED 拒绝。uint32_t ch;
pt_config_t pins = { J1962_PINS, 0x0000060EU }; /* 引脚 6 和 14 */
pt_config_list_t cfg = { 1, &pins };
PassThruConnect(dev, ISO15765_PS, 0, 500000, &ch);
/* 通道尚未接入总线 */
if (PassThruIoctl(ch, SET_CONFIG, &cfg, NULL) != STATUS_NOERROR) {
/* ERR_PIN_NOT_SUPPORTED - 设备布线中没有这一组合 */
}
/* 此后才可 PassThruWriteMsgs / PassThruReadMsgs;
重复 SET_CONFIG(J1962_PINS) - ERR_CHANNEL_IN_USE */
PassThruWriteMsgs 返回成功、PassThruReadMsgs 为空、CONNECTION_LOST 标志也不置位。已在台架上验证通过 TP2.0 对 ECU 编程。REQUEST_CONNECTION 失败后通道的内部过滤器未被移除:向无响应 ECU 尝试十余次即占满全部过滤器槽位并使通道静默;TP1_6_PS 上的 TEARDOWN_CONNECTION 返回拒绝 - 应用端无法关闭连接;TP2.0 不接受由 ECU 发起的连接,也不把连接外收到的帧交给应用(J2534-2 §19.3.1)。PassThruReadMsgs。此处是点对点连接,测试仪地址已在 routing activation 时登记,没有可过滤之物:通道把全部消息交给应用,PassThruStartMsgFilter 返回 ERR_NOT_SUPPORTED。CAN 驱动故障会在 DoIP 会话中途重启设备。接收任务看门狗从 5 s 提高到 30 s - 建立 DoIP 连接正常需要最长 20 s。PassThruConnect 在第一条消息就遇到队列溢出。基础 CAN 与 ISO15765 走到了另一个 CAN 控制器,到不了总线。接收队列在遇到损坏记录后无法恢复读取 - 所有基于 CAN 的协议都错误地检查了该标志。GET_NDIS_ADAPTER_INFO - 在 STATUS_NOERROR 下返回未初始化数据。现在返回适配器标识、MAC、ECU 看到设备的 IPv4 地址以及激活线状态;设备无 Ethernet 时 - ERR_NOT_SUPPORTED。GET_PROTOCOL_INFO - 只对部分协议应答且格式错误。现在在任何已打开通道上均可用:时间戳分辨率(1 µs)、支持的校验位、UART 数据位数。设备无法应答的参数在 supported 字段中标记,调用本身返回 STATUS_NOERROR。PassThruDisconnect - 访问已结束的通道任务会破坏设备内存。新增
libj2534.xcframework 包含设备(arm64)和模拟器(arm64/x86_64)切片,最低 iOS 12.0。每个切片含 j2534.h、j2534_ota.h 头文件、module map(Swift import J2534,自动链接 CoreBluetooth)及 privacy manifest。Pass-Thru API 原型已在 j2534.h 本身声明 - 所有平台一致。mbedTLS 已编入,无外部依赖。Xcode 设置:Embed = Do Not Embed(静态库),Other Linker Flags 中加 -lc++,Info.plist 中加 NSBluetoothAlwaysUsageDescription(BLE)与 NSLocalNetworkUsageDescription(WLAN)- 缺少时 iOS 会在首次使用传输层时终止应用。
import J2534
var deviceId: UInt32 = 0
// PassThruOpen 接受可变 char* - 传入字符串副本
var cstr = Array("ScanDoc;b:N4999".utf8CString) // 按名称前缀走 BLE
let ret = cstr.withUnsafeMutableBufferPointer { PassThruOpen($0.baseAddress, &deviceId) }
if ret == 0 {
var fw = [CChar](repeating: 0, count: 80)
var dll = [CChar](repeating: 0, count: 80)
var api = [CChar](repeating: 0, count: 80)
PassThruReadVersion(deviceId, &fw, &dll, &api)
PassThruClose(deviceId)
}
/* 协议和 IOCTL 的 ID 是带类型转换的宏,不会导入 Swift:
直接用数字,let CAN: UInt32 = 5, let ISO15765: UInt32 = 6 */
ptOtaUpdate(devId, firmwarePath, callback) 和 ptOtaAbort(devId);此前 OtaUpdate/OtaAbort 仅通过 C API 可用。进度通过 onProgress(current, total) 回传 - 以块计,从 1 开始。
// update.bin 已预先复制到应用存储。
// 调用为阻塞式 - 请在 main thread 之外执行。
val res = j2534.ptOtaUpdate(devId, file.absolutePath,
object : OtaProgressListener {
override fun onProgress(current: Int, total: Int) { /* 进度条 */ }
})
if (res.status == 0) {
// 固件已写入,设备重启:devId 失效,
// 用新的 ptOpen 重新连接(BLE 需等待约 10 s)
}
// res.status < 0 - ota_result_t 代码(见 j2534_ota.h)
// ptOtaAbort(devId) 中止更新且不重启设备
j2534.json 中的 log_level 键设置:-1 关闭、0 错误、1 +警告、2 +info、3 +debug、4 +verbose;默认为 3,即不作配置时日志完整写入。级别为 -1 时不创建 sdlogs 文件夹和 .qlog 文件,不向磁盘写入任何数据。Android 上还可从代码设置 - ptSetLogLevel(int);这样设置的级别优先于配置文件,因此发布版本中的日志无法从外部开启。
// Android:在 ptOpen 之前调用
j2534.ptSetLogLevel(-1) // 发布版本 - 日志关闭
j2534.ptSetLogLevel(3) // 联系支持 - 完整日志
// 其他平台:配置文件夹中的 j2534.json
// macOS ~/Library/Application Support/Quantex/
// Linux ~/.config/quantex/
// Windows %APPDATA%\Quantex\
{ "log_level": -1, "devices": [] }
修复
PassThruReadVersion 和 .qlog 头部返回 2.0.0.0:构建号未传入 Android 构建。现在版本按与其他平台相同的规则确定;联系支持时请提供此版本号。serial_* 符号失败:USB 传输已从 iOS 构建中排除,但对它的调用仍在。该传输已替换为桩实现 - 用 c: 字符串连接返回常规的端口打开错误。.qlog 日志中数据被截断 - 消息数据最多只写入 125 字节,单次 PassThruReadMsgs 或 PassThruWriteMsgs 调用传入的一组消息的记录受固定缓冲区限制。现在消息和整组均完整写入 - 对 DTC 列表等长响应尤为重要。.qlog 日志中的字段解析 - 库和设备用两套独立实现生成日志文本,同一数值的解析结果不一致。RxStatus 字段中 TP2.0 和 TP1.6 的连接已建立标志,库打印为 CONNECTION_ESTABLISHED,设备打印为 CONN_OK;IOCTL 名称有 22 处不同。现在协议名、TxFlags 与 RxStatus 标志、IOCTL 及其参数的名称由同一实现生成,同一次交互的应用日志与设备日志可并排阅读。下载 J2534 库 2.0.0.200 - Windows x86/x64/ARM64(Windows 7 单独构建)、macOS(universal)、Linux(x64、x86、ARM、ARM64)、Android(arm64-v8a、armeabi-v7a、x86、x86_64)、iOS。
新增
ISO13400_PS(0x8FFD)和 HSFZ_PS(0x8FFC)。它们不属于 SAE J2534 标准,是 ScanDoc 的自有扩展:通过 Ethernet 诊断 - 网络内车辆发现(VIN、逻辑地址)、TCP 连接、routing activation、UDS 交换。tester 地址默认为 0 - 请在 routing activation 之前设置 ISO13400_SOURCE_ADDR,否则网关会拒绝;ECU 地址随每条消息传递([TA][SA][UDS]),ISO13400_TARGET_ADDR 不通过 Set/GetConfig 设置。发送按 P2 串行化:同一时间只有一个未完成的 UDS 请求,NRC 7F xx 78 将等待延长至 P2*max(6 秒)。新的通道参数 ISO13400_P3_DOIP(0x8108)- 消息间暂停。
uint32_t ch, code = 0;
pt_config_t sa = { ISO13400_SOURCE_ADDR, 0x0E80 };
pt_config_list_t cfg = { 1, &sa };
PassThruConnect(dev, ISO13400_PS, 0, 0, &ch);
PassThruIoctl(ch, SET_CONFIG, &cfg, NULL); /* SA - 在 routing activation 之前设置 */
PassThruIoctl(ch, ISO13400_DISCOVER_VEHICLES, NULL, NULL); /* ECU 的 IP 会自动记住 */
PassThruIoctl(ch, ISO13400_CONNECT_TCP, NULL, NULL);
PassThruIoctl(ch, ISO13400_ACTIVATE_ROUTING, NULL, &code); /* 0x10 = 成功 */
/* 之后 PassThruWriteMsgs / PassThruReadMsgs - 常规 UDS */
0x55(J2534 帧标记)- J2534,其他(文本 AT 命令)- ELM327。修复
PassThruStartMsgFilter 只比较 CAN ID 的 4 个字节,忽略给定的过滤器长度。现在按标准要求对整个长度进行比较:按帧内容的 PASS/BLOCK 可用。
/* 在接收队列中抑制 TesterPresent 应答(07E8 02 7E ...) */
pt_msg_t mask = {0}, pattern = {0};
mask.protocol_id = pattern.protocol_id = CAN;
mask.data_size = pattern.data_size = 6; /* 4 字节 CAN ID + 2 字节数据 */
memcpy(mask.data, "\xFF\xFF\xFF\xFF\xFF\xFF", 6);
memcpy(pattern.data, "\x00\x00\x07\xE8\x02\x7E", 6);
uint32_t fid;
PassThruStartMsgFilter(ch, BLOCK_FILTER, &mask, &pattern, NULL, &fid);
AT SH 会破坏 Flow Control(FC 无填充发送,DLC=3 - 网关不发送 Consecutive Frames),并用自己的 TX ID 覆盖接收过滤器(不使用 AT CRA 时接收损坏)。按数据手册 AT SH 只设置发送标头 - 接收过滤器现在仅由 AT CRA/CF/CM 控制。PassThruStopPeriodicMsg 停止后可能多发送一帧。_PS - 通过 SET_CONFIG(J1962_PINS) 选择引脚未生效,帧未上总线。修复