SANPO SPI to FDCAN

SANPO SPI to FDCAN is suitable for periodic control of FDCAN devices from a Jetson, Raspberry Pi, or another host controller. CAN FD is available only in SPI LONG mode, with a fixed 73-byte transfer.

For SANPO SPI to classic CAN, see SANPO SPI to CAN.

Switch to LONG Before Use

The factory default SPI mode is SHORT, which cannot transmit or receive CAN FD. First switch the mode through a management port. After connecting USB, Windows shows six USB serial ports; two 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=LONG

Use CRLF as the line ending. After receiving OK, wait at least 10 ms before sending 73-byte SPI frames. The setting is saved to Flash and remains LONG after power-up.

Also query the CAN FD bit rates:

AT+SETFDCAN?

The factory defaults are a 1 Mbps arbitration phase and 5 Mbps data phase, with BRS enabled. The data phase can be set to 2, 3, 4, or 5 Mbps; see Communication Settings.

SPI Settings

Item

Setting

SPI mode

Mode 0 (CPOL=0, CPHA=0)

Bit order

MSB First

Transfer

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

CRC-8

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

Select a CAN FD 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 FD 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.

Data Length Code

Code

Bytes

Code

Bytes

00

0

08

8

01

1

09

12

02

2

0A

16

03

3

0B

20

04

4

0C

24

05

5

0D

32

06

6

0E

48

07

7

0F

64

73-Byte Message

Extended Frame

Byte positions

Content

0-1

Fixed 45 46, or EF

2

Channel

3-6

29-bit CAN ID, big-endian

7

Length code 00-0F

8-71

Fixed 64-byte data area; unused bytes are 00

72

CRC-8 of the first 72 bytes

Standard Frame

Byte positions

Content

0-1

Fixed 53 46, or SF

2

Channel

3-4

Fixed 00 00

5-6

11-bit CAN ID, big-endian

7

Length code 00-0F

8-71

Fixed 64-byte data area; unused bytes are 00

72

CRC-8 of the first 72 bytes

For example, when sending 16 bytes to Channel 1 with extended ID 0x1F100101, the first 24 bytes are:

45 46 01 1F 10 01 01 0A
01 01 01 01 42 00 00 00 01 01 64 00 78 56 34 12

Append 48 00 bytes and then the CRC-8 calculated over the first 72 bytes.

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

Read CAN FD Feedback

SPI is full duplex. Data read while sending a command may be old feedback or all zeros. Continue sending 73-byte empty frames to read later feedback.

For each non-zero frame, check in order:

  1. The byte-73 CRC equals the calculated CRC of bytes 0-71.

  2. The header is SF or EF.

  3. Channel is 1/2 on the current STM32.

  4. The length code is valid.

  5. The CAN ID and data match the target device protocol.

Troubleshooting

Symptom

Action

All bytes are 00

No feedback is queued; continue polling with a 73-byte empty frame

No response in 23-byte mode

CAN FD requires LONG; after switching, send 73 bytes per transfer

CRC error

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

CAN FD device does not reply

Check arbitration/data rates, BRS, Channel, ID, termination resistors, wiring, and power

Length code is correct but data is incomplete

Fill the complete 64-byte data area and pad unused bytes with 00