SANPO SPI to CAN
SANPO SPI to CAN lets a Jetson, Raspberry Pi, or another host controller operate classic CAN devices periodically. The host sends a fixed-length SPI message containing a CAN ID and data and reads device feedback during the current or a later transfer.
For CAN FD, see SANPO SPI to FDCAN.
SPI Settings
Item |
Setting |
|---|---|
SPI mode |
Mode 0 (CPOL=0, CPHA=0) |
Bit order |
MSB First |
SHORT |
22-byte message area + 1-byte CRC, 23 bytes total |
LONG |
72-byte message area + 1-byte CRC, 73 bytes total |
CRC-8 |
Polynomial |
Factory default is SHORT. Classic CAN works in both SHORT and LONG, but use SHORT for lower overhead when CAN FD is not required.
Switch modes over USB serial:
AT+SPIMODE=SHORT
AT+SPIMODE=LONG
Send the command as text with a CRLF line ending. The setting is saved. After success, wait at least 10 ms before starting transfers with the new length.
Select a CAN Channel
SPI chip select |
Channel |
Target |
|---|---|---|
First MCU |
|
CAN-1 |
First MCU |
|
CAN-2 |
Second MCU |
|
CAN-3 |
Second MCU |
|
CAN-4 |
Either chip select |
|
Both CAN interfaces on the current MCU |
Internally, 1/3 select the first local interface and 2/4 select the second. Replies only use local Channel 1/2.
Software CS0 and CS1 on a Linux host normally connect to the board’s two external chip selects. Confirm actual wiring rather than relying only on software numbering.
SHORT Message
Extended Frame
Byte position |
Content |
|---|---|
0 to 1 |
Fixed |
2 |
Channel |
3 to 6 |
29-bit CAN ID, most significant byte first |
7 |
Data length |
8 to 15 |
8-byte data area; fill unused bytes with |
16 to 21 |
|
22 |
CRC-8 over the first 22 bytes |
Standard Frame
Byte position |
Content |
|---|---|
0 to 1 |
Fixed |
2 |
Channel |
3 to 4 |
Fixed |
5 to 6 |
11-bit CAN ID, most significant byte first |
7 |
Data length |
8 to 15 |
8-byte data area; fill unused bytes with |
16 to 21 |
|
22 |
CRC-8 over the first 22 bytes |
For Channel 1, extended ID 0x0000FD01, and 8 data bytes, the 22 bytes before CRC are:
45 54 01 00 00 FD 01 08 01 02 03 04 05 06 07 08 00 00 00 00 00 00
LONG Message
The first 8 bytes match SHORT. Bytes 8 to 71 form a fixed 64-byte data area, and byte 72 is CRC-8. Classic CAN uses only the first 0 to 8 data bytes; fill the rest with 00.
Type |
Bytes 0 to 7 |
Bytes 8 to 71 |
Byte 72 |
|---|---|---|---|
Extended |
|
64-byte data area |
CRC-8 |
Standard |
|
64-byte data area |
CRC-8 |
Calculate CRC
def crc8(data: bytes) -> int:
crc = 0
for value in data:
crc ^= value
for _ in range(8):
crc = ((crc << 1) ^ 0x07) & 0xFF if crc & 0x80 else (crc << 1) & 0xFF
return crc
Calculate over the first 22 bytes for SHORT or the first 72 bytes for LONG and place the result in the final byte.
Read CAN Feedback
SPI is full duplex. Data read while sending a command may be older cached feedback or all 00. If the target reply is not immediately available, continue sending all-zero frames of the current length.
A valid reply has:
The total length required by the active SHORT/LONG mode.
A correct CRC in the final byte.
A message area beginning with
45 54or53 54.Local Channel
01or02.The valid CAN data length in byte 7.
One SPI read is not a fixed response to one request. Match feedback by CAN ID and device protocol.
Examples
Troubleshooting
Symptom |
Action |
|---|---|
Received data is all |
No feedback is queued; wait briefly and send another empty frame |
CRC fails |
Check Mode 0, MSB First, fixed length, SPI clock, and chip-select timing |
CAN device does not reply |
Check chip select, Channel, CAN ID, bitrate, termination, wiring, and power |
Frame is sent on both CAN interfaces |
Channel is |
No response after switching to LONG |
The host is still sending 23 bytes; send exactly 73 bytes per transfer |