Creación de un canal de comunicación lógico sobre una conexión física
Última modificación:
La función crea un canal de comunicación lógico con el vehículo en el dispositivo pass-thru indicado. El canal lógico superpone un esquema de protocolo adicional sobre el canal de comunicación físico existente.
Tras una ejecución correcta, la función devuelve STATUS_NOERROR, y el valor apuntado por pChannelID se utiliza como descriptor (handle) del canal creado. El canal se encuentra en estado inicializado.
Se admiten hasta 10 canales lógicos por cada canal de comunicación físico. La creación de un canal lógico no afecta al funcionamiento del canal físico ni de otros canales lógicos asociados a él.
long PassThruLogicalConnect(
unsigned long PhysicalChannelID,
unsigned long ProtocolID,
unsigned long Flags,
void *pChannelDescriptor,
unsigned long *pChannelID
)
El canal lógico creado tiene el siguiente estado inicial:
Parámetro de entrada. Identificador del canal físico obtenido en la llamada a PassThruConnect().
Parámetro de entrada. Identificador del protocolo para el canal de comunicación lógico. Determina cómo interactuará el canal lógico con el vehículo, así como el tipo de la estructura pChannelDescriptor.
| ProtocolID | Descripción |
|---|---|
ISO15765_LOGICAL |
ISO 15765-2 con control de flujo (flow control) |
Parámetro de entrada. Flags de configuración del canal lógico. Los flags pueden combinarse mediante OR.
| Flag | Descripción | Valores |
|---|---|---|
FULL_DUPLEX |
Modo dúplex del canal. Solo para ISO 15765. | 0 = semidúplex 1 = dúplex completo |
ISO15765_ON_J1939 |
Enmascaramiento de los bits de prioridad (28-26) en el CAN ID para mensajes ISO 15765 con identificador de 29 bits (conforme a ISO 15765-2 Annex A y SAE J1939-21). Solo para ISO 15765. | 0 = enmascaramiento desactivado (procesamiento estándar de ISO 15765) 1 = enmascaramiento activado |
Parámetro de entrada. Puntero a la estructura que describe los puntos finales de la conexión lógica. Si el puntero es NULL, la función devolverá ERR_NULL_PARAMETER.
Parámetro de entrada. Puntero a una variable unsigned long reservada por la aplicación. Tras una ejecución correcta, la variable contendrá el identificador del canal lógico para las llamadas posteriores a las funciones.
Para el protocolo ISO15765_LOGICAL se utiliza la estructura ISO15765_CHANNEL_DESCRIPTOR, que define los puntos finales de la conexión lógica:
typedef struct {
unsigned long LocalTxFlags; // TxFlags para LocalAddress
unsigned long RemoteTxFlags; // TxFlags para RemoteAddress
unsigned char LocalAddress[5]; // CAN ID + extended address (lado local)
unsigned char RemoteAddress[5]; // CAN ID + extended address (lado remoto)
} ISO15765_CHANNEL_DESCRIPTOR;
Flags permitidos para el descriptor del canal ISO 15765:
| Flag | Aplicación | Descripción |
|---|---|---|
CAN_29BIT_ID |
LocalAddress, RemoteAddress | Usar CAN ID de 29 bits (en lugar de 11 bits) |
ISO15765_ADDR_TYPE |
LocalAddress, RemoteAddress | Usar direccionamiento extendido (extended address) |
ISO15765_FRAME_PAD |
RemoteAddress | Activar el relleno (padding) de las tramas de flow control en la transmisión |
Address[0] — CAN ID bits 28-24 (los tres bits más significativos deben ser cero)Address[1] — CAN ID bits 23-16Address[2] — CAN ID bits 15-8Address[3] — CAN ID bits 7-0Address[4] — dirección extendida (si se indica el flag ISO15765_ADDR_TYPE)LocalAddress y RemoteAddress deben ser únicas. Ninguna de las direcciones debe coincidir con las direcciones de otros canales lógicos existentes para el
canal físico dado. El CAN ID con dirección extendida no debe coincidir con un CAN ID sin dirección extendida.
| Código | Descripción |
|---|---|
| STATUS_NOERROR | La función se ejecutó correctamente |
| ERR_CONCURRENT_API_CALL | Se llamó a una función de la API J2534 antes de finalizar la llamada anterior |
| ERR_DEVICE_NOT_OPEN | PassThruOpen() no se llamó correctamente |
| ERR_INVALID_CHANNEL_ID | Valor de PhysicalChannelID no válido |
| ERR_DEVICE_NOT_CONNECTED | Error de comunicación con el dispositivo pass-thru. El dispositivo se desconectó. |
| ERR_NOT_SUPPORTED | La DLL no admite esta función |
| ERR_LOG_CHAN_NOT_ALLOWED | El canal lógico no está permitido para la combinación dada de canal físico y ProtocolID |
| ERR_PROTOCOL_ID_NOT_SUPPORTED | El valor de ProtocolID no es compatible (no válido o desconocido) |
| ERR_FLAG_NOT_SUPPORTED | Los valores de Flags no son válidos, son desconocidos o no son aplicables al canal actual |
| ERR_INVALID_CHANNEL_DESCRIPTOR | Uno o varios elementos de la estructura pChannelDescriptor no son válidos o no son aplicables al canal actual |
| ERR_NULL_REQUIRED | Un parámetro que debería ser NULL no se estableció en NULL |
| ERR_NULL_PARAMETER | Se pasó un puntero NULL en lugar de un puntero obligatorio |
| ERR_NOT_UNIQUE | Intento de crear un canal lógico con direcciones que duplican las direcciones de un canal existente |
| ERR_EXCEEDED_LIMIT | Se superó el número máximo de canales lógicos para el canal físico dado |
| ERR_FAILED | Error no especificado. Utilice PassThruGetLastError() para obtener la descripción. |
#include "j2534_dll.hpp"
unsigned long deviceID = 0;
unsigned long physicalChannelID = 0;
unsigned long logicalChannelID = 0;
// Abrimos el dispositivo
long ret = PassThruOpen("ScanDoc", &deviceID);
if (ret != STATUS_NOERROR) return;
// Creamos la conexión física CAN
ret = PassThruConnect(deviceID, CAN, CAN_29BIT_ID, 500000, &physicalChannelID);
if (ret != STATUS_NOERROR) {
PassThruClose(deviceID);
return;
}
// Configuramos el descriptor del canal lógico ISO 15765
ISO15765_CHANNEL_DESCRIPTOR channelDesc = {0};
// Dirección local (adaptador) - 0x18DA00F1 (solicitud funcional)
channelDesc.LocalTxFlags = CAN_29BIT_ID;
channelDesc.LocalAddress[0] = 0x18;
channelDesc.LocalAddress[1] = 0xDA;
channelDesc.LocalAddress[2] = 0x00;
channelDesc.LocalAddress[3] = 0xF1;
// Dirección remota (ECU) - 0x18DAF100 (respuesta del 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;
// Creamos el canal lógico
ret = PassThruLogicalConnect(
physicalChannelID,
ISO15765_LOGICAL,
0, // Flags: semidúplex
&channelDesc,
&logicalChannelID
);
if (ret == STATUS_NOERROR) {
printf("Canal lógico creado: %lu\n", logicalChannelID);
// Ahora se puede usar logicalChannelID para PassThruReadMsgs/PassThruQueueMsgs
// Cerramos el canal lógico
PassThruLogicalDisconnect(logicalChannelID);
}
// Cerramos el canal físico y el dispositivo
PassThruDisconnect(physicalChannelID);
PassThruClose(deviceID);
from ctypes import *
# Carga de la biblioteca
j2534 = cdll.LoadLibrary("libj2534_v05_00.dylib")
# Estructura del descriptor del canal
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()
# Abrimos el dispositivo
ret = j2534.PassThruOpen(b"ScanDoc", byref(device_id))
if ret != 0:
print(f"Error de PassThruOpen: {ret}")
exit()
# Creamos la conexión física 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"Error de PassThruConnect: {ret}")
j2534.PassThruClose(device_id)
exit()
# Configuramos el descriptor del canal
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
# Creamos el canal lógico
ret = j2534.PassThruLogicalConnect(
physical_channel_id,
ISO15765_LOGICAL,
0,
byref(channel_desc),
byref(logical_channel_id)
)
if ret == 0:
print(f"Canal lógico creado: {logical_channel_id.value}")
# ...trabajo con el canal...
j2534.PassThruLogicalDisconnect(logical_channel_id)
else:
print(f"Error: {ret}")
j2534.PassThruDisconnect(physical_channel_id)
j2534.PassThruClose(device_id)
PassThruConnect() - Creación de la conexión físicaPassThruLogicalDisconnect() - Cierre del canal lógicoPassThruReadMsgs() - Lectura de mensajes del canal