打印
[STM32G4]

STM32G431单片机CAN通信实战指南

[复制链接]
53|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
帛灿灿|  楼主 | 2024-12-12 10:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在嵌入式开发中,CAN(Controller Area Network)是一种高效、可靠的通信协议,广泛应用于汽车电子、工业自动化等领域。本文将以STM32G431为例,详细讲解如何配置和使用CAN接口实现主从通信。STM32G431是一款基于Cortex-M4内核的高性能单片机,支持多种通信接口,是开发者的理想选择。
项目概述我们将实现以下功能:
  • STM32G431作为主控,通过CAN总线发送命令至从设备。
  • 从设备接收到命令后进行反馈。
  • 数据格式包括命令ID和数据载荷。
硬件连接
  • STM32G431开发板
  • MCP2551 CAN收发器
  • 终端电阻(120Ω)
  • 电源与接地
硬件连接如下:
  • STM32G431 的 CAN_TX 连接至 MCP2551 的 TXD。
  • STM32G431 的 CAN_RX 连接至 MCP2551 的 RXD。
  • MCP2551 的 CANH 和 CANL 接至总线。
  • 总线两端分别连接120Ω终端电阻。
软件配置与代码实现软件采用STM32CubeMX生成初始化代码,使用HAL库实现CAN通信。
配置步骤
  • 在STM32CubeMX中启用FDCAN外设。
  • 设置波特率为500kbps(可根据需求调整)。
  • 生成初始化代码并导入至Keil或CubeIDE中。
示例代码以下为实现主机发送和从机接收的完整代码:
#include "main.h"

// 定义CAN句柄
FDCAN_HandleTypeDef hfdcan1;

// 初始化FDCAN
void MX_FDCAN1_Init(void) {
    hfdcan1.Instance = FDCAN1;
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
    hfdcan1.Init.AutoRetransmission = ENABLE;
    hfdcan1.Init.TransmitPause = DISABLE;
    hfdcan1.Init.ProtocolException = DISABLE;
    hfdcan1.Init.NominalPrescaler = 1;
    hfdcan1.Init.NominalSyncJumpWidth = 1;
    hfdcan1.Init.NominalTimeSeg1 = 13;
    hfdcan1.Init.NominalTimeSeg2 = 2;
    if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) {
        Error_Handler();
    }

    // 配置过滤器
    FDCAN_FilterTypeDef filterConfig;
    filterConfig.IdType = FDCAN_STANDARD_ID;
    filterConfig.FilterIndex = 0;
    filterConfig.FilterType = FDCAN_FILTER_MASK;
    filterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    filterConfig.FilterID1 = 0x100;
    filterConfig.FilterID2 = 0x7FF;
    HAL_FDCAN_ConfigFilter(&hfdcan1, &filterConfig);

    // 启动FDCAN
    HAL_FDCAN_Start(&hfdcan1);
    HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
}

// CAN发送数据
void CAN_SendData(uint32_t id, uint8_t* data, uint8_t length) {
    FDCAN_TxHeaderTypeDef txHeader;
    txHeader.Identifier = id;
    txHeader.IdType = FDCAN_STANDARD_ID;
    txHeader.TxFrameType = FDCAN_DATA_FRAME;
    txHeader.DataLength = FDCAN_DLC_BYTES_8;
    txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    txHeader.BitRateSwitch = FDCAN_BRS_OFF;
    txHeader.FDFormat = FDCAN_CLASSIC_CAN;
    txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;

    if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, data) != HAL_OK) {
        Error_Handler();
    }
}

// CAN接收回调
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) {
    if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {
        FDCAN_RxHeaderTypeDef rxHeader;
        uint8_t rxData[8];
        HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rxHeader, rxData);

        // 处理接收到的数据
        if (rxHeader.Identifier == 0x200) {
            // 具体逻辑处理
        }
    }
}

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_FDCAN1_Init();

    uint8_t txData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    while (1) {
        CAN_SendData(0x100, txData, 8);
        HAL_Delay(1000);
    }
}
注意事项
  • 波特率匹配:主机与从机的波特率必须一致。
  • 总线终端电阻:无论调试还是应用环境中,总线两端必须有终端电阻。
  • 数据接收处理:要确保接收逻辑与实际需求匹配,避免因数据丢失或格式不符导致的异常。
总结本文详细介绍了如何使用STM32G431的CAN接口实现主从通信,并通过实际代码演示了发送和接收的完整流程。在实际开发中,可以根据项目需求对数据格式和逻辑处理进行扩展。

使用特权

评论回复
沙发
公羊子丹| | 2024-12-12 10:45 | 只看该作者
这个代码看起来很实用,我正好有个项目可以用上!

使用特权

评论回复
板凳
周半梅| | 2024-12-12 10:45 | 只看该作者
STM32G431 的 CAN 功能确实强大,得试试这个配置。

使用特权

评论回复
地板
童雨竹| | 2024-12-12 10:45 | 只看该作者
请问用其他型号的 STM32 单片机能兼容这个代码吗?

使用特权

评论回复
5
万图| | 2024-12-12 10:46 | 只看该作者
发现在调试 CAN 的时候,终端电阻真的很重要!

使用特权

评论回复
6
Wordsworth| | 2024-12-12 10:46 | 只看该作者
想问问用 CubeMX 配置时,有没有遇到过滤波器问题?

使用特权

评论回复
7
Bblythe| | 2024-12-12 10:46 | 只看该作者
代码部分写得挺清楚,学习了 HAL 的新用法!

使用特权

评论回复
8
Pulitzer| | 2024-12-12 10:46 | 只看该作者
500kbps 的波特率挺常见的,你有没有尝试更高的?

使用特权

评论回复
9
Uriah| | 2024-12-12 10:47 | 只看该作者
从机的代码部分可以再详细点,期待补充!

使用特权

评论回复
10
Clyde011| | 2024-12-12 10:47 | 只看该作者
最近项目也用 STM32G431,不知道能不能分享点调试技巧?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

3770

帖子

0

粉丝