SANPO SPI to CAN

SANPO SPI to CAN is suitable for periodic control of classic CAN devices from a Jetson, Raspberry Pi, or another host controller. The host sends CAN data in a fixed-length SPI frame and reads device feedback in the current or a later transfer.

For SANPO SPI to 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 payload + 1-byte CRC, 23 bytes total

LONG

72-byte payload + 1-byte CRC, 73 bytes total

CRC-8

Polynomial 0x07, initial value 0x00, no final XOR

The factory default is SHORT. Classic CAN can use SHORT or LONG, but CAN FD can only use LONG. If CAN FD is not needed, SHORT has lower overhead.

To switch mode, connect USB to the board. Windows shows six USB serial ports, two of which are management ports for the two STM32 MCUs and are normally displayed as SANPO Studio Management Port. Connect to each management port and send:

AT+SPIMODE=SHORT
AT+SPIMODE=LONG

Send the command as text with a CRLF line ending. The setting is saved after a successful response; the host must wait at least 10 ms before using the new frame length.

Select a CAN Interface

SPI chip select

Channel

Target

CS0 (first STM32)

0x01

CAN-1

CS0 (first STM32)

0x02

CAN-2

CS1 (second STM32)

0x03

CAN-3

CS1 (second STM32)

0x04

CAN-4

CS0 or CS1 (either chip select)

0x00

Both CAN interfaces on the current STM32

When sending, 1/3 select the first interface on the selected STM32 and 2/4 select the second. Replies use local Channel 1/2 on the current STM32. CS0 and CS1 on the host normally connect to the board’s two external chip selects. The host and board must share ground; two GND connections are recommended for stable data transfer.

SHORT Message

Extended Frame

Byte positions

Content

0-1

Fixed 45 54, or ET

2

Channel

3-6

29-bit CAN ID, big-endian

7

Data length 0 to 8

8-15

8-byte data area; unused bytes are 00

16-21

00 padding

22

CRC-8 of the first 22 bytes

For example, the first 22 bytes when sending 8 bytes to Channel 1 with extended ID 0x0000FD01 are:

45 54 01 00 00 FD 01 08 01 02 03 04 05 06 07 08 00 00 00 00 00 00

Standard Frame

Byte positions

Content

0-1

Fixed 53 54, or ST

2

Channel

3-4

Fixed 00 00

5-6

11-bit CAN ID, big-endian

7

Data length 0 to 8

8-15

8-byte data area; unused bytes are 00

16-21

00 padding

22

CRC-8 of the first 22 bytes

LONG Message

The first 8 bytes of LONG are the same as SHORT. Bytes 8-71 are a fixed 64-byte data area, and byte 72 is CRC-8. Classic CAN uses only bytes 0-8 of the data area; fill the rest with 00.

Type

Bytes 0-7

Bytes 8-71

Byte 72

Extended frame

ET + Channel + ExtID(4B) + Len

64-byte data area

CRC-8

Standard frame

ST + Channel + 00 00 + StdID(2B) + Len

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 CRC over the first 22 bytes in SHORT or the first 72 bytes in LONG, then put the result in the final byte.

Read CAN Feedback

SPI is full duplex. Data read while sending a control frame may be previously buffered feedback or all 00. If the target feedback is not returned immediately, continue polling by sending an empty frame of the same length.

Valid feedback must satisfy all of the following:

  • Total length matches the current SHORT/LONG mode.

  • The final byte contains a valid CRC.

  • The payload begins with 45 54 or 53 54.

  • Channel is local 01 or 02.

  • Byte 7 contains a valid CAN data length.

A single read is not a fixed response to a single request. The host should use the CAN ID and motor protocol to identify feedback.

Examples

Troubleshooting

Symptom

Action

All bytes are 00

No feedback is queued; continue polling with an empty frame of the same length

CRC error

Check Mode 0, MSB First, fixed transfer length, SPI clock, and chip-select timing

CAN device does not reply

Check chip select, Channel, CAN ID, bit rate, termination resistors, wiring, and power

Frames are sent to both CAN interfaces

Channel is 00; select a specific channel

No response after switching to LONG

The host is still sending 23-byte frames; send 73 bytes for every transfer