GD32F4xx系列CAN通信收发基础配置:
主要注意2点:
1、波特率的配置:
查找GD32F4xx的用户手册找到CAN外设对应的时钟:
这里可以看到GD32F4xx的时钟在APB1总线上
在GD32F4xx的时钟树上找到APB1外设的时钟频率:
根据GD32F4xx用户手册提供的波特率计算公式来进行CAN的初始化:
注意:如果不会计算也没关系,看主页上传的资源中有一个CAN波特率计算工具软件,只需要输入频率和波特率就能计算出BS1、BS2和BPR,并且能够计算出出错率和采样的成功率,能够打打提搞开发效率。
2、CAN通信的出错率:
在通信状态不稳定或者干扰比较大的情况下,CAN通信发送和接收可能出错,此时GD32F4xx会进行出错统计,当统计达到一定数量的时候,CAN功能会进入休眠状态,需要重新唤醒。在手册中能够看到:
1、在工程中添加gd32f4xx_can.c 和gd32f4xx_dbg.c 两个源文件以及头文件到工程中,如下图所示:
为什么要添加gd32f4xx_dbg.c这个文件,原因是gd32f4xx_can.c文件中调用了调试需要两个函数,为了不修改gd官方提供的库函数我们就直接将两个文件一起添加到工程中。
2、新建一个can.c和can.h文件添加到工程中。并进行can相关开发;
//can.c文件
/*
can通信初始化
*/
int32_t can_opt_init(void)
{
can_trasnmit_message_struct can_frame;
can_parameter_struct can_parameter;
can_filter_parameter_struct can_filter;
can_receive_message_struct can_mes;
rcu_periph_clock_enable(RCU_CAN0);//使能can时钟
rcu_periph_clock_enable(RCU_GPIOA);//使能引脚时钟
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_11);
gpio_af_set(GPIOA,GPIO_AF_9,GPIO_PIN_11);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_12);
gpio_af_set(GPIOA,GPIO_AF_9,GPIO_PIN_12);//can通信引脚配置
nvic_irq_enable(CAN0_RX0_IRQn,1,0);//can中断配置
/*can通信参数配置*/
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &can_mes);
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &can_frame);
/* initialize CAN */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.no_auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_8TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_1TQ;
can_parameter.prescaler = 20;//配置波特率默认250K
if(SUCCESS !=can_init(CAN0,&can_parameter))//初始化can
{
return -1;
}
/* initialize filter */
can_filter.filter_mode = CAN_FILTERMODE_MASK;
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
can_filter.filter_list_high = 0x0000;
can_filter.filter_list_low = 0x0000;
can_filter.filter_mask_high = 0x0000;
can_filter.filter_mask_low = 0x0000;
can_filter.filter_fifo_number = CAN_FIFO0;
can_filter.filter_enable = ENABLE;
can_filter.filter_number = 0;
can_filter_init(&can_filter);
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
can_interrupt_enable(CAN0, CAN_INT_TME);//中断使能
return 0;
}
/*
can 数据发送函数
*/
void can_opt_send(can_trasnmit_message_struct can_frame)
{
can_message_transmit(CAN0,&can_frame);
}
/*
can 错误获取并进行错误清除
在CAN因出错次数过多导致进入休眠状态时可以进行CAN功能唤醒
*/
int32_t can_opt_error(void)
{
if( can_flag_get(CAN0, CAN_FLAG_MTE2) != RESET ||
can_flag_get(CAN0, CAN_FLAG_MTE0) != RESET ||
can_flag_get(CAN0, CAN_FLAG_MTE1) != RESET ||
can_flag_get(CAN0, CAN_FLAG_PERR) != RESET ||
can_flag_get(CAN0, CAN_FLAG_WERR) != RESET)
{
can_flag_clear(CAN0, CAN_FLAG_MTE0);
can_flag_clear(CAN0, CAN_FLAG_MTE1);
can_flag_clear(CAN0, CAN_FLAG_MTE2);
can_flag_clear(CAN0, CAN_FLAG_PERR);
can_flag_clear(CAN0, CAN_FLAG_WERR);
can_wakeup(CAN0);
can_opt_init();
return 1;
}
return 0;
}
/*
can 停止can功能
*/
void can_opt_stop(void)
{
can_working_mode_set(CAN0,CAN_MODE_SLEEP);
}
//can.h 文件
#ifndef _CAN_H_
#define _CAN_H_
#include "gd32f4xx.h"
#include "gd32f4xx_can.h"
int32_t can_opt_init(void);
void can_opt_send(can_trasnmit_message_struct can_frame);
int32_t can_opt_error(void);
void can_opt_stop(void);
#endif
/*gd32f4xx_it.c文件需要增加CAN接收中断函数,这里只是简单的做数据接收并没有进行数据相关处理,到时候可以设置断点查看接收到的数据即可。*/
can_receive_message_struct can_mes;
void CAN0_RX0_IRQHandler(void)
{
can_message_receive(CAN0, CAN_FIFO0, &can_mes);
if(can_mes.rx_efid == 0x18FFF605)
{
can_mes.rx_data[0] = 1;
}
}
3、在main.c文件main函数中调用初始化以及数据发送;
4、连接好CAN通信盒和MCU,打开CAN调试工具。将代码编译下载到MCU并运行程序。
5、设置CAN调试断点在can发送数据完成之后,并等待程序运行到断点处
6.查看CAN调试工具,接收到MCU发送过来的CAN数据,并对比MCU发送过来的数据与接收数据是否一致
通过对比可以发现数据发送基本无误。
7、使用CAN调试工具给MCU发送数据,并在CAN接收中断中设置断点查看接收数据是否正确。
通过对比可以发现CAN调试工具给MCU发送的数据与MCU接收到的数据一致,因此MCU的CAN接收与发送功能正常,代码可以使用。