Quantex GmbH
Twój region: Europa

Przewodnik po J2534 dla programistów

Ostatnia modyfikacja:

Czym jest J2534?

J2534 (często nazywany Pass-Thru) to standard opracowany przez SAE (Society of Automotive Engineers), który rozwiązuje istotny problem: pozwala temu samemu oprogramowaniu diagnostycznemu współpracować z adapterami diagnostycznymi różnych producentów.

Główna idea:

Wyobraź sobie, że piszesz program do diagnostyki samochodów. Bez standardu J2534 musiałbyś napisać osobny kod dla każdego adaptera (K-Line, adapter CAN itd.), który chcesz obsługiwać. To skomplikowane i kosztowne.

Standard J2534 definiuje jednolite API (interfejs programistyczny), które producenci adapterów muszą zaimplementować w swoich sterownikach. Standard definiuje to API wyłącznie jako bibliotekę DLL dla systemu Windows

Dla programisty oznacza to:

W ten sposób J2534 to „most” między Twoją aplikacją a adapterem diagnostycznym, który ukrywa złożoność konkretnego sprzętu i pozwala skupić się na logice diagnostyki.

Wielu programistów, poza systemem Windows, chce korzystać z alternatywnych platform. Oprócz standardowej biblioteki DLL dla Windows oferujemy także biblioteki dla Linux, macOS, a także platform mobilnych Android i iOS.


Czego J2534 nie robi (Twój zakres odpowiedzialności)

Ważne, aby rozumieć, że J2534 to standard warstwy transportowej. Bierze na siebie całą pracę związaną z wysyłaniem i odbieraniem bajtów danych przez wybrany interfejs fizyczny (CAN, K-Line itd.).

Standard J2534 nie definiuje jednak:

To pozostaje zadaniem Twojej aplikacji. Jako programista musisz wiedzieć, jakie dokładnie bajty należy wysłać, aby zażądać na przykład kodów błędów lub bieżących parametrów, oraz jak przeanalizować odpowiedź jednostki sterującej.

Do tego potrzebna Ci będzie znajomość aplikacyjnych protokołów diagnostycznych, takich jak:

J2534 DLL dostarczy Twoje bajty do ECU, ale co to za bajty i co zrobić z odpowiedzią — decyduje Twój program.


Przegląd standardów

Standard J2534 jest częścią dużej rodziny standardów regulujących diagnostykę samochodową. Dla głębokiego zrozumienia zalecane jest zapoznanie się z oficjalnymi dokumentami.

Szczegółowa tabela zależności protokołów i standardów

Adapter ScanDoc implementuje nie pełną wersję standardu J2534-1 oraz niektóre rozszerzenia z J2534-2, a także posiada własne funkcje rozszerzające możliwości.


Obsługiwane protokoły

Standard J2534 definiuje zestaw protokołów warstwy fizycznej i transportowej, za pośrednictwem których odbywa się wymiana danych z ECU pojazdu. Poniżej opisano każdy protokół obsługiwany przez adapter ScanDoc.

ISO 15765 (CAN z warstwą transportową)

Główny protokół do diagnostyki nowoczesnych samochodów. ISO 15765 (znany także jako ISO-TP) realizuje warstwę transportową ponad magistralą CAN: automatycznie wykonuje segmentację długich komunikatów na ramki CAN, sterowanie przepływem (Flow Control) i składanie odpowiedzi z wielu ramek.

Właśnie ten protokół jest używany do diagnostyki przez UDS (ISO 14229) i OBD-II na magistrali CAN. Jeśli Twoim zadaniem jest wysyłanie zapytań diagnostycznych i odbieranie odpowiedzi od ECU, użyj ISO15765.

// Połączenie przez ISO 15765 na 500 kbit/s
PassThruConnect(deviceID, ISO15765, 0, 500000, &channelID);

CAN (surowy strumień)

Protokół CAN zapewnia dostęp do surowego strumienia ramek CAN bez warstwy transportowej. Każdy komunikat to jedna ramka CAN (do 8 bajtów danych). Adapter nie wykonuje segmentacji i składania — odbierasz i wysyłasz ramki w niezmienionej postaci.

Użyj tego protokołu, gdy musisz pracować z magistralą CAN bezpośrednio: monitorowanie ruchu, wysyłanie pojedynczych ramek, praca z niestandardowymi protokołami ponad CAN.

// Połączenie CAN na 500 kbit/s z 29-bitowymi ID
PassThruConnect(deviceID, CAN, CAN_29BIT_ID, 500000, &channelID);

ISO 14230 (KWP2000)

Protokół diagnostyki przez K-Line, szeroko stosowany w samochodach z lat 2000. (zwłaszcza europejskich). Obsługuje dwa sposoby inicjalizacji połączenia: 5-bodową (wolną) i szybką (fast init). Po inicjalizacji wymiana odbywa się z prędkością uzgodnioną z ECU.

Używany do diagnostyki dealerskiej przez KWP2000 oraz do OBD-II na K-Line.

// Połączenie przez ISO 14230 na 10400 bodów, tylko K-Line
PassThruConnect(deviceID, ISO14230, ISO9141_K_LINE, 10400, &channelID);

ISO 9141

Wcześniejszy protokół K-Line, zdefiniowany standardem ISO 9141-2. Używany do diagnostyki OBD-II w starszych samochodach (do lat 2004-2008 w zależności od regionu). Obsługuje tylko inicjalizację 5-bodową.

// Połączenie przez ISO 9141 na 10400 bodów
PassThruConnect(deviceID, ISO9141, 0, 10400, &channelID);

SAE J1850 VPW

Protokół z modulacją zmiennej szerokości impulsu (Variable Pulse Width), stosowany w samochodach General Motors do diagnostyki OBD-II. Działa z prędkością 10,4 kbit/s po jednym przewodzie.

// Połączenie przez J1850 VPW
PassThruConnect(deviceID, J1850VPW, 0, 10400, &channelID);

SAE J1850 PWM

Protokół z modulacją szerokości impulsu (Pulse Width Modulation), stosowany w samochodach Ford do diagnostyki OBD-II. Działa z prędkością 41,6 kbit/s po dwóch przewodach.

// Połączenie przez J1850 PWM
PassThruConnect(deviceID, J1850PWM, 0, 41600, &channelID);

Jak zacząć pracę (Przewodnik krok po kroku)

Praca z adapterem J2534 z poziomu Twojej aplikacji zwykle przebiega według tego algorytmu:

Krok 1: Wyszukanie i załadowanie J2534 DLL

Każdy producent adaptera J2534 udostępnia swoją implementację API w postaci pliku DLL. Podczas instalacji sterownika informacja o tej bibliotece DLL (ścieżka do pliku) zapisywana jest w rejestrze systemu Windows.

Twoja aplikacja powinna:

  1. Znaleźć dostępne urządzenia J2534 w rejestrze systemowym.
  2. Umożliwić użytkownikowi wybór, którego adaptera użyć (jeśli jest ich kilka).
  3. Załadować odpowiednią bibliotekę DLL do pamięci za pomocą funkcji LoadLibrary (w systemie Windows).

Krok 2: Główna pętla pracy z adapterem

Po załadowaniu biblioteki DLL i uzyskaniu wskaźników do funkcji typowa sesja diagnostyczna wygląda tak:

  1. Otwórz połączenie z adapterem:
    Wywołaj funkcję PassThruOpen(), aby zainicjalizować komunikację z urządzeniem fizycznym. W odpowiedzi otrzymasz DeviceID — unikalny identyfikator tej sesji.
    // Przykład
    unsigned long deviceID;
    long result = PassThruOpen(NULL, &deviceID);
  2. Ustanów kanał komunikacji z ECU:
    Wywołaj PassThruConnect(), aby ustanowić logiczny kanał komunikacji z pojazdem za pomocą określonego protokołu (na przykład ISO15765 dla magistrali CAN). Wskazujesz protokół, prędkość i inne parametry. W odpowiedzi otrzymujesz ChannelID.
    // Przykład
    unsigned long channelID;
    result = PassThruConnect(deviceID, ISO15765, 0, 500000, &channelID);
  3. Ustaw filtry:
    Konfiguracja filtrów to obowiązkowy krok. Domyślnie adapter nie będzie przyjmować przychodzących komunikatów, dopóki nie zostanie skonfigurowany co najmniej jeden filtr. Filtry pozwalają odsiać cały niepotrzebny ruch na magistrali i otrzymywać tylko interesujące Cię dane (na przykład odpowiedzi od konkretnego ECU). Do tworzenia i konfiguracji filtrów służy funkcja PassThruStartMsgFilter().
  4. Wymiana danych:

    Proces wymiany danych jest asynchroniczny i oparty na kolejkach:

    • Wysyłanie danych: Wywołanie funkcji PassThruWriteMsg() nie wysyła komunikatu do magistrali natychmiast. Zamiast tego umieszcza jeden lub kilka komunikatów w kolejce do wysłania i od razu zwraca sterowanie. Sterownik adaptera samodzielnie wyśle te komunikaty z kolejki, gdy tylko pojawi się taka możliwość.
    • Odczyt danych: Przychodzące z magistrali komunikaty (na przykład odpowiedzi od ECU) gromadzą się w wewnętrznej kolejce odbioru. Funkcja PassThruReadMsg() służy do pobierania komunikatów z tej kolejki.

    Ważna uwaga: Biblioteka J2534 jest jednowątkowa. Oznacza to, że wszystkie wywołania funkcji (PassThruWriteMsg, PassThruReadMsg i in.) dla jednego kanału muszą być wykonywane ściśle sekwencyjnie. Nie można wywołać jednej funkcji, dopóki nie zakończy się wykonanie poprzedniej. Próba jednoczesnego wywołania funkcji z różnych wątków dla tego samego kanału doprowadzi do nieprzewidywalnego zachowania.

  5. Zamknij kanał komunikacji:
    Po zakończeniu pracy z ECU zamknij kanał za pomocą PassThruDisconnect().
    // Przykład
    result = PassThruDisconnect(channelID);
  6. Zamknij połączenie z adapterem:
    Na samym końcu, gdy praca z adapterem jest całkowicie zakończona, wywołaj PassThruClose(), aby zwolnić urządzenie.
    // Przykład
    result = PassThruClose(deviceID);

Ta pętla to podstawa każdej aplikacji J2534. W kolejnych sekcjach szczegółowo opisano każdą funkcję API i jej parametry.


Obsługa błędów

Każda funkcja J2534 API zwraca kod stanu. Pomyślne wykonanie zawsze zwraca STATUS_NOERROR (wartość 0). Każda inna wartość wskazuje na konkretny błąd (na przykład ERR_TIMEOUT, ERR_INVALID_CHANNEL_ID itd.).

Niezwykle ważne jest sprawdzanie zwracanej wartości po każdym wywołaniu funkcji.

Szczególny kod błędu — ERR_FAILED. To ogólny, niespecyficzny błąd. Tylko w tym przypadku należy wywołać funkcję PassThruGetLastError(), aby uzyskać od sterownika bardziej szczegółowy, tekstowy opis problemu.

// Przykład prawidłowej obsługi błędów
long result = PassThruConnect(deviceID, ISO15765, 0, 500000, &channelID);
if (result != STATUS_NOERROR)
{
    printf("Błąd PassThruConnect. Kod: %ld\n", result);

    // Jeśli błąd jest ogólny, żądamy szczegółów
    if (result == ERR_FAILED)
    {
        char errorDescription[80];
        PassThruGetLastError(&errorDescription[0], 80);
        printf("  Informacje dodatkowe: %s\n", errorDescription);
    }

    // Tutaj może znajdować się logika obsługi innych kodów błędów
    // switch (result) { case ERR_TIMEOUT: ... }

    return; // Przerywamy wykonanie
}

Dokumentacja standardowych funkcji J2534

Szczegółowy opis każdej funkcji standardu J2534 został wydzielony do dokumentacji funkcji.