21ic问答首页 - GD32F205的CAN1接口引脚问题
GD32F205的CAN1接口引脚问题
我在使用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吗?
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
评论
2026-01-23
您需要登录后才可以回复 登录 | 注册