扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

GD32E50x 三路CANFD配置

01/16 13:09
2016
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

1 CAN配置

注:本文以GD32E508x为例,其他MCU可能有差异。

1.1 GPIO配置

CAN0、CAN1和CAN2都可以映射到多个GPIO使用,但是配置有所差异。

其中CAN0和CAN1通过配置REMAP寄存器的值来选择对应的GPIO,如下图所示:

在这里插入图片描述

而CAN2是通过AFIO配置,参考代码如下:

gpio_afio_port_config(AFIO_PB10_CAN2_CFG, ENABLE);gpio_afio_port_config(AFIO_PB11_CAN2_CFG, ENABLE);// gpio_afio_port_config(AFIO_PA9_CAN2_CFG, ENABLE);// gpio_afio_port_config(AFIO_PA10_CAN2_CFG, ENABLE);

GPIO配置参考代码如下:

void can0_gpio_config(void){    /* enable CAN0 clock */    rcu_periph_clock_enable(RCU_CAN0);    rcu_periph_clock_enable(CAN0RX_CLOCK);    rcu_periph_clock_enable(RCU_AF);    /* configure CAN0 GPIO */    gpio_init(CAN0RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN0RX_PIN);    gpio_init(CAN0TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN0TX_PIN);    gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP, ENABLE);}void can1_gpio_config(void){    /* enable CAN1 clock */    rcu_periph_clock_enable(RCU_CAN1);    rcu_periph_clock_enable(CAN1RX_CLOCK);    rcu_periph_clock_enable(RCU_AF);    /* configure CAN1 GPIO */    gpio_init(CAN1RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN1RX_PIN);    gpio_init(CAN1TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN1TX_PIN);    gpio_pin_remap_config(GPIO_CAN1_REMAP, ENABLE);}void can2_gpio_config(void){    /* enable CAN2 clock */    rcu_periph_clock_enable(RCU_CAN2);    rcu_periph_clock_enable(CAN2RX_CLOCK);    rcu_periph_clock_enable(RCU_AF);    /* configure CAN2 GPIO */    gpio_init(CAN2RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN2RX_PIN);    gpio_init(CAN2TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN2TX_PIN);    gpio_afio_port_config(AFIO_PB10_CAN2_CFG, ENABLE);    gpio_afio_port_config(AFIO_PB11_CAN2_CFG, ENABLE);}

1.2 CAN配置

CAN配置除了CAN本身的参数,还需要注意接收过滤器的分配,如下图所示,CAN0和CAN1共用28个过滤器,CAN2独立使用14个过滤器。

在这里插入图片描述

CAN配置参考代码如下:

void can0_config(void){    can_parameter_struct can_parameter;    can_fdframe_struct can_fd_parameter;    can_fd_tdc_struct can_fd_tdc_parameter;    can_filter_parameter_struct can_filter;    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);    /* initialize CAN register */    can_deinit(CAN0);#if 0  // CAN配置    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = DISABLE;    can_parameter.rec_fifo_overwrite = DISABLE;    can_parameter.trans_fifo_order = DISABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 仲裁段波特率 = 90M / 9 / (1 + 7 + 2) = 1M */    /* configure CAN baud rate 1MBps, sample point at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;  // TSG1    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;  // TSG2    can_parameter.prescaler = 9U;                   // 分频系数    /* initialize CAN */    can_init(CAN0, &can_parameter);#else  // CANFD配置    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = ENABLE;    can_parameter.rec_fifo_overwrite = ENABLE;    can_parameter.trans_fifo_order = ENABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* baudrate 1Mbps, sample piont at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;    can_parameter.prescaler = 9U;    /* initialize CAN */    can_init(CAN0, &can_parameter);    can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);    can_fd_parameter.fd_frame = ENABLE;    can_fd_parameter.excp_event_detect = ENABLE;    can_fd_parameter.delay_compensation = ENABLE;    can_fd_tdc_parameter.tdc_filter = 0x04U;    can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;    can_fd_tdc_parameter.tdc_offset = 0x04U;    can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;    can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;    can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 数据段波特率 = 90M / 3 / (1 + 4 + 1) = 5M */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_4TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 3;                    // 分频系数    /* initialize CAN-FD */    can_fd_init(CAN0, &can_fd_parameter);#endif    /* initialize filter */    /* configure filter mode */    can_filter.filter_mode = CAN_FILTERMODE_MASK;    can_filter.filter_bits = CAN_FILTERBITS_32BIT;    /* configure filter ID */    can_filter.filter_list_high = 0x0000U;    can_filter.filter_list_low = 0x0000U;    /* configure filter mask */    can_filter.filter_mask_high = 0x0000U;    can_filter.filter_mask_low = 0x0000U;    /* select receiver fifo */    can_filter.filter_fifo_number = CAN_FIFO0;    can_filter.filter_number = 0U;    can_filter.filter_enable = ENABLE;    can_filter_init(CAN0, &can_filter);    /* configure CAN0 NVIC */    nvic_irq_enable(CAN0_RX0_IRQn, 0U, 0U);    /* enable can receive FIFO0 not empty interrupt */    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);}void can1_config(void){    can_parameter_struct can_parameter;    can_fdframe_struct can_fd_parameter;    can_fd_tdc_struct can_fd_tdc_parameter;    can_filter_parameter_struct can_filter;    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);    /* initialize CAN register */    can_deinit(CAN1);    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = ENABLE;    can_parameter.rec_fifo_overwrite = ENABLE;       can_parameter.trans_fifo_order = ENABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 仲裁段波特率 = 90M / 9 / (1 + 7 + 2) = 1M */    /* CAN采样率 = (1 + TSG1) / (1 + TSG1 + TSG2) = (1 + 7) / (1 + 7 + 2) = 80% */    /* baudrate 1Mbps, sample piont at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;  // TSG1    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;  // TSG2    can_parameter.prescaler = 9U;                   // 分频系数    /* initialize CAN */    can_init(CAN1, &can_parameter);    can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);    can_fd_parameter.fd_frame = ENABLE;    can_fd_parameter.excp_event_detect = ENABLE;    can_fd_parameter.delay_compensation = ENABLE;    can_fd_tdc_parameter.tdc_filter = 0x04U;    can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;    can_fd_tdc_parameter.tdc_offset = 0x04U;    can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;    can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;    can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */#if 1    /* 数据段波特率 = 90M / 3 / (1 + 4 + 1) = 5M */    /* CAN采样率 = (1 + TSG1) / (1 + TSG1 + TSG2) = (1 + 4) / (1 + 4 + 1) = 83.3% */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_4TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 3;                    // 分频系数#else    /* 数据段波特率 = 90M / 2 / (1 + 6 + 2) = 5M */    /* CAN采样率 = (1 + TSG1) / (1 + TSG1 + TSG2) = (1 + 6) / (1 + 6 + 2) = 77.77% */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_7TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 2;                    // 分频系数#endif    /* initialize CAN-FD */    can_fd_init(CAN1, &can_fd_parameter);    /* initialize filter */    /* configure filter mode */    can_filter.filter_mode = CAN_FILTERMODE_MASK;    can_filter.filter_bits = CAN_FILTERBITS_32BIT;    /* configure filter ID */    can_filter.filter_list_high = 0x0000U;    can_filter.filter_list_low = 0x0000U;    /* configure filter mask */    can_filter.filter_mask_high = 0x0000U;    can_filter.filter_mask_low = 0x0000U;    /* select receiver fifo */    can_filter.filter_fifo_number = CAN_FIFO1;      can_filter.filter_number = 15U;  // CAN_FCTL默认定义了CAN0和CAN1过滤器序号的分配数量,CAN0使用0-13序号,CAN1使用14-27,可以通过can1_filter_start_bank()修改    can_filter.filter_enable = ENABLE;    can_filter_init(CAN1, &can_filter);    /* configure CAN1 NVIC */    nvic_irq_enable(CAN1_RX1_IRQn, 1U, 1U);    /* enable can receive FIFO0 not empty interrupt */    can_interrupt_enable(CAN1, CAN_INTEN_RFNEIE1);}void can2_config(void){    can_parameter_struct can_parameter;    can_fdframe_struct can_fd_parameter;    can_fd_tdc_struct can_fd_tdc_parameter;    can_filter_parameter_struct can_filter;    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);    /* initialize CAN register */    can_deinit(CAN2);    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = ENABLE;    can_parameter.rec_fifo_overwrite = ENABLE;    can_parameter.trans_fifo_order = ENABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* baudrate 1Mbps, sample piont at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;    can_parameter.prescaler = 9U;    /* initialize CAN */    can_init(CAN2, &can_parameter);    can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);    can_fd_parameter.fd_frame = ENABLE;    can_fd_parameter.excp_event_detect = ENABLE;    can_fd_parameter.delay_compensation = ENABLE;    can_fd_tdc_parameter.tdc_filter = 0x04U;    can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;    can_fd_tdc_parameter.tdc_offset = 0x04U;    can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;    can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;    can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 数据段波特率 = 90M / 3 / (1 + 4 + 1) = 5M */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_4TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 3;                    // 分频系数    /* initialize CAN-FD */    can_fd_init(CAN2, &can_fd_parameter);    /* initialize filter */    /* configure filter mode */    can_filter.filter_mode = CAN_FILTERMODE_MASK;    can_filter.filter_bits = CAN_FILTERBITS_32BIT;    /* configure filter ID */    can_filter.filter_list_high = 0x0000U;    can_filter.filter_list_low = 0x0000U;    /* configure filter mask */    can_filter.filter_mask_high = 0x0000U;    can_filter.filter_mask_low = 0x0000U;    /* select receiver fifo */    can_filter.filter_fifo_number = CAN_FIFO0;    can_filter.filter_number = 1U;    can_filter.filter_enable = ENABLE;    can_filter_init(CAN2, &can_filter);    /* configure CAN2 NVIC */    nvic_irq_enable(CAN2_RX0_IRQn, 0U, 0U);    /* enable can receive FIFO0 not empty interrupt */    can_interrupt_enable(CAN2, CAN_INTEN_RFNEIE0);}

1.3 CAN发送

CAN发送参考代码如下:

typedef struct{    uint32_t id;           // CAN ID    uint8_t frame_format;  // format of frame | 0:standard | 1:extended format    uint8_t can_type;      // CAN type | 0:CAN | 1:CANFD | 2:CANFD加速    uint8_t buf[64];       // CAN buf    uint8_t buf_len;       // CAN buf len} can_trasnmit_data_t;int can_send_message(uint8_t ch, can_trasnmit_data_t can_data){    uint8_t i;    can_trasnmit_message_struct *can_tx_message;    switch (ch)    {    case 0:    #ifdef CAN0_ENABLE        can_tx_message = &can0_tx_message;    #endif        break;    case 1:    #ifdef CAN1_ENABLE        can_tx_message = &can1_tx_message;    #endif        break;    case 2:    #ifdef CAN2_ENABLE        can_tx_message = &can2_tx_message;    #endif        break;    default:        break;    }    if(can_data.frame_format == 0)    {// 标准帧        can_tx_message->tx_sfid = can_data.id;    }    else    {// 扩展帧        can_tx_message->tx_efid = can_data.id;    }    if(can_data.can_type == 0)    {// CAN        can_tx_message->fd_flag = 0;        can_tx_message->fd_brs = 0;    }    else if(can_data.can_type == 1)    {// CANFD        can_tx_message->fd_flag = 1;    }    else if(can_data.can_type == 2)    {// CANFD加速        can_tx_message->fd_flag = 1;        can_tx_message->fd_brs = 1;    }    can_tx_message->fd_esi = 0;    memcpy(can_tx_message->tx_data, can_data.buf, can_data.buf_len);    // CANFD模式下,数据长度只能为0 - 8, 12, 16, 20, 24, 32, 48, 64    if(can_data.buf_len > 48)    {           can_tx_message->tx_dlen = 64;    }       else if(can_data.buf_len > 32)    {        can_tx_message->tx_dlen = 48;    }    else if(can_data.buf_len > 24)    {        can_tx_message->tx_dlen = 32;    }    else if(can_data.buf_len > 20)    {        can_tx_message->tx_dlen = 24;    }    else if(can_data.buf_len > 16)    {        can_tx_message->tx_dlen = 20;    }    else if(can_data.buf_len > 12)    {        can_tx_message->tx_dlen = 16;    }    else if(can_data.buf_len > 8)    {        can_tx_message->tx_dlen = 12;    }    else    {        can_tx_message->tx_dlen = can_data.buf_len;    }#if 1    printf("rn can(%d) transmit data(id: 0x%x): ", ch, can_tx_message->tx_sfid);    for(i = 0U; i < can_tx_message->tx_dlen; i++)     {        printf(" %02x", can_tx_message->tx_data[i]);    }#endif    /* transmit message */    if(can_message_transmit(CAN2, can_tx_message) != CAN_NOMAILBOX)    {// 发送成功        return 1;    }    return 0;}

1.4 CAN接收

CAN接收参考代码如下:

void CAN0_RX0_IRQHandler(void){    /* check the receive message */    can_message_receive(CAN0, CAN_FIFO0, &can0_rx_message);#if 1    printf("rn can0 receive(id=0x%X) data: ", can0_rx_message.rx_sfid);    for(int i = 0U; i < can0_rx_message.rx_dlen; i++)     {        printf(" %02x", can0_rx_message.rx_data[i]);    }#endif}void CAN1_RX1_IRQHandler(void){    /* check the receive message */    can_message_receive(CAN1, CAN_FIFO1, &can1_rx_message);#if 1    printf("rn can1 receive(id=0x%X) data: ", can1_rx_message.rx_sfid);    for(int i = 0U; i < can1_rx_message.rx_dlen; i++)     {        printf(" %02x", can1_rx_message.rx_data[i]);    }#endif}void CAN2_RX0_IRQHandler(void){    /* check the receive message */    can_message_receive(CAN2, CAN_FIFO0, &can2_rx_message);#if 1    printf("rn can2 receive(id=0x%X) data: ", can2_rx_message.rx_sfid);    for(int i = 0U; i < can2_rx_message.rx_dlen; i++)     {        printf(" %02x", can2_rx_message.rx_data[i]);    }#endif}

2 代码编写

参考代码如下:

can.c:

#include "main.h"#include "can.h"#include "string.h"// CAN收发缓存#ifdef CAN0_ENABLEcan_trasnmit_message_struct can0_tx_message;can_receive_message_struct can0_rx_message;#endif#ifdef CAN1_ENABLEcan_trasnmit_message_struct can1_tx_message;can_receive_message_struct can1_rx_message;#endif#ifdef CAN2_ENABLEcan_trasnmit_message_struct can2_tx_message;can_receive_message_struct can2_rx_message;#endif#ifdef CAN0_ENABLEvoid can0_gpio_config(void){    /* enable CAN0 clock */    rcu_periph_clock_enable(RCU_CAN0);    rcu_periph_clock_enable(CAN0RX_CLOCK);    rcu_periph_clock_enable(RCU_AF);    /* configure CAN0 GPIO */    gpio_init(CAN0RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN0RX_PIN);    gpio_init(CAN0TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN0TX_PIN);    gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP, ENABLE);}void can0_config(void){    can_parameter_struct can_parameter;    can_fdframe_struct can_fd_parameter;    can_fd_tdc_struct can_fd_tdc_parameter;    can_filter_parameter_struct can_filter;    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);    /* initialize CAN register */    can_deinit(CAN0);#if 0  // CAN配置    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = DISABLE;    can_parameter.rec_fifo_overwrite = DISABLE;    can_parameter.trans_fifo_order = DISABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 仲裁段波特率 = 90M / 9 / (1 + 7 + 2) = 1M */    /* configure CAN baud rate 1MBps, sample point at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;  // TSG1    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;  // TSG2    can_parameter.prescaler = 9U;                   // 分频系数    /* initialize CAN */    can_init(CAN0, &can_parameter);#else  // CANFD配置    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = ENABLE;    can_parameter.rec_fifo_overwrite = ENABLE;    can_parameter.trans_fifo_order = ENABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* baudrate 1Mbps, sample piont at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;    can_parameter.prescaler = 9U;    /* initialize CAN */    can_init(CAN0, &can_parameter);    can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);    can_fd_parameter.fd_frame = ENABLE;    can_fd_parameter.excp_event_detect = ENABLE;    can_fd_parameter.delay_compensation = ENABLE;    can_fd_tdc_parameter.tdc_filter = 0x04U;    can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;    can_fd_tdc_parameter.tdc_offset = 0x04U;    can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;    can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;    can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 数据段波特率 = 90M / 3 / (1 + 4 + 1) = 5M */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_4TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 3;                    // 分频系数    /* initialize CAN-FD */    can_fd_init(CAN0, &can_fd_parameter);#endif    /* initialize filter */    /* configure filter mode */    can_filter.filter_mode = CAN_FILTERMODE_MASK;    can_filter.filter_bits = CAN_FILTERBITS_32BIT;    /* configure filter ID */    can_filter.filter_list_high = 0x0000U;    can_filter.filter_list_low = 0x0000U;    /* configure filter mask */    can_filter.filter_mask_high = 0x0000U;    can_filter.filter_mask_low = 0x0000U;    /* select receiver fifo */    can_filter.filter_fifo_number = CAN_FIFO0;    can_filter.filter_number = 0U;    can_filter.filter_enable = ENABLE;    can_filter_init(CAN0, &can_filter);    /* configure CAN0 NVIC */    nvic_irq_enable(CAN0_RX0_IRQn, 0U, 0U);    /* enable can receive FIFO0 not empty interrupt */    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);}void CAN0_RX0_IRQHandler(void){    /* check the receive message */    can_message_receive(CAN0, CAN_FIFO0, &can0_rx_message);#if 1    printf("rn can0 receive(id=0x%X) data: ", can0_rx_message.rx_sfid);    for(int i = 0U; i < can0_rx_message.rx_dlen; i++)     {        printf(" %02x", can0_rx_message.rx_data[i]);    }#endif}#endif#ifdef CAN1_ENABLEvoid can1_gpio_config(void){    /* enable CAN1 clock */    rcu_periph_clock_enable(RCU_CAN1);    rcu_periph_clock_enable(CAN1RX_CLOCK);    rcu_periph_clock_enable(RCU_AF);    /* configure CAN1 GPIO */    gpio_init(CAN1RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN1RX_PIN);    gpio_init(CAN1TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN1TX_PIN);    gpio_pin_remap_config(GPIO_CAN1_REMAP, ENABLE);}void can1_config(void){    can_parameter_struct can_parameter;    can_fdframe_struct can_fd_parameter;    can_fd_tdc_struct can_fd_tdc_parameter;    can_filter_parameter_struct can_filter;    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);    /* initialize CAN register */    can_deinit(CAN1);    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = ENABLE;    can_parameter.rec_fifo_overwrite = ENABLE;       can_parameter.trans_fifo_order = ENABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 仲裁段波特率 = 90M / 9 / (1 + 7 + 2) = 1M */    /* CAN采样率 = (1 + TSG1) / (1 + TSG1 + TSG2) = (1 + 7) / (1 + 7 + 2) = 80% */    /* baudrate 1Mbps, sample piont at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;  // TSG1    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;  // TSG2    can_parameter.prescaler = 9U;                   // 分频系数    /* initialize CAN */    can_init(CAN1, &can_parameter);    can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);    can_fd_parameter.fd_frame = ENABLE;    can_fd_parameter.excp_event_detect = ENABLE;    can_fd_parameter.delay_compensation = ENABLE;    can_fd_tdc_parameter.tdc_filter = 0x04U;    can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;    can_fd_tdc_parameter.tdc_offset = 0x04U;    can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;    can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;    can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */#if 1    /* 数据段波特率 = 90M / 3 / (1 + 4 + 1) = 5M */    /* CAN采样率 = (1 + TSG1) / (1 + TSG1 + TSG2) = (1 + 4) / (1 + 4 + 1) = 83.3% */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_4TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 3;                    // 分频系数#else    /* 数据段波特率 = 90M / 2 / (1 + 6 + 2) = 5M */    /* CAN采样率 = (1 + TSG1) / (1 + TSG1 + TSG2) = (1 + 6) / (1 + 6 + 2) = 77.77% */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_7TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 2;                    // 分频系数#endif    /* initialize CAN-FD */    can_fd_init(CAN1, &can_fd_parameter);    /* initialize filter */    /* configure filter mode */    can_filter.filter_mode = CAN_FILTERMODE_MASK;    can_filter.filter_bits = CAN_FILTERBITS_32BIT;    /* configure filter ID */    can_filter.filter_list_high = 0x0000U;    can_filter.filter_list_low = 0x0000U;    /* configure filter mask */    can_filter.filter_mask_high = 0x0000U;    can_filter.filter_mask_low = 0x0000U;    /* select receiver fifo */    can_filter.filter_fifo_number = CAN_FIFO1;      can_filter.filter_number = 15U;  // CAN_FCTL默认定义了CAN0和CAN1过滤器序号的分配数量,CAN0使用0-13序号,CAN1使用14-27,可以通过can1_filter_start_bank()修改    can_filter.filter_enable = ENABLE;    can_filter_init(CAN1, &can_filter);    /* configure CAN1 NVIC */    nvic_irq_enable(CAN1_RX1_IRQn, 1U, 1U);    /* enable can receive FIFO0 not empty interrupt */    can_interrupt_enable(CAN1, CAN_INTEN_RFNEIE1);}void CAN1_RX1_IRQHandler(void){    /* check the receive message */    can_message_receive(CAN1, CAN_FIFO1, &can1_rx_message);#if 1    printf("rn can1 receive(id=0x%X) data: ", can1_rx_message.rx_sfid);    for(int i = 0U; i < can1_rx_message.rx_dlen; i++)     {        printf(" %02x", can1_rx_message.rx_data[i]);    }#endif}#endif#ifdef CAN2_ENABLEvoid can2_gpio_config(void){    /* enable CAN2 clock */    rcu_periph_clock_enable(RCU_CAN2);    rcu_periph_clock_enable(CAN2RX_CLOCK);    rcu_periph_clock_enable(RCU_AF);    /* configure CAN2 GPIO */    gpio_init(CAN2RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN2RX_PIN);    gpio_init(CAN2TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN2TX_PIN);    gpio_afio_port_config(AFIO_PB10_CAN2_CFG, ENABLE);    gpio_afio_port_config(AFIO_PB11_CAN2_CFG, ENABLE);}void can2_config(void){    can_parameter_struct can_parameter;    can_fdframe_struct can_fd_parameter;    can_fd_tdc_struct can_fd_tdc_parameter;    can_filter_parameter_struct can_filter;    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);    /* initialize CAN register */    can_deinit(CAN2);    /* initialize CAN parameters */    can_parameter.time_triggered = DISABLE;    can_parameter.auto_bus_off_recovery = DISABLE;    can_parameter.auto_wake_up = DISABLE;    can_parameter.auto_retrans = ENABLE;    can_parameter.rec_fifo_overwrite = ENABLE;    can_parameter.trans_fifo_order = ENABLE;    can_parameter.working_mode = CAN_NORMAL_MODE;    /* baudrate 1Mbps, sample piont at 80% */    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;    can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;    can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;    can_parameter.prescaler = 9U;    /* initialize CAN */    can_init(CAN2, &can_parameter);    can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);    can_fd_parameter.fd_frame = ENABLE;    can_fd_parameter.excp_event_detect = ENABLE;    can_fd_parameter.delay_compensation = ENABLE;    can_fd_tdc_parameter.tdc_filter = 0x04U;    can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;    can_fd_tdc_parameter.tdc_offset = 0x04U;    can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;    can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;    can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;    /* CAN波特率 = 时钟频率 / 分频系数 / (1 + TSG1 + TSG2) */    /* 数据段波特率 = 90M / 3 / (1 + 4 + 1) = 5M */    can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;    can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_4TQ;  // TSG1    can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;  // TSG2    /* CAN-FD data segement prescaler should be the same as non-data segement prescaler */    can_fd_parameter.data_prescaler = 3;                    // 分频系数    /* initialize CAN-FD */    can_fd_init(CAN2, &can_fd_parameter);    /* initialize filter */    /* configure filter mode */    can_filter.filter_mode = CAN_FILTERMODE_MASK;    can_filter.filter_bits = CAN_FILTERBITS_32BIT;    /* configure filter ID */    can_filter.filter_list_high = 0x0000U;    can_filter.filter_list_low = 0x0000U;    /* configure filter mask */    can_filter.filter_mask_high = 0x0000U;    can_filter.filter_mask_low = 0x0000U;    /* select receiver fifo */    can_filter.filter_fifo_number = CAN_FIFO0;    can_filter.filter_number = 1U;    can_filter.filter_enable = ENABLE;    can_filter_init(CAN2, &can_filter);    /* configure CAN2 NVIC */    nvic_irq_enable(CAN2_RX0_IRQn, 0U, 0U);    /* enable can receive FIFO0 not empty interrupt */    can_interrupt_enable(CAN2, CAN_INTEN_RFNEIE0);}void CAN2_RX0_IRQHandler(void){    /* check the receive message */    can_message_receive(CAN2, CAN_FIFO0, &can2_rx_message);#if 1    printf("rn can2 receive(id=0x%X) data: ", can2_rx_message.rx_sfid);    for(int i = 0U; i < can2_rx_message.rx_dlen; i++)     {        printf(" %02x", can2_rx_message.rx_data[i]);    }#endif}#endif#if defined (CAN0_ENABLE) || defined (CAN1_ENABLE) || defined (CAN2_ENABLE)int can_send_message(uint8_t ch, can_trasnmit_data_t can_data){    uint8_t i;    can_trasnmit_message_struct *can_tx_message;    switch (ch)    {    case 0:    #ifdef CAN0_ENABLE        can_tx_message = &can0_tx_message;    #endif        break;    case 1:    #ifdef CAN1_ENABLE        can_tx_message = &can1_tx_message;    #endif        break;    case 2:    #ifdef CAN2_ENABLE        can_tx_message = &can2_tx_message;    #endif        break;    default:        break;    }    if(can_data.frame_format == 0)    {// 标准帧        can_tx_message->tx_sfid = can_data.id;    }    else    {// 扩展帧        can_tx_message->tx_efid = can_data.id;    }    if(can_data.can_type == 0)    {// CAN        can_tx_message->fd_flag = 0;        can_tx_message->fd_brs = 0;    }    else if(can_data.can_type == 1)    {// CANFD        can_tx_message->fd_flag = 1;    }    else if(can_data.can_type == 2)    {// CANFD加速        can_tx_message->fd_flag = 1;        can_tx_message->fd_brs = 1;    }    can_tx_message->fd_esi = 0;    memcpy(can_tx_message->tx_data, can_data.buf, can_data.buf_len);    // CANFD模式下,数据长度只能为0 - 8, 12, 16, 20, 24, 32, 48, 64    if(can_data.buf_len > 48)    {           can_tx_message->tx_dlen = 64;    }       else if(can_data.buf_len > 32)    {        can_tx_message->tx_dlen = 48;    }    else if(can_data.buf_len > 24)    {        can_tx_message->tx_dlen = 32;    }    else if(can_data.buf_len > 20)    {        can_tx_message->tx_dlen = 24;    }    else if(can_data.buf_len > 16)    {        can_tx_message->tx_dlen = 20;    }    else if(can_data.buf_len > 12)    {        can_tx_message->tx_dlen = 16;    }    else if(can_data.buf_len > 8)    {        can_tx_message->tx_dlen = 12;    }    else    {        can_tx_message->tx_dlen = can_data.buf_len;    }#if 1    printf("rn can(%d) transmit data(id: 0x%x): ", ch, can_tx_message->tx_sfid);    for(i = 0U; i < can_tx_message->tx_dlen; i++)     {        printf(" %02x", can_tx_message->tx_data[i]);    }#endif    /* transmit message */    if(can_message_transmit(CAN2, can_tx_message) != CAN_NOMAILBOX)    {// 发送成功        return 1;    }    return 0;}#endifvoid can_tx_test(void){    uint8_t i;    can_trasnmit_data_t can_data;    for (i = 0; i < 64; i++)    {        can_data.buf[i] = i;    }#ifdef CAN0_ENABLE    can_data.id = 0x123;    can_data.frame_format = 0;  // 标准帧    can_data.can_type = 0;      // CAN    can_data.buf_len = 8;       // 数据长度    can_send_message(0, can_data);#endif#ifdef CAN1_ENABLE    can_data.id = 0x456;    can_data.frame_format = 0;  // 标准帧    can_data.can_type = 1;      // CANFD    can_data.buf_len = 16;      // 数据长度    can_send_message(1, can_data);#endif#ifdef CAN2_ENABLE    can_data.id = 0x789;    can_data.frame_format = 0;  // 标准帧    can_data.can_type = 2;      // CANFD加速    can_data.buf_len = 64;      // 数据长度    can_send_message(2, can_data);#endif}void can_user_init(void){#ifdef CAN0_ENABLE    // CAN0 init    can0_gpio_config();    can0_config();    /* initialize can0 transmit message */    can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &can0_tx_message);    /* initialize can0 receive message */    can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &can0_rx_message);#endif#ifdef CAN1_ENABLE    // CAN1 init    can1_gpio_config();    can1_config();    /* initialize can1 transmit message */    can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &can1_tx_message);    /* initialize can1 receive message */    can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &can1_rx_message);#endif#ifdef CAN2_ENABLE    // CAN2 init    can2_gpio_config();    can2_config();    /* initialize can2 transmit message */    can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &can2_tx_message);    /* initialize can2 receive message */    can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &can2_rx_message);#endif    printf("can init successrn");}

can.h:

#ifndef __CAN_HANDLE_H#define __CAN_HANDLE_H#include "gd32e50x_can.h"#define CAN0_ENABLE#define CAN1_ENABLE#define CAN2_ENABLE#define CAN0RX_CLOCK  RCU_GPIOB#define CAN0RX_PORT   GPIOB#define CAN0RX_PIN    GPIO_PIN_8#define CAN0TX_CLOCK  RCU_GPIOB#define CAN0TX_PORT   GPIOB#define CAN0TX_PIN    GPIO_PIN_9#define CAN1RX_CLOCK  RCU_GPIOB#define CAN1RX_PORT   GPIOB#define CAN1RX_PIN    GPIO_PIN_5#define CAN1TX_CLOCK  RCU_GPIOB#define CAN1TX_PORT   GPIOB#define CAN1TX_PIN    GPIO_PIN_6#define CAN2RX_CLOCK  RCU_GPIOB#define CAN2RX_PORT   GPIOB#define CAN2RX_PIN    GPIO_PIN_10#define CAN2TX_CLOCK  RCU_GPIOB#define CAN2TX_PORT   GPIOB#define CAN2TX_PIN    GPIO_PIN_11typedef struct{    uint32_t id;           // CAN ID    uint8_t frame_format;  // format of frame | 0:standard | 1:extended format    uint8_t can_type;      // CAN type | 0:CAN | 1:CANFD | 2:CANFD加速    uint8_t buf[64];       // CAN buf    uint8_t buf_len;       // CAN buf len} can_trasnmit_data_t;void can_user_init(void);void can_tx_test(void);#endif

main.c:

#include "main.h"#include "uart.h"#include "can.h"int main(void){    // systick_config();    uart_user_init();    can_user_init();    printf("app init success.n");    can_tx_test();    while(1)    {    }}

3 测试验证

把MCU三路CAN接到一起,并接入CAN盒的同一通道。用CAN盒抓取数据如下图所示,MCU启动后一次通过3路CAN发送不同的数据。

在这里插入图片描述

MCU单路CAN接CAN盒,然后用CAN盒发送数据,MCU接收如下图所示:MCU收到数据并通过串口打印接收log。

在这里插入图片描述

在这里插入图片描述

相关推荐