打印

GD32C103的CAN使用问题

[复制链接]
2409|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhangyh89|  楼主 | 2021-11-19 15:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
CAN, TE, pi, IO, ni
本帖最后由 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);
}

无标题.png (76.88 KB )

无标题.png

STM32CANBaudRate.zip

5.07 MB

使用特权

评论回复
沙发
autodash| | 2021-11-19 16:39 | 只看该作者
你把采样点放在75%试试

使用特权

评论回复
板凳
dxfshsh| | 2021-11-19 17:57 | 只看该作者
不推荐使用自动波特率分配,其适配性,不可能做的很好,当您用到CANFD时,更是这样,您需要自己设计一个更加合理的分配方案。

使用特权

评论回复
地板
imdx| | 2021-11-19 21:34 | 只看该作者
GD32E103那个自动计算波特率的函数有bug,不要用。不知道现在GD32C103的库改了没。

使用特权

评论回复
5
zhangyh89|  楼主 | 2021-11-19 23:43 | 只看该作者
imdx 发表于 2021-11-19 21:34
GD32E103那个自动计算波特率的函数有bug,不要用。不知道现在GD32C103的库改了没。 ...

请问有没有可以参靠的常用波特率设置代码,尝试更改BS1,BS2,还有分频,但是设完后完全无法通讯,估计还是设置有问题

使用特权

评论回复
6
zhangyh89|  楼主 | 2021-11-20 00:48 | 只看该作者
现确定了是自动波特率设置的bs1 bs2 swj有问题,改完后好多了不会出现任何错误了
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 CAN_Configuration(void)
{
        can_parameter_struct CAN_InitStructure;
//        can_filter_parameter_struct CAN_FilterInitStructure;
        rcu_periph_clock_enable(RCU_CAN0);
        can_deinit(CAN0);
       
        can0_gpio_config();       
       
        CAN_InitStructure.working_mode= CAN_NORMAL_MODE;
        CAN_InitStructure.resync_jump_width= CAN_BT_SJW_1TQ;
        CAN_InitStructure.time_segment_1= CAN_BT_BS1_12TQ;
        CAN_InitStructure.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=3;//CAN0总线的时钟 60M/((1+12+7)*3) = 1000k
        can_init(CAN0, &CAN_InitStructure);

    can1_filter_start_bank(14);
    can_filter_mask_mode_init(0, 0, CAN_STANDARD_FIFO0, 0);
    /* configure CAN0 NVIC */
    nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
    /* enable can receive FIFO0 not empty interrupt */
    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
}

使用特权

评论回复
7
full_stack| | 2021-11-20 13:45 | 只看该作者
采样率保持一致,

使用特权

评论回复
8
full_stack| | 2021-11-20 13:46 | 只看该作者
这个问题,出现的原因就是不同CAN控制器,采样率不一样,采样点尽量接近。

使用特权

评论回复
9
autodash| | 2021-11-20 18:13 | 只看该作者
GD的demo代码的采样率就是随意来的,去看看nxp,freescale 车规芯片的采样率,那才是正确的。 采样率跟波特率和线长是有很大关系的。 如果你只是在桌面上测测,随便设定就行。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

30

帖子

0

粉丝