GD32C103单片机CAN通讯导致CAN总线一直报错

        有个项目,需要CAN通讯和USB通讯,F103的片子两者之间有影响,所以查阅资料选择了C103系列的片子。产品开发后,自测没问题,就发给客户使用。

        使用后客户反馈,产品放入总线,一直报错,导致CAN总线异常,影响使用;项目组集中讨论后,最后测试解决,为软件问题。

        CAN通讯初始化的问题!!!!考虑到初次使用该芯片,所有使用官方固件库进行开发,官方CAN初始化函数如下:

/*!
    \brief      initialize CAN function
    \param[in]  none
    \param[out] none
    \retval     none
*/
void can_config(void)
{
    can_parameter_struct can_parameter;
     
    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
    /* initialize CAN register */
    can_deinit(CAN0);
    can_deinit(CAN1);
    
    /* initialize CAN parameters */
    can_parameter.time_triggered = DISABLE;
    can_parameter.auto_bus_off_recovery = DISABLE;
    can_parameter.auto_wake_up = DISABLE;
    can_parameter.auto_retrans = DISABLE;
    can_parameter.rec_fifo_overwrite = DISABLE;
    can_parameter.trans_fifo_order = DISABLE;
    can_parameter.working_mode = CAN_NORMAL_MODE;  
    /* initialize CAN */
    can_init(CAN0, &can_parameter);
    can_init(CAN1, &can_parameter);
    
    /* config CAN0 baud rate */
    can_frequency_set(CAN0, DEV_CAN_BAUD_RATE);
    /* config CAN1 baud rate */
    can_frequency_set(CAN1, DEV_CAN_BAUD_RATE);
    
    /* initialize filter */ 
    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);
    
    /* configure CAN0 NVIC */
    nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
    /* configure CAN1 NVIC */
    nvic_irq_enable(CAN1_RX0_IRQn, 1, 0);
    /* enable can receive FIFO0 not empty interrupt */
    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
    can_interrupt_enable(CAN1, CAN_INTEN_RFNEIE0);
}

        问题出在can_frequency_set()函数,该函数不能设置采样点、同步跳转,导致波特率偏差,接入总线后,就一直报错。所以需要增加采样点、同步跳转的设置

    /*设置采样点、同步跳转*/

    can_parameter.resync_jump_width = CAN_BT_SJW_2TQ;  /*提高位宽容忍度*/
    can_parameter.time_segment_1    = CAN_BT_BS1_11TQ;
    can_parameter.time_segment_2    = CAN_BT_BS2_4TQ;  /*采样点:(BS1+1)/(BS1+BS2+1)=75%*/
    /* initialize CAN */
    can_init(CAN0, &can_parameter);
    
    /* config CAN0 baud rate */
    can_frequency_set(CAN0, DEV_CAN_BAUD_RATE);

        更改配置后,再次接入CAN总线,工作正常。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的基于GD32C103单片机采集LVDT传感器电压、转换为位移量并通过CAN总线输出的代码框架,供参考: ```c #include "gd32f10x.h" #include "can.h" #define LVDT_ADC_CHANNEL ADC_CH_0 #define LVDT_ADC_GPIO_PORT GPIOA #define LVDT_ADC_GPIO_PIN GPIO_PIN_0 #define VREF 3300 // 单位:mV #define LVDT_SENSITIVITY 1 // LVDT传感器灵敏度,单位:mV/mm // 初始化ADC void adc_init(void) { /* 使能GPIOA时钟 */ rcu_periph_clock_enable(RCU_GPIOA); /* 使能ADC时钟 */ rcu_periph_clock_enable(RCU_ADC); /* 配置PA0为模拟输入引脚 */ gpio_mode_set(LVDT_ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, LVDT_ADC_GPIO_PIN); /* 配置ADC时钟分频和工作模式 */ adc_clock_config(ADC_ADCCK_PCLK2_DIV8); adc_mode_config(ADC_MODE_FREE); /* 配置ADC通道为PA0 */ adc_channel_config(LVDT_ADC_CHANNEL, ADC_SAMPLETIME_55POINT5); /* 使能ADC */ adc_enable(); /* 校准ADC */ adc_calibration_enable(); } // 采样LVDT电压并返回对应的位移量,单位:mm float lvdt_volt_to_disp(void) { uint16_t adc_value; float voltage, displacement; /* 配置ADC采样模式为单次转换 */ adc_special_function_config(ADC_SCAN_MODE, DISABLE); adc_special_function_config(ADC_CONTINUOUS_MODE, DISABLE); adc_special_function_config(ADC_DISCONTINUOUS_MODE, DISABLE); adc_special_function_config(ADC_DATA_ALIGN_RIGHT, ENABLE); adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE); /* 开始ADC转换 */ adc_software_trigger_enable(ADC_REGULAR_CHANNEL); /* 等待转换完成 */ while(SET != adc_flag_get(ADC_FLAG_EOC)); /* 读取ADC转换值 */ adc_value = adc_regular_data_read(); /* 计算对应的电压值 */ voltage = (float)adc_value * VREF / 4096; /* 计算对应的位移量 */ displacement = voltage / LVDT_SENSITIVITY; return displacement; } // 初始化CAN总线 void can_init(void) { /* 使能GPIOB时钟 */ rcu_periph_clock_enable(RCU_GPIOB); /* 使能CAN时钟 */ rcu_periph_clock_enable(RCU_CAN0); /* 配置PB8和PB9为复用功能 */ gpio_mode_set(GPIOB, GPIO_MODE_AF_PP, GPIO_PUPD_PULLUP, GPIO_PIN_8); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_8); gpio_mode_set(GPIOB, GPIO_MODE_AF_PP, GPIO_PUPD_PULLUP, GPIO_PIN_9); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_9); /* 配置CAN总线 */ can_deinit(CAN0); can_struct_para_init(CAN_INIT_STRUCT, CAN_TTCM_Mode, DISABLE, CAN_ABOM_State, DISABLE, CAN_AWUM_State, DISABLE, CAN_NART_State, ENABLE, CAN_RFLM_State, DISABLE, CAN_TXFP_State, DISABLE, CAN_Mode, CAN_NORMAL_MODE, CAN_SJW, CAN_SJW_1TQ, CAN_BS1, CAN_BS1_5TQ, CAN_BS2, CAN_BS2_2TQ, 6); can_init(CAN0, &CAN_INIT_STRUCT); } // 发送位移量数据到CAN总线 void send_disp_via_can(float disp) { uint8_t data[8]; uint32_t mailbox; /* 将位移量转换为CAN数据格式 */ int16_t disp_data = (int16_t)(disp * 10); data[0] = disp_data >> 8; data[1] = disp_data & 0xFF; /* 发送数据到CAN总线 */ can_struct_para_init(CAN_TX_MESSAGE_STRUCT, 0, CAN_TX_DATA_FRAME, CAN_STANDARD_ID, 0); CAN_TX_MESSAGE_STRUCT.tx_sfid = 0x123; CAN_TX_MESSAGE_STRUCT.tx_dlen = 2; CAN_TX_MESSAGE_STRUCT.tx_data[0] = data[0]; CAN_TX_MESSAGE_STRUCT.tx_data[1] = data[1]; can_message_transmit(CAN0, &CAN_TX_MESSAGE_STRUCT); } int main(void) { float lvdt_disp; /* 初始化ADC和CAN总线 */ adc_init(); can_init(); while(1) { /* 采样LVDT电压并计算位移量 */ lvdt_disp = lvdt_volt_to_disp(); /* 发送位移量数据到CAN总线 */ send_disp_via_can(lvdt_disp); } } ``` 需要注意的是,上述代码仅供参考,具体实现还需要根据具体硬件平台和实际应用场景进行适当修改和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值