Skip to content

Commit 9fe17e4

Browse files
authored
Support 11-bit identifiers in the serial interface (#1758)
1 parent b075a68 commit 9fe17e4

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

can/interfaces/serial/serial_can.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None:
135135

136136
# Pack arbitration ID
137137
try:
138-
arbitration_id = struct.pack("<I", msg.arbitration_id)
138+
arbitration_id = msg.arbitration_id + (0 if msg.is_extended_id else 0x20000000)
139+
arbitration_id = struct.pack("<I", arbitration_id)
139140
except struct.error:
140141
raise ValueError(
141142
f"Arbitration ID is out of range: {msg.arbitration_id}"
@@ -188,9 +189,15 @@ def _recv_internal(
188189

189190
s = self._ser.read(4)
190191
arbitration_id = struct.unpack("<I", s)[0]
191-
if arbitration_id >= 0x20000000:
192+
is_extended_id = False if arbitration_id & 0x20000000 else True
193+
arbitration_id -= 0 if is_extended_id else 0x20000000
194+
if is_extended_id and arbitration_id >= 0x20000000:
192195
raise ValueError(
193-
"received arbitration id may not exceed 2^29 (0x20000000)"
196+
"received arbitration id may not exceed or equal 2^29 (0x20000000) if extended"
197+
)
198+
if not is_extended_id and arbitration_id >= 0x800:
199+
raise ValueError(
200+
"received arbitration id may not exceed or equal 2^11 (0x800) if not extended"
194201
)
195202

196203
data = self._ser.read(dlc)
@@ -204,6 +211,7 @@ def _recv_internal(
204211
arbitration_id=arbitration_id,
205212
dlc=dlc,
206213
data=data,
214+
is_extended_id=is_extended_id,
207215
)
208216
return msg, False
209217

doc/interfaces/serial.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ six parts. The start and the stop byte for the frame, the timestamp, DLC,
3030
arbitration ID and the payload. The payload has a variable length of between
3131
0 and 8 bytes, the other parts are fixed. Both, the timestamp and the
3232
arbitration ID will be interpreted as 4 byte unsigned integers. The DLC is
33-
also an unsigned integer with a length of 1 byte.
33+
also an unsigned integer with a length of 1 byte. Non-extended (11-bit)
34+
identifiers are encoded by adding 0x20000000 to the 11-bit ID. For example, an
35+
11-bit CAN ID of 0x123 is encoded with an arbitration ID of 0x20000123.
3436

3537
Serial frame format
3638
^^^^^^^^^^^^^^^^^^^
@@ -102,3 +104,21 @@ Examples of serial frames
102104
+================+=====================+======+=====================+==============+
103105
| 0xAA | 0x66 0x73 0x00 0x00 | 0x00 | 0x01 0x00 0x00 0x00 | 0xBB |
104106
+----------------+---------------------+------+---------------------+--------------+
107+
108+
.. rubric:: CAN message with 0 byte payload with an 11-bit CAN ID
109+
110+
+----------------+---------+
111+
| CAN message |
112+
+----------------+---------+
113+
| Arbitration ID | Payload |
114+
+================+=========+
115+
| 0x20000001 (1) | None |
116+
+----------------+---------+
117+
118+
+----------------+---------------------+------+---------------------+--------------+
119+
| Serial frame |
120+
+----------------+---------------------+------+---------------------+--------------+
121+
| Start of frame | Timestamp | DLC | Arbitration ID | End of frame |
122+
+================+=====================+======+=====================+==============+
123+
| 0xAA | 0x66 0x73 0x00 0x00 | 0x00 | 0x01 0x00 0x00 0x20 | 0xBB |
124+
+----------------+---------------------+------+---------------------+--------------+

test/serial_test.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def test_rx_tx_data_none(self):
8686

8787
def test_rx_tx_min_id(self):
8888
"""
89-
Tests the transfer with the lowest arbitration id
89+
Tests the transfer with the lowest extended arbitration id
9090
"""
9191
msg = can.Message(arbitration_id=0)
9292
self.bus.send(msg)
@@ -95,13 +95,31 @@ def test_rx_tx_min_id(self):
9595

9696
def test_rx_tx_max_id(self):
9797
"""
98-
Tests the transfer with the highest arbitration id
98+
Tests the transfer with the highest extended arbitration id
9999
"""
100100
msg = can.Message(arbitration_id=536870911)
101101
self.bus.send(msg)
102102
msg_receive = self.bus.recv()
103103
self.assertMessageEqual(msg, msg_receive)
104104

105+
def test_rx_tx_min_nonext_id(self):
106+
"""
107+
Tests the transfer with the lowest non-extended arbitration id
108+
"""
109+
msg = can.Message(arbitration_id=0x000, is_extended_id=False)
110+
self.bus.send(msg)
111+
msg_receive = self.bus.recv()
112+
self.assertMessageEqual(msg, msg_receive)
113+
114+
def test_rx_tx_max_nonext_id(self):
115+
"""
116+
Tests the transfer with the highest non-extended arbitration id
117+
"""
118+
msg = can.Message(arbitration_id=0x7FF, is_extended_id=False)
119+
self.bus.send(msg)
120+
msg_receive = self.bus.recv()
121+
self.assertMessageEqual(msg, msg_receive)
122+
105123
def test_rx_tx_max_timestamp(self):
106124
"""
107125
Tests the transfer with the highest possible timestamp

0 commit comments

Comments
 (0)