AI-generated text still pending human review/editing.
ISO-TP transport ↗

KWP2000 & ISO 14230

Keyword Protocol 2000 is UDS's direct ancestor, the diagnostic language that ran on older ECUs (roughly mid-1990s to late-2000s) before ISO 14229 (UDS) standardised everything. On modern CAN vehicles you meet it as KWP2000-on-CAN (ISO 15765-3): the same ISO-TP transport sloppyCAN already speaks, with a different set of service IDs and error codes on top.

Same ISO-TP Carrier

Originally KWP2000 ran over a K-line (ISO 14230 on ISO 9141 wiring). When the industry moved to CAN, the application layer was re-hosted on ISO-TP (ISO 15765-2), the same Single-Frame / First-Frame / Flow-Control / Consecutive-Frame transport UDS uses. That is why sloppyCAN implements KWP2000 as a mode of the ISO-TP / UDS tab, not a new transport: only the decode tables change.

For the transport mechanics, how a long response splits into First Frame + Flow Control + Consecutive Frames, see the ISO-TP Explainer.

Same Conventions as UDS

The request/response grammar is identical to UDS, so if you know one you know the other:

Tester → ECU
21 F0
ReadDataByLocalIdentifier, RLI 0xF0
→
ECU → tester
61 F0 …
positive response (0x21 + 0x40), RLI echoed, then data

Where It Differs From UDS

Several KWP service IDs share a number with UDS but mean something different. sloppyCAN keeps separate KWP tables instead of patching the UDS ones, since decoding 21 as a UDS service would be wrong.

SIDIn KWP2000In UDS
21ReadDataByLocalIdentifierDoes not exist
1AReadECUIdentificationDoes not exist
81StartCommunicationKWP-only
82StopCommunicationKWP-only
83AccessTimingParametersAccessTimingParameter
3BWriteDataByLocalIdentifierUses 2E by DID

The negative-response-code list also differs in spots. The routing codes 0xA0 ecuNotResponding and 0xA1 ecuAddressUnknown are a KWP thing, left over from the K-line world where a gateway sat between the tester and the ECU, and UDS doesn't define them. (The block-transfer codes around 0x71-0x73 look like a difference but aren't: UDS kept them.) sloppyCAN's KWP mode names these from the ISO 14230 table.

A Typical Session

Unlike OBD-II, where you can fire a request at a broadcast address, a KWP session is explicitly opened and closed:

StepRequestMeaning
181StartCommunication, wakes the ECU, gets key bytes back (C1 …)
210 81StartDiagnosticSession, mode 0x81 default (others: 85 programming, 89 standby, 92 EOL)
31A 9AReadECUIdentification, option 0x9A, response is mostly ASCII
421 F0ReadDataByLocalIdentifier, RLI 0xF0
53ETesterPresent, keeps the session alive, sent periodically
682StopCommunication, closes the session cleanly

TesterPresent matters here. If the tester goes quiet for the session's timeout (typically a few seconds, negotiable via 0x83), the ECU drops back to its default session, so diagnostic tools send 3E on a heartbeat.

Try it

Switch the ISO-TP / UDS tab to KWP2000 and turn on Demo. The palette buttons (StartComms, StartSession, TesterPresent, ReadECUIdent, ReadByLocalId, StopComms) each transmit a real request, and a simulated ECU answers: positive responses decoded with KWP service names, unknown services answered with 7F <sid> 11 (serviceNotSupported). You can also type any hex into the input, e.g. 21 F0 or 1A 9A.