问答

汇集网友智慧,解决技术难题

21ic问答首页 - GD32F205的CAN1接口引脚问题

CAN 引脚 接口

GD32F205的CAN1接口引脚问题

Liuweixing2026-01-14
我在使用GD32F205RET6器件实现CAN0和CAN1两个接口,实现接收中断,初始化如下:

void CAN_init(void)
{
    can_parameter_struct can_init_struct;
    can_filter_parameter_struct can_filter_struct;
  
    /************************** 1. 使能相关时钟 **************************/
    // 使能GPIOA、GPIOB、AFIO时钟(复用功能依赖AFIO)
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);
    // 使能CAN0和CAN1时钟(CAN1依赖CAN0时钟,手册3.17节)
    rcu_periph_clock_enable(RCU_CAN0);
    rcu_periph_clock_enable(RCU_CAN1);

    /************************** 2. 配置GPIO引脚 **************************/
        // CAN0: PA11 (CAN0_RX), PA12 (CAN0_TX) - 默认引脚配置
                // 注意:RX引脚应该配置为内部上拉输入,而不是浮空输入
                gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);  // TX: 复用推挽输出
                gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_11);    // RX: 内部上拉输入
          // 4. 禁用USBFS(避免与CAN0复用冲突,文档表2-5:PA11=CAN0_RX/USBFS_DM)
//    usbfs_deinit();
                // 如果需要重映射,取消下面的注释
                // gpio_pin_remap_config(GPIO_CAN0_FULL_REMAP, ENABLE);
                // CAN1: PB12 (CAN1_RX), PB13 (CAN1_TX) - 默认引脚配置
                gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);  // TX: 复用推挽输出
                gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_12);     // RX: 内部上拉输入
          // 4. 禁用SPI1/I2C1(避免与CAN1复用冲突,文档表2-5:PB12=CAN1_RX/SPI1_NSS)
    spi_disable(SPI1);
    i2c_deinit(I2C1);
        // 如果需要重映射,取消下面的注释
        // gpio_pin_remap_config(GPIO_CAN1_REMAP, ENABLE);  
    /************************** 3. 复位CAN控制器 **************************/
    can_deinit(CAN0);
    can_deinit(CAN1);

    /************************** 4. 配置CAN0(主控制器) **************************/
    can_struct_para_init(CAN_INIT_STRUCT, &can_init_struct);
    // 工作模式:正常模式,自动重传,FIFO锁定(满后丢弃新帧)
    can_init_struct.auto_bus_off_recovery = ENABLE;
    can_init_struct.working_mode = CAN_NORMAL_MODE;
    can_init_struct.auto_bus_off_recovery = ENABLE;
    can_init_struct.time_triggered = DISABLE;
          can_init_struct.auto_bus_off_recovery = ENABLE;
          can_init_struct.auto_wake_up = DISABLE;
          can_init_struct.auto_retrans = ENABLE;  // 使能自动重传
          can_init_struct.rec_fifo_overwrite = ENABLE;  // 允许FIFO覆盖
          can_init_struct.trans_fifo_order = DISABLE;
    // 波特率配置:系统时钟120MHz → APB1分频2 → APB1时钟60MHz(手册5.3.2节)
    // 波特率=60MHz / [(BRP+1)*(1+TS1+TS2)] = 1Mbps → (BRP+1)*(1+TS1+TS2)=60
    // 选择:BRP=4(0x04),TS1=10(0x0A,对应11TQ),TS2=1(0x01,对应2TQ)

                can_init_struct.resync_jump_width = CAN_BT_SJW_1TQ;//
    can_init_struct.time_segment_1 = CAN_BT_BS1_9TQ; //
    can_init_struct.time_segment_2 = CAN_BT_BS2_2TQ; //
    can_init_struct.prescaler = 5; //

    can_init(CAN0, &can_init_struct);

    /************************** 5. 配置CAN1(扩展控制器) **************************/
    // CAN1复用CAN0的波特率配置(手册26.4节:CAN1无独立BRP寄存器)
    can_struct_para_init(CAN_INIT_STRUCT, &can_init_struct);
                can_init_struct.working_mode = CAN_NORMAL_MODE;
    can_init_struct.auto_bus_off_recovery = ENABLE;
    can_init_struct.time_triggered = DISABLE;
          can_init_struct.auto_bus_off_recovery = ENABLE;
          can_init_struct.auto_wake_up = DISABLE; //gai
          can_init_struct.auto_retrans = ENABLE;  // 使能自动重传
          can_init_struct.rec_fifo_overwrite = ENABLE;  // 允许FIFO覆盖
          can_init_struct.trans_fifo_order = DISABLE;
               
    can_init(CAN1, &can_init_struct);
//                can_working_mode_set(CAN1, CAN_NORMAL_MODE);
    /************************** 6. 配置过滤器(手册26.3.5节) **************************/
    // 过滤器组0 → 分配给CAN0,映射到FIFO0,接收所有ID
    //can_filter_struct_init(&can_filter_struct);
                can_struct_para_init(CAN_FILTER_STRUCT, &can_filter_struct);
    can_filter_struct.filter_mode = CAN_FILTERMODE_MASK;
    can_filter_struct.filter_bits = CAN_FILTERBITS_32BIT;
    can_filter_struct.filter_list_high = 0x0000;
    can_filter_struct.filter_list_low = 0x0000;
    can_filter_struct.filter_mask_high = 0x0000;
    can_filter_struct.filter_mask_low = 0x0000;
    can_filter_struct.filter_number = 0;
    can_filter_struct.filter_enable = ENABLE;
    can_filter_struct.filter_fifo_number = CAN_FIFO0;
    can_filter_struct.filter_enable = ENABLE;
    can_filter_init(&can_filter_struct);

    // 过滤器组14 → 分配给CAN1,映射到FIFO1,接收所有ID(手册26.3.5节:14~27组归CAN1)
                can1_filter_start_bank(14);
                can_struct_para_init(CAN_FILTER_STRUCT, &can_filter_struct);
    can_filter_struct.filter_mode = CAN_FILTERMODE_MASK;
    can_filter_struct.filter_bits = CAN_FILTERBITS_32BIT;
    can_filter_struct.filter_list_high = 0x0000;
    can_filter_struct.filter_list_low = 0x0000;
    can_filter_struct.filter_mask_high = 0x0000;
    can_filter_struct.filter_mask_low = 0x0000;
    can_filter_struct.filter_number = 14;
    can_filter_struct.filter_enable = ENABLE;
    can_filter_struct.filter_fifo_number = CAN_FIFO1;
    can_filter_struct.filter_enable = ENABLE;
    can_filter_init(&can_filter_struct);

    /************************** 7. 使能接收FIFO不空中断(手册26.3.9节) **************************/
    // CAN0 FIFO0非空中断
    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
    // CAN1 FIFO1非空中断(依赖CAN0的INTEN寄存器)
    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE1);

    /************************** 8. 配置NVIC中断优先级 **************************/
    nvic_irq_enable(CAN0_RX0_IRQn, 0, 1); // 优先级0,子优先级1
    nvic_irq_enable(CAN1_RX1_IRQn, 1, 0); // 优先级0,子优先级0
}

结果是:CAN0正常,CAN1采用CAN0的FIFO1接收,时钟接收不到数据。现在的问题是
(1)CAN1的RX引脚是PB12,TX引脚是PB13有没有错,DataBook上是这样的,如果采用引脚映射CAN1_RX 可以是PB5,CAN1_TX可以是PB6;
(2)CAN1是否真的不是独立的,而是依赖CAN0的FIFO1来接收数据,并由CAN0的FIFO1不空中断产生中断;
(3)CAN1的接收过滤器与CAN0的过滤器是同一个模块,仅仅是CAN0采用0-13,CAN1采用14-27吗?
回答 +关注 0
281人浏览 1人回答问题 分享 举报
1 个回答
  • GD32F205RET6的CAN1接口接收数据成功了。数天来测试不成功的原因:CAN1的波特率不能设成1000kbps,将其波特率降到400kbps则可以正常收发。为与上行侧的2206主板通信,2206主板的CAN0波特率设为250kbps,ROBOT板的CAN1也设成250kbps,检测上行侧发出的数据包正常。

您需要登录后才可以回复 登录 | 注册