STM32H743 CANFD未配置TDC导致在1M_5M高波特率下数据场信号丢失

调试STM32H743的CANFD时,官方参考代码里面的波特率配置为1M_4M,并且采样点数不满足要求,后面通过配置仲裁场为1M,数据场为5M,示波器观察发现丢失数据场,只有仲裁场,后面查看了MCP2517的配置里面,有一个TDC参数对应STM32H743的HAL_FDCAN_ConfigTxDelayCompensation(发送延迟补偿),使能之后,配置TDC值。

HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);//使能hfdcan1的TDC
HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1,TdcOffset ,TdcFilter);//配置hfdcan1
//TdcOffset = DataTimeSeg1*DataPrescaler 
//TdcFilter的配置可以是0,我暂时配置为和TDCTdcOffset 一致

其中DataTimeSeg1和DataPrescaler的配置如下:可以得到TdcOffset =1*11=11

  hfdcan1.Init.NominalPrescaler = 1;
  hfdcan1.Init.NominalSyncJumpWidth = 12;
  hfdcan1.Init.NominalTimeSeg1 = 67;
  hfdcan1.Init.NominalTimeSeg2 = 12;
  hfdcan1.Init.DataPrescaler = 1;
  hfdcan1.Init.DataSyncJumpWidth = 4;
  hfdcan1.Init.DataTimeSeg1 = 11;
  hfdcan1.Init.DataTimeSeg2 = 4;

然后可以通过查看TDC所在寄存器的值,可以查看TDC是否设置成功,设置失败DBTP=0x00000E33,设置成功DBTP=0x00800E33,具体DBTP寄存器的各位请查看STM32H743数据手册

FDCAN_ProtocolStatus_FDCAN1=HAL_FDCAN_GetProtocolStatus(&hfdcan1,&Status_FDCAN1);//查看TDC所在寄存器的值

 

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
帮我优化一下这段代码配置2M波特率CANFD :#include "can.h" #include "gd32c10x.h" #include "gd32c10x_eval.h" void can_gpio_config(void) { rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_CAN1); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); 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_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_5); gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP , ENABLE); gpio_pin_remap_config(GPIO_CAN1_REMAP, ENABLE); } void can_config(void) { can_parameter_struct can_parameter; can_fdframe_struct can_fd_parameter; can_fd_tdc_struct can_fd_tdc_parameter; can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); can_deinit(CAN0); can_deinit(CAN1); 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 = DISABLE; can_parameter.trans_fifo_order = DISABLE; can_parameter.working_mode = CAN_NORMAL_MODE; can_init(CAN0, &can_parameter); can_init(CAN1, &can_parameter); can_frequency_set(CAN0, CAN_BAUD_RATE); can_frequency_set(CAN1, CAN_BAUD_RATE); 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_init(CAN1, &can_fd_parameter); can_fd_frequency_set(CAN0, CANFD_BAUD_RATE); can_fd_frequency_set(CAN1, CANFD_BAUD_RATE); can1_filter_start_bank(14); can_filter_mask_mode_init(DEV_CAN0_ID, DEV_CAN0_MASK, CAN_EXTENDED_FIFO0, 0); can_filter_mask_mode_init(DEV_CAN1_ID, DEV_CAN1_MASK, CAN_EXTENDED_FIFO0, 15); nvic_irq_enable(CAN0_RX0_IRQn, 7, 0); nvic_irq_enable(CAN1_RX0_IRQn, 7, 0); can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0); can_interrupt_enable(CAN1, CAN_INTEN_RFNEIE0); }
05-31
可以将函数can_gpio_config()和can_config()的代码分别进行优化,具体优化如下: 1. can_gpio_config()优化: 将rcu_periph_clock_enable(RCU_GPIOB)和rcu_periph_clock_enable(RCU_AF)放到函数外部进行调用,减少函数内部的代码量。 将GPIO初始化的代码放到一个数组中,使用循环语句进行初始化,减少代码行数,提代码可读性。 优化后的代码如下: ``` void can_gpio_config(void) { /* 这两个语句可以放到函数外部进行调用 */ rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_CAN1); /* GPIOB时钟和复用功能时钟在函数外部调用 */ gpio_init_parameter_struct gpio_init_struct[4] = { {GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_8}, {GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9}, {GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_5}, {GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6} }; for(int i = 0; i < 4; i++) { gpio_init(&gpio_init_struct[i]); } gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP , ENABLE); gpio_pin_remap_config(GPIO_CAN1_REMAP, ENABLE); } ``` 2. can_config()优化: 将can_init()和can_frequency_set()合并为一个函数进行调用。 将can_fd_init()和can_fd_frequency_set()合并为一个函数进行调用。 将can_filter_mask_mode_init()和can1_filter_start_bank()合并为一个函数进行调用。 优化后的代码如下: ``` void can_config(void) { can_parameter_struct can_parameter; can_fdframe_struct can_fd_parameter; can_fd_tdc_struct can_fd_tdc_parameter; can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); can_deinit(CAN0); can_deinit(CAN1); 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 = DISABLE; can_parameter.trans_fifo_order = DISABLE; can_parameter.working_mode = CAN_NORMAL_MODE; can_init_parameter_struct can_init_struct[2] = { {CAN0, &can_parameter, CAN_BAUD_RATE}, {CAN1, &can_parameter, CAN_BAUD_RATE}, }; for(int i = 0; i < 2; i++) { 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(can_init_struct[i].can_periph, &can_fd_parameter); can_frequency_set(can_init_struct[i].can_periph, can_init_struct[i].baud_rate); can_fd_frequency_set(can_init_struct[i].can_periph, CANFD_BAUD_RATE); } can_filter_mask_mode_struct can_filter_struct[2] = { {DEV_CAN0_ID, DEV_CAN0_MASK, CAN_EXTENDED_FIFO0, 0}, {DEV_CAN1_ID, DEV_CAN1_MASK, CAN_EXTENDED_FIFO0, 15}, }; for(int i = 0; i < 2; i++) { can_filter_mask_mode_init(can_filter_struct[i].can_id, can_filter_struct[i].can_mask, can_filter_struct[i].can_fifo, can_filter_struct[i].can_bank); } can1_filter_start_bank(14); nvic_irq_enable(CAN0_RX0_IRQn, 7, 0); nvic_irq_enable(CAN1_RX0_IRQn, 7, 0); can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0); can_interrupt_enable(CAN1, CAN_INTEN_RFNEIE0); } ``` 经过以上的优化,代码可读性更强,代码行数更少,也更易于维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值