GD32F303RET6之CAN通信

一、GD32F303RET6 CAN通信简介

GD32F303RET6是一款高性能的微控制器,它集成了CAN(Controller Area Network)控制器,CAN是一种广泛应用于汽车、工业控制等领域的串行通信协议,具有高可靠性、高实时性和良好的错误检测能力等优点。CAN协议支持多主通信,允许网络中的多个节点同时发送和接收消息,并且可以通过标识符来区分不同的消息,实现数据的优先级控制。

二、CAN通信的基本原理

  1. CAN帧结构
    CAN协议定义了几种不同类型的帧,包括数据帧、远程帧、错误帧和过载帧。其中,数据帧是最常用的,它包含了标识符(ID)、数据长度码(DLC)和数据域等。标识符用于区分不同的消息,数据长度码表示数据的长度,数据域存储实际要传输的数据。CAN帧可以分为标准帧(11位标识符)和扩展帧(29位标识符)。

  2. 位定时
    CAN通信的位定时非常重要,它决定了通信的波特率。位定时参数包括波特率预分频器(BRP)、同步段(Sync_Seg)、时间段1(Time_Seg1)和时间段2(Time_Seg2)。这些参数的正确设置可以确保通信的稳定性和可靠性。

  3. 仲裁机制
    当多个节点同时发送消息时,CAN的仲裁机制会根据标识符的大小来决定哪个消息优先发送。标识符值越小,优先级越高,这样可以保证高优先级的消息优先传输,避免数据冲突。

三、GD32F303RET6 CAN通信的代码实现

以下是一个使用GD32F303RET6标准库实现CAN通信的示例代码:

#include "gd32f30x.h"
#include <stdio.h>

// 初始化CAN
void CAN_Init(void)
{
    // 使能CAN和GPIO的时钟
    rcc_periph_clock_enable(RCC_APB1Periph_CAN0);
    rcc_periph_clock_enable(RCC_AHBPeriph_GPIOA);

    // 配置GPIO为CAN功能
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11 | GPIO_PIN_12);
    gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP1, ENABLE);

    // CAN初始化
    can_parameter_struct can_parameter;
    can_struct_para_init(&can_parameter);
    can_parameter.time_triggered = DISABLE;
    can_parameter.auto_bus_off_recovery = ENABLE;
    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_MODE_NORMAL;
    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_3TQ;
    can_parameter.prescaler = 4; // 假设波特率为500KHz,APB1时钟为48MHz
    can_init(CAN0, &can_parameter);

    // 配置CAN过滤器
    can_filter_parameter_struct can_filter_parameter;
    can_filter_parameter.filter_number = 0;
    can_filter_parameter.filter_mode = CAN_FILTERMODE_MASK;
    can_filter_parameter.filter_bits = CAN_FILTERBITS_32BIT;
    can_filter_parameter.filter_list_high = 0x0000;
    can_filter_parameter.filter_list_low = 0x0000;
    can_filter_parameter.filter_mask_high = 0x0000;
    can_filter_parameter.filter_mask_low = 0x0000;
    can_filter_parameter.filter_fifo_number = CAN_FIFO0;
    can_filter_parameter.filter_enable = ENABLE;
    can_filter_init(&can_filter_parameter);

    // 使能CAN接收中断
    can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
    nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
}

// CAN接收中断服务函数
void CAN0_RX0_IRQHandler(void)
{
    if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFNE0))
    {
        can_receive_message_struct can_rx_message;
        can_struct_para_init(&can_rx_message);
        can_message_receive(CAN0, CAN_FIFO0, &can_rx_message);
        // 处理接收到的消息
        printf("Received: ID = 0x%x, DLC = %d\n", can_rx_message.rx_sfid, can_rx_message.rx_dlc);
        for (int i = 0; i < can_rx_message.rx_dlc; i++)
        {
            printf("Data[%d] = 0x%x ", i, can_rx_message.rx_data[i]);
        }
        printf("\n");
    }
}

// 发送CAN消息
void CAN_SendMessage(uint32_t id, uint8_t dlc, uint8_t *data)
{
    can_trasnmit_message_struct can_tx_message;
    can_struct_para_init(&can_tx_message);
    can_tx_message.tx_sfid = id;
    can_tx_message.tx_efid = 0;
    can_tx_message.tx_ff = CAN_FF_STANDARD;
    can_tx_message.tx_ft = CAN_FT_DATA;
    can_tx_message.tx_dlc = dlc;
    for (int i = 0; i < dlc; i++)
    {
        can_tx_message.tx_data[i] = data[i];
    }
    can_transmit(CAN0, &can_tx_message);
}

int main(void)
{
    CAN_Init();
    uint8_t send_data[] = {0x12, 0x34, 0x56, 0x78};
    while (1)
    {
        // 发送消息
        CAN_SendMessage(0x123, 4, send_data);
        for (int i = 0; i < 1000000; i++); // 简单延时
    }
}

代码解释

  • CAN_Init()函数:
    • 首先,使用rcc_periph_clock_enable()使能CAN和相应GPIO的时钟。
    • 配置GPIO为复用功能(使用PA11和PA12作为CAN的收发引脚),并设置引脚的复用功能和速度。
    • 对CAN进行参数初始化,设置工作模式、自动重传、重同步跳跃宽度、时间段等参数,通过调整prescaler等参数可以设置波特率。
    • 配置CAN过滤器,这里使用了一个简单的过滤器,允许接收所有消息。
    • 使能CAN接收中断,并配置中断服务函数。
  • CAN0_RX0_IRQHandler()函数:
    • 当接收到消息时,通过can_interrupt_flag_get()检查接收中断标志,然后使用can_message_receive()接收消息并存储在can_rx_message结构体中,最后打印出接收到的消息信息。
  • CAN_SendMessage()函数:
    • 用于发送CAN消息,将传入的标识符、数据长度和数据存储在can_tx_message结构体中,并使用can_transmit()函数发送消息。

四、配置细节和注意事项

  1. 波特率设置
    在设置CAN的波特率时,需要根据APB1时钟频率和所需的波特率计算出合适的波特率预分频器(BRP)、时间段1(Time_Seg1)和时间段2(Time_Seg2)。例如,在上述代码中,APB1时钟为48MHz,通过设置prescaler = 4time_segment_1 = CAN_BT_BS1_6TQtime_segment_2 = CAN_BT_BS2_3TQ,可以计算出波特率为500KHz。

  2. 过滤器配置
    CAN过滤器可以用来过滤接收到的消息,只接收符合特定标识符或标识符范围的消息。在实际应用中,可以根据需要配置不同的过滤器模式和参数,以实现灵活的消息过滤功能。

  3. 中断处理
    在上述代码中,使用了接收中断来处理接收到的消息。在中断服务函数中,需要尽快处理消息,避免占用过多的时间,影响系统的实时性。

  4. 发送消息的可靠性
    发送消息时,要确保发送缓冲区未满,并且在发送完成后,可以通过检查发送状态标志来确认消息是否发送成功。

  5. 错误处理
    CAN控制器具有多种错误检测机制,如错误帧、错误计数器等。在实际应用中,可以通过检查这些错误标志和计数器,及时发现和处理通信错误,确保通信的可靠性。

五、应用场景和扩展

  1. 汽车电子
    在汽车电子领域,CAN可以用于发动机控制、仪表盘显示、制动系统等多个子系统之间的通信,实现车辆状态的监测和控制。

  2. 工业控制
    在工业自动化中,CAN可以用于PLC、传感器、执行器等设备之间的通信,实现分布式控制和数据采集。

  3. 扩展功能
    可以添加更多的节点,实现多节点之间的通信;或者使用CAN的远程帧功能,实现对远程设备的请求和响应操作;还可以使用扩展帧来增加标识符的范围,以满足更复杂的应用需求。

六、总结

GD32F303RET6的CAN通信功能为开发各种需要高可靠性和实时性的应用提供了强大的支持。通过正确的配置和代码实现,可以实现数据的可靠传输和接收。在实际开发中,需要根据具体的应用需求,仔细调整CAN的参数,包括波特率、过滤器和中断处理等,以实现高效、稳定的通信。同时,注意处理可能出现的错误和异常情况,保证系统的可靠性和稳定性。

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

❤欢迎关注我的知乎:对error视而不见

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值