How to correctly send a CAN FD format data packet?

I am using VS Code to develop on the nRF52832, which is externally connected to a TCAN4550 CAN-FD chip. I successfully used the tcan4550evm.overlay to send and receive 8-byte CAN data normally. However, when I tried to send a CAN-FD format data packet, the operation failed. so,how to correctly send a CAN FD format data packet? I look forward to your reply.

The printout shows the following error message.

My overlay configuration is as follows:

/ {
    gpio_keys {
        compatible = "gpio-keys";
        pat9125_a_int: pat9125_a_int {
            gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
            label = "PAT9125_A_INT";
        };
        pat9125_b_int: pat9125_b_int {
            gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
            label = "PAT9125_B_INT";
        };
    };

    aliases {
        pat9125-a-int = &pat9125_a_int;
        pat9125-b-int = &pat9125_b_int;
        /* 将 can0 别名合并到这里 */
        can0 = &tcan4x5x_tcan4550evm;
    };

    chosen {
        zephyr,canbus = &tcan4x5x_tcan4550evm;
    };
};

&i2c0 {
    status = "okay";

    pat9125_a: pat9125@73 {
        compatible = "pixart,pat9125";
        reg = <0x73>;
        label = "PAT9125_A";
    };

    pat9125_b: pat9125@75 {
        compatible = "pixart,pat9125";
        reg = <0x75>;
        label = "PAT9125_B";
    };
};


&arduino_spi {
    status = "okay";
    cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */

    tcan4x5x_tcan4550evm: can@0 {
        compatible = "ti,tcan4x5x";
        reg = <0>;
        spi-max-frequency = <2000000>;
        clock-frequency = <40000000>;
        device-state-gpios = <&arduino_header 12 GPIO_ACTIVE_HIGH>; /* D6 */
        device-wake-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */
        reset-gpios = <&arduino_header 14 GPIO_ACTIVE_HIGH>; /* D8 */
        int-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */
        bosch,mram-cfg = <0x0 15 15 7 7 0 10 10>;
        can-transceiver {
            max-bitrate = <8000000>;
        };
        /* 在这里直接配置节点属性,而不是通过别名 */
        bitrate = <500000>;         /* 仲裁阶段波特率: 500 kbps */
        bitrate-data = <500000>;    /* 数据阶段波特率: 500 kbps */
        sample-point = <875>;       /* 仲裁阶段采样点: 87.5% */
        sample-point-data = <875>;  /* 数据阶段采样点: 87.5% */
        status = "okay";
    };
};
My prj configuration is as follows:
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_CBPRINTF_FP_SUPPORT=y
# 确保日志已启用
CONFIG_LOG=y
# 设置默认日志级别(0=EMERG, 1=ALERT, 2=CRIT, 3=ERR, 4=WARNING, 5=INFO, 6=DEBUG, 7=VERBOSE)
CONFIG_LOG_DEFAULT_LEVEL=3
# 允许动态修改日志级别
CONFIG_LOG_MODE_IMMEDIATE=y

# 调试/监控
CONFIG_THREAD_MONITOR=y
CONFIG_THREAD_NAME=y

# 多线程支持
CONFIG_MULTITHREADING=y
CONFIG_NUM_COOP_PRIORITIES=16
CONFIG_NUM_PREEMPT_PRIORITIES=16
CONFIG_MAIN_STACK_SIZE=4096
# 线程分析器
CONFIG_THREAD_STACK_INFO=y
CONFIG_THREAD_ANALYZER=y
CONFIG_THREAD_ANALYZER_AUTO=y
CONFIG_THREAD_ANALYZER_USE_PRINTK=y
CONFIG_INIT_STACKS=y


# CAN总线配置
CONFIG_CAN=y
CONFIG_STATS=y
CONFIG_CAN_STATS=y
CONFIG_CAN_FD_MODE=y # 启用 Zephyr 的 CAN FD API 支持

# SPI配置
CONFIG_SPI=y          # 启用 SPI 总线驱动(TCAN4550 的通信方式)
CONFIG_SPI_NRFX=y               # nRF52硬件SPI驱动
CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=128
CONFIG_PINCTRL=y      # 启用引脚控制(通常是 SPI 和 GPIO 的依赖)
CONFIG_CAN_TCAN4X5X=y # 启用 TCAN4550 系列芯片的驱动程序
My main function is as follows:
int main(void)
{
    int ret;
    bool led_state = true;
    if (!device_is_ready(led.port)) {
        LOG_ERR("LED device %s is not ready", led.port->name);
        return 0;
    }
    ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    if (ret < 0) {
        LOG_ERR("Could not configure LED GPIO pin, error: %d", ret);
        return 0;
    }

    /* 1. 检查CAN设备是否就绪 */
    if (!device_is_ready(can_dev)) {
        LOG_ERR("CAN device not ready!");
        return 0;
    }
    /* 2. 启动CAN控制器 */
    ret = can_start(can_dev);
    if (ret != 0) {
        LOG_ERR("Failed to start CAN controller [%d]", ret);
        return 0;
    }
    /* 3. 设置一个过滤器,只接收ID为0x123的标准CAN帧 */
    struct can_filter my_filter = {
        .id = 0x123,
        .mask = CAN_STD_ID_MASK, /* 只关心标准ID */
        .flags = 0 /* 对于标准ID,此标志应为0。这里假设你想过滤标准ID的数据帧 */
    };
    /* 4. 将过滤器和回调函数附加到CAN设备 */
    ret = can_add_rx_filter(can_dev, can_rx_callback, NULL, &my_filter);
    if (ret < 0) {
        LOG_ERR("Failed to add CAN RX filter [%d]", ret);
        return 0;
    }

    LOG_INF("CAN application started");
    while (1) {
      //thread_analyzer_print(0);
         ret = gpio_pin_toggle_dt(&led);
        if (ret < 0) {
            LOG_ERR("Could not toggle LED, error: %d", ret);
            return 0;
        }
        led_state = !led_state;
        printf("LED state: %s\n", led_state ? "ON" : "OFF");

        /* 5. 构造并发送一条CAN消息 */
        struct can_frame frame_to_send = {
            .id = 0x456,      /* 发送ID */
            /* CAN FD 帧标志,BRS表示使用更快的比特率传输数据段 */
            .flags = CAN_FRAME_FDF | CAN_FRAME_BRS,
            .dlc = 12,         /* 数据长度码, 9对应12字节. CAN FD DLC > 8 时有特殊含义 */
            .data = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,0x01, 0x02, 0x03, 0x04}
        };
        frame_to_send.dlc = can_bytes_to_dlc(12); // 使用辅助函数将字节数转换为DLC值

        ret = can_send(can_dev, &frame_to_send, K_SECONDS(1), NULL, NULL);
        if (ret != 0) {
            LOG_ERR("Failed to send CAN frame [%d]", ret);
        }

                /* 6. 等待并处理接收到的消息 */
        struct can_frame received_frame;
        if (k_msgq_get(&can_msgq, &received_frame, K_MSEC(500)) == 0) {
            LOG_INF("CAN frame received! ID: 0x%03X, DLC: %d", received_frame.id, received_frame.dlc);
            LOG_HEXDUMP_INF(received_frame.data, received_frame.dlc, "Data:");
        }
        k_msleep(SLEEP_TIME_MS);      
    }
    return 0;
}
Related