[研电赛技术支持] GD32F305 CAN通讯驱动配置

[复制链接]
1690|1
八层楼 发表于 2025-8-12 17:05 | 显示全部楼层 |阅读模式
一、CAN0

查看芯片手册,CAN0的初始化,IO口需要重映射。




#define CAN_BAUDRATE  500

//CAN0引脚定义
#define   CAN0_CLOCK                    RCU_GPIOB
#define   CAN0_GPIO                     GPIOB
#define   CAN0_TX_GPIO_PIN              GPIO_PIN_9
#define   CAN0_RX_GPIO_PIN              GPIO_PIN_8


can_trasnmit_message_struct transmit_message;
can_receive_message_struct receive_message;


void CAN0_Init(void)
{
    can_parameter_struct can_parameter;
    can_filter_parameter_struct can_filter;

    u32 filter_list_id = 0x1f8040fe;//过滤器列表数字(用不到可以不用)
    u32 filter_mask_id = 0x1f000000;//过滤掩码数

    //打开时钟
    rcu_periph_clock_enable(CAN0_CLOCK);
    rcu_periph_clock_enable(RCU_CAN0);
    rcu_periph_clock_enable(RCU_AF);

    /* configure CAN0 GPIO */
    gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP,ENABLE);       //重映射配置
    gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,CAN0_RX_GPIO_PIN);
    gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,CAN0_TX_GPIO_PIN);


    /* initialize transmit message */
    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
    can_struct_para_init(CAN_INIT_STRUCT, &can_filter);

    /* initialize CAN register */
    can_deinit(CAN0);
    /* initialize CAN parameters */
    can_parameter.time_triggered = DISABLE;            //时间出发通信发送使能
    can_parameter.auto_bus_off_recovery =ENABLE;       //bus off自动恢复使能
    can_parameter.auto_wake_up = DISABLE;              //自动唤醒恢复使能
    can_parameter.no_auto_retrans = DISABLE;           //关闭自动重传模式
    can_parameter.rec_fifo_overwrite = DISABLE;        //接收FIFO覆盖模式使能
    can_parameter.trans_fifo_order = DISABLE;          //发送FIFO命令使能
    can_parameter.working_mode = CAN_NORMAL_MODE;      //正常工作模式
    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
    can_parameter.time_segment_1 = CAN_BT_BS1_5TQ;
    can_parameter.time_segment_2 = CAN_BT_BS2_4TQ;

    /* 1MBps */
#if CAN_BAUDRATE == 1000
    can_parameter.prescaler = 6;
    /* 500KBps */
#elif CAN_BAUDRATE == 500
    can_parameter.prescaler = 12;
    /* 250KBps */
#elif CAN_BAUDRATE == 250
    can_parameter.prescaler = 24;
    /* 125KBps */
#elif CAN_BAUDRATE == 125
    can_parameter.prescaler = 48;
    /* 100KBps */
#elif  CAN_BAUDRATE == 100
    can_parameter.prescaler = 60;
    /* 50KBps */
#elif  CAN_BAUDRATE == 50
    can_parameter.prescaler = 120;
    /* 20KBps */
#elif  CAN_BAUDRATE == 20
    can_parameter.prescaler = 300;
#endif

    can_init(CAN0, &can_parameter);

     /* initialize filter */
    can_filter.filter_number=0;     //
    can_filter.filter_mode = CAN_FILTERMODE_MASK;  //掩码过滤模式
    can_filter.filter_bits = CAN_FILTERBITS_32BIT; //过滤长度
    can_filter.filter_list_high = ((filter_list_id << 3) >> 16) & 0xffff; //过滤器列表数字高位
    can_filter.filter_list_low = (filter_list_id << 3) & 0xffff;  //过滤器列表数字低位
    can_filter.filter_mask_high = ((filter_mask_id << 3)>>16) & 0xffff; //过滤掩码数高位
    can_filter.filter_mask_low = ((filter_mask_id << 3)&0xffff);  //过滤掩码数低位
    can_filter.filter_fifo_number = CAN_FIFO0; //与过滤器关联的FIFO
    can_filter.filter_enable = ENABLE; //过滤使能

    can_filter_init(&can_filter);

    /* configure CAN0 NVIC */
    nvic_irq_enable(CAN0_RX0_IRQn,1,2);

    /* enable can receive FIFO0 not empty interrupt */
    can_interrupt_enable(CAN0, CAN_INT_RFNE0);

    //发送消息配置
    can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
    transmit_message.tx_sfid = 0x321;           //标准帧ID
    transmit_message.tx_efid = 0x13456734;      //扩展帧ID,29bits
    transmit_message.tx_ft = CAN_FT_DATA;
    transmit_message.tx_ff = CAN_FF_EXTENDED;

    //接收消息配置
    can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
}



/************************************************************************************************
**函数名:Can0_SendData(u8* pstr,u16 length)
**功能  :CAN0数据发送
**其他  :
************************************************************************************************/
void Can0_SendData(u8* pstr,u16 length)
{
    u32 i =0;
    if(length > 8) return;
    transmit_message.tx_dlen = length;
    for(i=0;i<length;i++)
    {
        transmit_message.tx_data = pstr;
    }
    can_message_transmit(CAN0, &transmit_message);  //CAN发送函数
}

/************************************************************************************************
**函数名:CAN0_RX0_IRQHandler(void)
**功能  :CAN0中断接收处理
**其他  :
************************************************************************************************/
void CAN0_RX0_IRQHandler(void)
{
    /* check the receive message */
    can_message_receive(CAN0, CAN_FIFO0, &receive_message);
    CAN0_Receice_Analysis(&receive_message);
}



二、CAN1

查看了一下芯片手册,IO初始化配置不需要重映射。




//GD32F305系列要使用CAN1必须打开这个宏
#define GD32F30X_CL 1

#define CAN1_BAUDRATE 250

//CAN1引脚定义
#define   CAN1_CLOCK                    RCU_GPIOB
#define   CAN1_GPIO                     GPIOB
#define   CAN1_TX_GPIO_PIN              GPIO_PIN_13
#define   CAN1_RX_GPIO_PIN              GPIO_PIN_12



can_trasnmit_message_struct Can1_transmit_message;
can_receive_message_struct Can1_receive_message;

void CAN1_Init(void)
{
    can_parameter_struct can_parameter1;
    can_filter_parameter_struct can_filter1;

    //打开时钟
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_CAN1);
    rcu_periph_clock_enable(RCU_AF);

    /* configure CAN0 GPIO */
    gpio_init(CAN1_GPIO,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,CAN1_RX_GPIO_PIN);   //CANRX
    gpio_init(CAN1_GPIO,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,CAN1_TX_GPIO_PIN); //CANTX

    /* initialize transmit message */
    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter1);
    can_struct_para_init(CAN_INIT_STRUCT, &can_filter1);

    /* initialize CAN register */
    can_deinit(CAN1);

    /* initialize CAN parameters */
    can_parameter1.time_triggered = DISABLE;            //时间出发通信发送失能
    can_parameter1.auto_bus_off_recovery =ENABLE;       //bus off自动恢复失能
    can_parameter1.auto_wake_up = DISABLE;              //自动唤醒恢复失能
    can_parameter1.no_auto_retrans = DISABLE;           //关闭自动重传模式
    can_parameter1.rec_fifo_overwrite = DISABLE;        //接收FIFO覆盖模式失能
    can_parameter1.trans_fifo_order = DISABLE;          //发送FIFO命令失能
    can_parameter1.working_mode = CAN_NORMAL_MODE;      //正常工作模式
    can_parameter1.resync_jump_width = CAN_BT_SJW_1TQ;
    can_parameter1.time_segment_1 = CAN_BT_BS1_5TQ;
    can_parameter1.time_segment_2 = CAN_BT_BS2_4TQ;

            /* 1MBps */
#if CAN1_BAUDRATE == 1000
    can_parameter1.prescaler = 6;
    /* 500KBps */
#elif CAN1_BAUDRATE == 500
    can_parameter1.prescaler = 12;
    /* 250KBps */
#elif CAN1_BAUDRATE == 250
    can_parameter1.prescaler = 24;
    /* 125KBps */
#elif CAN1_BAUDRATE == 125
    can_parameter1.prescaler = 48;
    /* 100KBps */
#elif  CAN1_BAUDRATE == 100
    can_parameter1.prescaler = 60;
    /* 50KBps */
#elif  CAN1_BAUDRATE == 50
    can_parameter1.prescaler = 120;
    /* 20KBps */
#elif  CAN1_BAUDRATE == 20
    can_parameter1.prescaler = 300;
#endif

    if(can_init(CAN1, &can_parameter1) != SUCCESS) {
        // 初始化失败处理
        printf("can1 init error!\r\n");
    }

    /* initialize filter */
    can_filter1.filter_number = 15;     //CAN1使用过滤器因该为14-27
    can_filter1.filter_mode = CAN_FILTERMODE_MASK;  //掩码过滤模式
    can_filter1.filter_bits = CAN_FILTERBITS_32BIT; //过滤长度
        can_filter1.filter_list_high = 0x0000; //过滤器列表数字高位
    can_filter1.filter_list_low = 0x0000;  //过滤器列表数字低位
    can_filter1.filter_mask_high = 0x0000; //过滤掩码数高位
    can_filter1.filter_mask_low = 0x0000;  //过滤掩码数低位
    can_filter1.filter_fifo_number = CAN_FIFO0; //与过滤器关联的FIFO
    can_filter1.filter_enable = ENABLE; //过滤使能

    can_filter_init(&can_filter1);

    /* configure CAN0 NVIC */
    nvic_irq_enable(CAN1_RX0_IRQn,1,2);

    /* enable can receive FIFO0 not empty interrupt */
    can_interrupt_enable(CAN1, CAN_INT_RFNE0);
    //发送消息配置
    can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &Can1_transmit_message);
    Can1_transmit_message.tx_sfid = 0x321;           //标准帧ID
    Can1_transmit_message.tx_efid = 0x13456734;      //扩展帧ID,29bits
    Can1_transmit_message.tx_ft = CAN_FT_DATA;
    Can1_transmit_message.tx_ff = CAN_FF_EXTENDED;
    //接收消息配置
    can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &Can1_receive_message);
}



/************************************************************************************************
**函数名:Can1_SendData(u8* pstr,u16 length)
**功能  :CAN1数据发送
**其他  :
************************************************************************************************/
void Can1_SendData(uint8_t* pstr,uint16_t length)
{
    u32 i =0;
    if(length > 8) return;
    transmit_message.tx_dlen = length;
    for(i=0;i<length;i++)
    {
        transmit_message.tx_data = pstr;
    }
    can_message_transmit(CAN1, &transmit_message);  //CAN发送函数
}


/************************************************************************************************
**函数名:CAN1_RX0_IRQHandler(void)
**功能  :CAN1中断接收处理
**其他  :
************************************************************************************************/
void CAN1_RX0_IRQHandler(void)
{
    /* check the receive message */
    can_message_receive(CAN1, CAN_FIFO0, &receive_message);
    CAN1_Receice_Analysis(&receive_message);
}



三、调试

配置完了,可以烧录代码试试看,能不能跑通。

如果不行。首先排除软件问题:

1、把正常工作模式换成回环模式




//can_parameter1.working_mode = CAN_NORMAL_MODE;      //正常工作模式

can_parameter1.working_mode = CAN_LOOPBACK_MODE;      //回环工作模式


2、换成后就能去调试了,按我这一套配置的话,应该是没有问题的。可以正常收发。在接收中断中打个断点看能不能接收到。

排除完软件问题还是不行。那么,有请硬件同事登场。哈哈哈哈~
————————————————
版权声明:本文为CSDN博主「一叶舞澎湃」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/p467616/article/details/148222890

l63t89 发表于 2025-8-31 23:47 | 显示全部楼层
你这套 CAN 配置思路很实用!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

131

主题

4396

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部