GD32/STM32 CAN通讯配置及应用

本文详细介绍了GD32F105处理器的CAN接口初始化配置,包括波特率设置、GPIO配置、参数调整,以及CAN滤波和接收、发送功能的实现。特别关注了掩码模式下的CANID过滤。
摘要由CSDN通过智能技术生成

GD32/STM32 CAN通讯配置及应用

由于CAN通讯具有速度快,距离远的优势,现在越来越多设备采用can通讯,尤其是车企。本文形容can通讯的初始化配置以及应用。

程序初始化配置(GD32)例程

采用GD32F105互联型产品。有两路CAN。APB1时钟为16M,CAN波特率为250K。

/***********************************************************************
*@brief	:CAN初始化
*@param	:None
*@return:None
***********************************************************************/
void CANLoad_Init(DataRate_t DataRate)
{
	uint8_t i;
//	uint32_t Clock;
	rcu_periph_clock_enable(RCU_CAN0);
	rcu_periph_clock_enable(RCU_CAN1);
	
	can_parameter_struct can_parameter;
	can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);

    /*GPIO Init*/
    gpio_init(CAN0_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN0_RX_PIN);
    gpio_init(CAN0_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN0_TX_PIN);
	
    gpio_init(CAN1_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN1_RX_PIN);
    gpio_init(CAN1_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN1_TX_PIN);
	
    /* initialize CAN register */
    can_deinit(CAN0);
    can_deinit(CAN1);

	//CAN由APB1时钟而来
//	Clock = rcu_clock_freq_get(CK_APB1);

    /* initialize CAN parameters */
    can_parameter.time_triggered = DISABLE;
    can_parameter.auto_bus_off_recovery = ENABLE;
    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_6TQ;
    can_parameter.time_segment_2 = CAN_BT_BS2_1TQ;
    
    can_parameter.prescaler = 8;
    /* initialize CAN */
    can_init(CAN0, &can_parameter);

    can_parameter.prescaler = 8;
	
    can_init(CAN1, &can_parameter);

	can_filter_parameter_struct can_filter;
	
    can_struct_para_init(CAN_INIT_STRUCT, &can_filter);
	
	can_filter.filter_number = 0;
	can_filter.filter_list_high = 0x3000;	//过滤器高字节
	can_filter.filter_list_low =  0x0000;	//过滤器低字节	
	can_filter.filter_mask_high = 0x3000//过滤器掩码数高位
	can_filter.filter_mask_low = 0x0000		//过滤器掩码数低位		
	
	can_filter.filter_fifo_number = CAN_FIFO0;	//滤过器关联FIFO0
	can_filter.filter_mode = CAN_FILTERMODE_MASK;	//掩码模式
	can_filter.filter_bits = CAN_FILTERBITS_32BIT;//32位
	can_filter.filter_enable = ENABLE;

	can_filter_init(&can_filter);
    /* CAN1 filter number */
    can_filter.filter_number = 15;
    can_filter_init(&can_filter);

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

CAN滤波

CAN滤波分为掩码模式和列表按模式,掩码模式是接收什么ID。这里我们只讨论掩码模式。
在掩码模式下,标识符寄存器与掩码寄存器相关联,掩码寄存器指定将标识符的哪些位处理为“必须匹配”或“不关心”。
例如
标识符:

ID二进制
0x18FFA1A11 1000 1111 1111 1010 0001 1010

掩码:

ID二进制
0x1FFFFFFE1 1111 1111 1111 1111 1111 1110

可以过滤的CAN ID为 0x18FFA1A1和0x18FFA1A0即最后一位不关心为什么。

CAN接收发送及应用

对CANID的长度、ID和扩展帧进行判断

/*-----------------------------------------------------------------------
@brief	:CAN1接收中断
-----------------------------------------------------------------------*/
void CAN1_RX0_IRQHandler(void)
{
	can_receive_message_struct RxMessage;
	can_message_receive(CAN1, CAN_FIFO0, &RxMessage);
	CAN1_RxMessage(&RxMessage);
}
/*-----------------------------------------------------------------------
@brief	:CAN1接收函数
-----------------------------------------------------------------------*/
void CAN1_RxMessage(can_receive_message_struct* RxMessage)
{
	if((0x18FFFFFF == RxMessage->rx_efid)&&(CAN_FF_EXTENDED == RxMessage->rx_ff)&&(8 == RxMessage->rx_dlen))
{
		Name = RxMessage->rx_data[0];
}
/*-----------------------------------------------------------------------
@brief	:CAN发送函数
-----------------------------------------------------------------------*/
void CAN1_HAILI_1(void)
{
	can_trasnmit_message_struct SendMessage;
	TxMessage_Init(&Tx1_Data);

	SendMessage.tx_data[0] = 0x11;
	SendMessage.tx_data[1] = 0x22;
	
	SendMessage.tx_dlen = 8;
	SendMessage.tx_ff = CAN_FF_EXTENDED;
	SendMessage.tx_ft = CAN_FT_DATA;
	SendMessage.tx_sfid = 0x18FF1234;
	can_message_transmit(CAN0, &SendMessage);
}

总结

实际还需要结合自己的逻辑进行改动。

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是基于GD32F3xx系列芯片的CAN功能配置及注释示例: ```c #include "gd32f3xx.h" void CAN_Configuration(void) { /* 使能CAN时钟 */ rcu_periph_clock_enable(RCU_CAN0); /* 配置CAN GPIO */ gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8 | GPIO_PIN_9); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8 | GPIO_PIN_9); gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_8 | GPIO_PIN_9); /* CAN 初始化 */ can_deinit(CAN0); can_struct_para_init(&can_init_struct); /* 定义CAN时钟分频 */ can_init_struct.can_frequency = 36000000U; /* 定义CAN位速率 */ can_init_struct.can_tx_sjw = CAN_SJW_1TQ; can_init_struct.can_rx_sjw = CAN_SJW_1TQ; can_init_struct.can_bs1 = CAN_BS1_13TQ; can_init_struct.can_bs2 = CAN_BS2_2TQ; /* 定义过滤器 */ can_filter_struct_para_init(&can_filter_init_struct); /* 过滤器模式 */ can_filter_init_struct.can_filter_bits = CAN_FILTERBITS_32BIT; /* 过滤器ID */ can_filter_init_struct.can_filter_id_high = 0x0000; can_filter_init_struct.can_filter_id_low = 0x0000; /* 过滤器掩码 */ can_filter_init_struct.can_filter_mask_id_high = 0x0000; can_filter_init_struct.can_filter_mask_id_low = 0x0000; /* 过滤器FIFO */ can_filter_init_struct.can_filter_fifo_number = CAN_FIFO0; /* 过滤器使能 */ can_filter_enable(CAN0, 0); /* CAN 初始化 */ can_init(CAN0, &can_init_struct); /* 配置CAN中断 */ nvic_irq_enable(CAN0_RX0_IRQn, 0, 0); can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0); /* 启动CAN */ can_enable(CAN0); } void CAN_Transmit(uint8_t* data, uint8_t len, uint32_t id) { can_trasnmit_message_struct transmit_message; /* 定义传输结构体 */ can_struct_para_init(&transmit_message); /* 定义传输格式 */ transmit_message.tx_sfid = id; transmit_message.tx_efid = 0x00; transmit_message.tx_ff = CAN_FF_STANDARD; transmit_message.tx_ft = CAN_FT_DATA; /* 定义传输数据 */ for (uint8_t i = 0; i < len; i++) { transmit_message.tx_data[i] = data[i]; } /* 定义传输数据长度 */ transmit_message.tx_dlen = len; /* 发送消息 */ can_message_transmit(CAN0, &transmit_message); } void CAN_Receive(uint8_t* data, uint8_t* len, uint32_t* id) { can_receive_message_struct receive_message; /* 定义接收结构体 */ can_struct_para_init(&receive_message); /* 接收消息 */ can_message_receive(CAN0, CAN_FIFO0, &receive_message); /* 获取接收数据 */ *id = receive_message.rx_sfid; *len = receive_message.rx_dlen; for (uint8_t i = 0; i < *len; i++) { data[i] = receive_message.rx_data[i]; } } ``` 注释: 1. `CAN_Transmit`函数:定义CAN发送函数 2. `can_trasnmit_message_struct`:CAN发送结构体,使用`can_struct_para_init`函数初始化为默认值 3. `transmit_message.tx_sfid = id`:定义CAN标准帧ID 4. `transmit_message.tx_ff = CAN_FF_STANDARD`:定义CAN标准帧格式 5. `transmit_message.tx_ft = CAN_FT_DATA`:定义CAN数据帧类型 6. `transmit_message.tx_data[i] = data[i]`:定义CAN数据 7. `transmit_message.tx_dlen = len`:定义CAN数据长度 8. `can_message_transmit(CAN0, &transmit_message)`:发送CAN消息 9. `CAN_Receive`函数:定义CAN接收函数 10. `can_receive_message_struct`:CAN接收结构体,使用`can_struct_para_init`函数初始化为默认值 11. `can_message_receive(CAN0, CAN_FIFO0, &receive_message)`:接收CAN消息 12. `*id = receive_message.rx_sfid`:获取CAN标准帧ID 13. `*len = receive_message.rx_dlen`:获取CAN数据长度 14. `data[i] = receive_message.rx_data[i]`:获取CAN数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

释博文

您的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值