本帖最后由 zhangyh89 于 2021-11-20 15:54 编辑
最近在使用GD32C103的CAN功能,发现用一般的USB转CAN给GD32发指令的话USB转can的上位机经常提示有总线错误,如果发送数据过快还会出现USB转CAN离线的状态,USB转CAN需要重新启动才能继续发数据,但是两个不同类型的USB转CAN护发数据的就不会有问题,试过降低波特率加终端电阻都是会出现这些现象,不知道是不是GD32代码了CAN初始化的问题,还是硬件电路有问题。是否与SJW,BS1,BS2的设置有关,我设置波特率使用的GD32C103库函数自动计算的。
最终解决了,就是采样点的问题,用波特率计算器计算得出的结果进行配置后,can接收完全没有问题了,不过can-fd相关部分还是用的官方库函数的自动计算,can-fd模式下接收还是会偶尔会出现接收错误,这个错误不知道是不是由于使用的can接口芯片不支持超过1M波特率导致,暂时还没验证。附件内为波特兰率计算器
typedef enum
{
CAN_BDR_100K = 0,
CAN_BDR_125K ,
CAN_BDR_250K ,
CAN_BDR_500K ,
CAN_BDR_1000K
}can_bdr_enum;
void can0_gpio_config(void)
{
/* enable CAN clock */
rcu_periph_clock_enable(RCU_CAN0);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_AF);
gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP,ENABLE);
//gpio_pin_remap_config(GPIO_CAN0_FULL_REMAP,ENABLE);
/* configure CAN0 GPIO */
gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,GPIO_PIN_8);
gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9);
/* 终端电阻控制引脚*/
gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_10);
}
void can0_init(can_bdr_enum bdr,int baudrate_fd)
{
can_parameter_struct CAN_InitStructure;
can_fd_tdc_struct can_fd_tdc_parameter;
can_fdframe_struct can_fd_parameter;
rcu_periph_clock_enable(RCU_CAN0);
can_deinit(CAN0);
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &g_transmit_message);
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &g_receive_message);
can0_gpio_config();
if(bdr >= CAN_BDR_1000K)
bdr = CAN_BDR_1000K;
CAN_InitStructure.working_mode= CAN_NORMAL_MODE;
CAN_InitStructure.resync_jump_width= CAN_BT_SJW_1TQ;
CAN_InitStructure.time_segment_1= CAN_BAUDRATE_LIST[bdr].time_segment_1;//CAN_BT_BS1_12TQ;
CAN_InitStructure.time_segment_2= CAN_BAUDRATE_LIST[bdr].time_segment_2;//CAN_BT_BS2_7TQ;
CAN_InitStructure.time_triggered= DISABLE;
CAN_InitStructure.auto_bus_off_recovery= ENABLE;
CAN_InitStructure.auto_wake_up= ENABLE;
CAN_InitStructure.auto_retrans= ENABLE;
CAN_InitStructure.rec_fifo_overwrite= DISABLE;
CAN_InitStructure.trans_fifo_order= ENABLE;
CAN_InitStructure.prescaler= CAN_BAUDRATE_LIST[bdr].prescaler;//3;//CAN0总线的时钟 60M/((1+12+7)*3) = 1000k
can_init(CAN0, &CAN_InitStructure);
if(baudrate_fd != 0)
{
g_canfd_open = 1;
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 = 0x04;
can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;
can_fd_tdc_parameter.tdc_offset = 0x04;
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_fd_init(CAN0, &can_fd_parameter);
can_fd_frequency_set(CAN0, baudrate_fd);
}
//can1_filter_start_bank(14);
can_filter_mask_mode_init(0x001, 0x7FF, CAN_STANDARD_FIFO0, 0);
can_filter_mask_mode_init(0x0FF, 0x7FF, CAN_STANDARD_FIFO0, 1);
/* configure CAN0 NVIC */
nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
nvic_irq_enable(CAN0_TX_IRQn, 0, 0);
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
can_interrupt_enable(CAN0, CAN_INT_TME);
}
|