YTM32B1M SDK解析05 - FlexCAN总线通信接口

1. 概述

FlexCAN(Flexible Controller Area Network)是YTM32B1M微控制器中的高性能CAN总线控制器,支持CAN 2.0A/B协议和CAN FD(Flexible Data-rate)扩展协议。本文档详细解析YTM32B1M SDK中FlexCAN驱动的实现,包括消息缓冲区管理、FIFO操作、位时序配置和错误处理等功能。

2. 文件组织结构

2.1 头文件

  • flexcan_driver.h: FlexCAN驱动的主要头文件,定义了所有公共接口和数据结构

  • flexcan_hw_access.h: FlexCAN硬件访问层头文件

  • flexcan_irq.h: FlexCAN中断处理相关头文件

2.2 源文件

  • flexcan_driver.c: FlexCAN驱动的主要实现文件

  • flexcan_irq.c: FlexCAN中断服务程序实现

  • flexcan_hw_access.c: FlexCAN硬件抽象层实现

2.3 架构层次

应用层
    ↓
flexcan_driver.h/c (高层API)
    ↓
flexcan_hw_access.h/c (硬件抽象层)
    ↓
FlexCAN寄存器定义
    ↓
FlexCAN硬件控制器

3. 核心数据结构解析

3.1 消息ID类型枚举

typedef enum {
    FLEXCAN_MSG_ID_STD,         // 标准ID (11位)
    FLEXCAN_MSG_ID_EXT          // 扩展ID (29位)
} flexcan_msgbuff_id_type_t;

3.2 事件类型枚举

typedef enum {
    FLEXCAN_EVENT_RX_COMPLETE,     // 接收完成
    FLEXCAN_EVENT_RXFIFO_COMPLETE, // RxFIFO接收完成
    FLEXCAN_EVENT_RXFIFO_WARNING,  // RxFIFO警告(接近满)
    FLEXCAN_EVENT_RXFIFO_OVERFLOW, // RxFIFO溢出
    FLEXCAN_EVENT_TX_COMPLETE,     // 发送完成
    FLEXCAN_EVENT_ENHANCE_RXFIFO_AVAILABLEDATA, // 增强RxFIFO数据可用
    FLEXCAN_EVENT_ENHANCE_RXFIFO_WATERMARK,     // 增强RxFIFO水位
    FLEXCAN_EVENT_ENHANCE_RXFIFO_OVERFLOW,      // 增强RxFIFO溢出
    FLEXCAN_EVENT_WAKEUP_TIMEOUT,  // 唤醒超时
    FLEXCAN_EVENT_WAKEUP_MATCH,    // 唤醒匹配
    FLEXCAN_EVENT_SELF_WAKEUP,     // 自唤醒
    FLEXCAN_EVENT_DMA_COMPLETE,    // DMA传输完成
    FLEXCAN_EVENT_DMA_ERROR,       // DMA传输错误
    FLEXCAN_EVENT_ERROR            // 一般错误
} flexcan_event_type_t;

3.3 错误事件类型枚举

typedef enum {
    FLEXCAN_ERROR_OVERRUN_EVENT = CAN_ESR1_ERROVR_MASK,    // 过载错误
    FLEXCAN_FD_DATA_BIT_ERROR_EVENT = CAN_ESR1_ERRINT_FAST_MASK, // FD数据位错误
    FLEXCAN_BUS_OFF_DONE_EVENT = CAN_ESR1_BOFFDONEINT_MASK,     // 总线关闭完成
    FLEXCAN_TX_WARNING_EVENT = CAN_ESR1_TXWRN_MASK,            // 发送警告
    FLEXCAN_RX_WARNING_EVENT = CAN_ESR1_RXWRN_MASK,            // 接收警告
    FLEXCAN_BUS_OFF_ENTER_EVENT = CAN_ESR1_BOFFINT_MASK,       // 进入总线关闭
    FLEXCAN_BIT_ERROR_EVENT = CAN_ESR1_ERRINT_MASK,            // 位错误
    FLEXCAN_WAKEUP_EVENT = CAN_ESR1_WAKINT_MASK,               // 唤醒事件
    FLEXCAN_RAM_ECC_ERROR_EVENT = CAN_ERRSR_FANCEIF_MASK | CAN_ERRSR_HANCEIF_MASK // RAM ECC错误
} flexcan_error_event_type_t;

3.4 消息缓冲区状态枚举

typedef enum {
    FLEXCAN_MB_IDLE,      // 消息缓冲区空闲
    FLEXCAN_MB_RX_BUSY,   // 消息缓冲区接收忙
    FLEXCAN_MB_TX_BUSY,   // 消息缓冲区发送忙
    FLEXCAN_MB_DMA_ERROR  // DMA传输错误
} flexcan_mb_state_t;

3.5 操作模式枚举

typedef enum {
    FLEXCAN_NORMAL_MODE,        // 正常模式
    FLEXCAN_LISTEN_ONLY_MODE,   // 只听模式
    FLEXCAN_LOOPBACK_MODE,      // 回环模式
    FLEXCAN_FREEZE_MODE,        // 冻结模式
    FLEXCAN_DISABLE_MODE        // 禁用模式
} flexcan_operation_modes_t;

3.6 RxFIFO传输类型枚举

typedef enum {
    FLEXCAN_RXFIFO_USING_INTERRUPTS,    // 使用中断
    FLEXCAN_RXFIFO_USING_DMA            // 使用DMA
} flexcan_rxfifo_transfer_type_t;

3.7 消息缓冲区结构

typedef struct {
    uint32_t cs;                        // 控制和状态字段
    uint32_t msgId;                     // 消息ID
    uint8_t data[64];                   // 数据字节(最大64字节)
    uint8_t dataLen;                    // 数据长度
} flexcan_msgbuff_t;

3.8 数据信息结构

typedef struct {
    flexcan_msgbuff_id_type_t msg_id_type;  // 消息ID类型
    uint32_t data_length;                   // 数据长度
    bool fd_enable;                         // FD使能
    uint8_t fd_padding;                     // FD填充值
    bool enable_brs;                        // 位速率切换使能
    bool is_remote;                         // 远程帧标志
} flexcan_data_info_t;

3.9 位时序配置结构

typedef struct {
    uint32_t propSeg;         // 传播段
    uint32_t phaseSeg1;       // 相位段1
    uint32_t phaseSeg2;       // 相位段2
    uint32_t preDivider;      // 时钟预分频器
    uint32_t rJumpwidth;      // 重同步跳跃宽度
} flexcan_time_segment_t;

3.10 消息缓冲区句柄结构

typedef struct {
    flexcan_msgbuff_t *mb_message;       // 消息缓冲区指针
    semaphore_t mbSema;                  // 信号量
    volatile flexcan_mb_state_t state;   // 缓冲区状态
    bool isBlocking;                     // 阻塞标志
    bool isRemote;                       // 远程帧标志
} flexcan_mb_handle_t;

3.11 FlexCAN状态结构

typedef struct FlexCANState {
    flexcan_mb_handle_t mbs[FEATURE_CAN_MAX_MB_NUM];  // 消息缓冲区数组
    void (*callback)(uint8_t instance,                // 回调函数指针
                     flexcan_event_type_t eventType,
                     uint32_t buffIdx,
                     struct FlexCANState *driverState);
    void *callbackParam;                              // 回调参数
    void (*error_callback)(uint8_t instance,          // 错误回调函数
                           flexcan_error_event_type_t eventType,
                           struct FlexCANState *driverState);
    void *errorCallbackParam;                         // 错误回调参数
    uint8_t rxFifoDMAChannel;                        // RxFIFO DMA通道
    flexcan_mb_handle_t enhanceRxFifoState;          // 增强RxFIFO状态
    flexcan_rxfifo_transfer_type_t transferType;     // 传输类型
} flexcan_state_t;

3.12 用户配置结构

typedef struct {
    uint32_t max_num_mb;                            // 最大消息缓冲区数量
    flexcan_rx_fifo_id_filter_num_t num_id_filters; // ID过滤器数量
    bool is_rx_fifo_needed;                         // 是否需要RxFIFO
    flexcan_operation_modes_t flexcanMode;          // 操作模式
    flexcan_fd_payload_size_t payload;              // 载荷大小
    bool fd_enable;                                 // FD使能
    flexcan_clk_source_t pe_clock;                  // 协议引擎时钟源
    flexcan_time_segment_t bitrate;                 // 标准帧位速率
    flexcan_time_segment_t bitrate_cbt;             // FD数据相位位速率
    flexcan_rxfifo_transfer_type_t transfer_type;   // 传输类型
    uint8_t rxFifoDMAChannel;                       // RxFIFO DMA通道
    bool is_enhance_rx_fifo_needed;                 // 是否需要增强RxFIFO
    uint32_t num_enhance_rx_fifo_filters;           // 增强RxFIFO过滤器数量
    uint32_t num_enhance_rx_fifo_extid_filters;     // 扩展ID过滤器数量
    uint32_t num_enhance_rx_fifo_min_messages;      // 最小消息数量
} flexcan_user_config_t;

4. FlexCAN系统架构图

CAN总线                    FlexCAN控制器                应用层
┌─────────────┐           ┌─────────────────────────┐    ┌─────────────┐
│             │           │      消息缓冲区         │    │             │
│   CAN_H     │◄─────────►│  ┌─────┬─────┬─────┐   │◄──►│   应用程序   │
│             │           │  │ MB0 │ MB1 │ ... │   │    │             │
│   CAN_L     │           │  └─────┴─────┴─────┘   │    └─────────────┘
│             │           │                         │           │
└─────────────┘           │      RxFIFO            │    ┌─────────────┐
                          │  ┌─────────────────┐   │    │             │
                          │  │   过滤器表      │   │◄──►│  中断处理   │
                          │  └─────────────────┘   │    │             │
                          │                         │    └─────────────┘
                          │    位时序控制器         │           │
                          │  ┌─────────────────┐   │    ┌─────────────┐
                          │  │  时钟分频器     │   │    │             │
                          │  └─────────────────┘   │◄──►│  DMA控制    │
                          │                         │    │             │
                          │    错误管理单元         │    └─────────────┘
                          │  ┌─────────────────┐   │
                          │  │  错误计数器     │   │
                          │  └─────────────────┘   │
                          └─────────────────────────┘

5. 核心API接口详解

5.1 初始化和配置接口

// 获取默认配置
void FLEXCAN_DRV_GetDefaultConfig(flexcan_user_config_t *config);

// 初始化FlexCAN
status_t FLEXCAN_DRV_Init(uint8_t instance, 
                          flexcan_state_t *state,
                          const flexcan_user_config_t *config);

// 去初始化FlexCAN
status_t FLEXCAN_DRV_Deinit(uint8_t instance);

5.2 位速率配置接口

// 设置标准帧位速率
void FLEXCAN_DRV_SetBitrate(uint8_t instance, 
                            const flexcan_time_segment_t *bitrate);

// 设置FD数据相位位速率
void FLEXCAN_DRV_SetBitrateCbt(uint8_t instance, 
                               const flexcan_time_segment_t *bitrate);

// 获取位速率配置
void FLEXCAN_DRV_GetBitrate(uint8_t instance, 
                            flexcan_time_segment_t *bitrate);

5.3 消息发送接口

// 配置发送消息缓冲区
status_t FLEXCAN_DRV_ConfigTxMb(uint8_t instance,
                                uint8_t mb_idx,
                                const flexcan_data_info_t *tx_info,
                                uint32_t msg_id);

// 发送数据(阻塞)
status_t FLEXCAN_DRV_SendBlocking(uint8_t instance,
                                  uint8_t mb_idx,
                                  const flexcan_data_info_t *tx_info,
                                  uint32_t msg_id,
                                  const uint8_t *mb_data,
                                  uint32_t timeout_ms);

// 发送数据(非阻塞)
status_t FLEXCAN_DRV_Send(uint8_t instance,
                          uint8_t mb_idx,
                          const flexcan_data_info_t *tx_info,
                          uint32_t msg_id,
                          const uint8_t *mb_data);

// 获取发送状态
status_t FLEXCAN_DRV_GetTransferStatus(uint8_t instance, uint8_t mb_idx);

// 中止发送
status_t FLEXCAN_DRV_AbortTransfer(uint8_t instance, uint8_t mb_idx);

5.4 消息接收接口

// 配置接收消息缓冲区
status_t FLEXCAN_DRV_ConfigRxMb(uint8_t instance,
                                uint8_t mb_idx,
                                const flexcan_data_info_t *rx_info,
                                uint32_t msg_id);

// 接收数据(阻塞)
status_t FLEXCAN_DRV_ReceiveBlocking(uint8_t instance,
                                     uint8_t mb_idx,
                                     flexcan_msgbuff_t *data,
                                     uint32_t timeout_ms);

// 接收数据(非阻塞)
status_t FLEXCAN_DRV_Receive(uint8_t instance,
                             uint8_t mb_idx,
                             flexcan_msgbuff_t *data);

5.5 RxFIFO接口

// 配置RxFIFO
status_t FLEXCAN_DRV_ConfigRxFifo(uint8_t instance,
                                  flexcan_rx_fifo_id_element_format_t id_format,
                                  const flexcan_id_table_t *id_filter_table);

// 从RxFIFO接收(阻塞)
status_t FLEXCAN_DRV_RxFifoBlocking(uint8_t instance,
                                    flexcan_msgbuff_t *data,
                                    uint32_t timeout_ms);

// 从RxFIFO接收(非阻塞)
status_t FLEXCAN_DRV_RxFifo(uint8_t instance, flexcan_msgbuff_t *data);

5.6 掩码配置接口

// 设置掩码类型
void FLEXCAN_DRV_SetRxMaskType(uint8_t instance, flexcan_rx_mask_type_t type);

// 设置RxFIFO全局掩码
void FLEXCAN_DRV_SetRxFifoGlobalMask(uint8_t instance,
                                     flexcan_msgbuff_id_type_t id_type,
                                     uint32_t mask);

// 设置消息缓冲区全局掩码
void FLEXCAN_DRV_SetRxMbGlobalMask(uint8_t instance,
                                   flexcan_msgbuff_id_type_t id_type,
                                   uint32_t mask);

// 设置个别掩码
status_t FLEXCAN_DRV_SetRxIndividualMask(uint8_t instance,
                                         flexcan_msgbuff_id_type_t id_type,
                                         uint8_t mb_idx,
                                         uint32_t mask);

6. 外设应用描述

6.1 FlexCAN的主要应用场景

  1. 汽车电子: 车身控制、发动机管理、仪表通信

  2. 工业自动化: 现场总线通信、设备控制

  3. 医疗设备: 设备间通信、数据采集

  4. 航空航天: 飞行控制系统、数据总线

  5. 能源管理: 电池管理系统、充电桩通信

6.2 典型应用示例

6.2.1 基本FlexCAN初始化
#include "flexcan_driver.h"

// FlexCAN状态结构
flexcan_state_t canState;

// 回调函数
void canCallback(uint8_t instance, flexcan_event_type_t eventType,
                 uint32_t buffIdx, flexcan_state_t *flexcanState)
{
    switch (eventType) {
        case FLEXCAN_EVENT_TX_COMPLETE:
            // 发送完成处理
            break;
        case FLEXCAN_EVENT_RX_COMPLETE:
            // 接收完成处理
            break;
        case FLEXCAN_EVENT_RXFIFO_COMPLETE:
            // RxFIFO接收完成处理
            break;
        default:
            break;
    }
}

void flexcan_init_example(void)
{
    flexcan_user_config_t canConfig;
    
    // 获取默认配置
    FLEXCAN_DRV_GetDefaultConfig(&canConfig);
    
    // 修改配置参数
    canConfig.max_num_mb = 16;                      // 16个消息缓冲区
    canConfig.is_rx_fifo_needed = true;            // 启用RxFIFO
    canConfig.num_id_filters = FLEXCAN_RX_FIFO_ID_FILTERS_8; // 8个过滤器
    canConfig.flexcanMode = FLEXCAN_NORMAL_MODE;    // 正常模式
    canConfig.fd_enable = false;                    // 禁用FD
    
    // 配置位时序(500kbps)
    canConfig.bitrate.propSeg = 7;
    canConfig.bitrate.phaseSeg1 = 4;
    canConfig.bitrate.phaseSeg2 = 1;
    canConfig.bitrate.preDivider = 9;
    canConfig.bitrate.rJumpwidth = 1;
    
    // 初始化FlexCAN
    status_t status = FLEXCAN_DRV_Init(0, &canState, &canConfig);
    if (status != STATUS_SUCCESS) {
        // 初始化失败处理
    }
    
    // 安装回调函数
    FLEXCAN_DRV_InstallEventCallback(0, canCallback, NULL);
}
6.2.2 发送CAN消息示例
void can_send_example(void)
{
    // 配置发送消息缓冲区
    flexcan_data_info_t dataInfo = {
        .msg_id_type = FLEXCAN_MSG_ID_STD,  // 标准ID
        .data_length = 8,                   // 8字节数据
        .fd_enable = false,                 // 非FD帧
        .is_remote = false                  // 数据帧
    };
    
    uint32_t msgId = 0x123;  // 消息ID
    uint8_t txData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    
    // 配置发送消息缓冲区0
    status_t status = FLEXCAN_DRV_ConfigTxMb(0, 0, &dataInfo, msgId);
    if (status != STATUS_SUCCESS) {
        return;
    }
    
    // 发送数据(阻塞方式)
    status = FLEXCAN_DRV_SendBlocking(0, 0, &dataInfo, msgId, txData, 1000);
    if (status == STATUS_SUCCESS) {
        // 发送成功
    } else if (status == STATUS_TIMEOUT) {
        // 发送超时
    }
}
6.2.3 接收CAN消息示例
void can_receive_example(void)
{
    // 配置接收消息缓冲区
    flexcan_data_info_t dataInfo = {
        .msg_id_type = FLEXCAN_MSG_ID_STD,  // 标准ID
        .data_length = 8,                   // 8字节数据
        .fd_enable = false,                 // 非FD帧
        .is_remote = false                  // 数据帧
    };
    
    uint32_t msgId = 0x456;  // 期望接收的消息ID
    flexcan_msgbuff_t rxMsg;
    
    // 配置接收消息缓冲区1
    status_t status = FLEXCAN_DRV_ConfigRxMb(0, 1, &dataInfo, msgId);
    if (status != STATUS_SUCCESS) {
        return;
    }
    
    // 接收数据(阻塞方式)
    status = FLEXCAN_DRV_ReceiveBlocking(0, 1, &rxMsg, 5000);
    if (status == STATUS_SUCCESS) {
        // 处理接收到的数据
        processReceivedMessage(&rxMsg);
    } else if (status == STATUS_TIMEOUT) {
        // 接收超时
    }
}
6.2.4 RxFIFO配置和使用示例
void can_rxfifo_example(void)
{
    // 配置ID过滤器表
    flexcan_id_table_t idFilterTable[8] = {
        {false, false, 0x100},  // 接受ID 0x100
        {false, false, 0x200},  // 接受ID 0x200
        {false, false, 0x300},  // 接受ID 0x300
        // ... 更多过滤器
    };
    
    // 配置RxFIFO
    status_t status = FLEXCAN_DRV_ConfigRxFifo(0, 
                                               FLEXCAN_RX_FIFO_ID_FORMAT_A,
                                               idFilterTable);
    if (status != STATUS_SUCCESS) {
        return;
    }
    
    // 从RxFIFO接收消息
    flexcan_msgbuff_t rxMsg;
    while (1) {
        status = FLEXCAN_DRV_RxFifoBlocking(0, &rxMsg, 1000);
        if (status == STATUS_SUCCESS) {
            // 处理接收到的消息
            processRxFifoMessage(&rxMsg);
        }
    }
}
6.2.5 CAN FD配置示例
void can_fd_example(void)
{
    flexcan_user_config_t canConfig;
    
    // 获取默认配置
    FLEXCAN_DRV_GetDefaultConfig(&canConfig);
    
    // 启用CAN FD
    canConfig.fd_enable = true;
    canConfig.payload = FLEXCAN_PAYLOAD_SIZE_64;  // 64字节载荷
    
    // 仲裁相位位时序(500kbps)
    canConfig.bitrate.propSeg = 7;
    canConfig.bitrate.phaseSeg1 = 4;
    canConfig.bitrate.phaseSeg2 = 1;
    canConfig.bitrate.preDivider = 9;
    canConfig.bitrate.rJumpwidth = 1;
    
    // 数据相位位时序(2Mbps)
    canConfig.bitrate_cbt.propSeg = 2;
    canConfig.bitrate_cbt.phaseSeg1 = 1;
    canConfig.bitrate_cbt.phaseSeg2 = 1;
    canConfig.bitrate_cbt.preDivider = 4;
    canConfig.bitrate_cbt.rJumpwidth = 1;
    
    // 初始化FlexCAN
    FLEXCAN_DRV_Init(0, &canState, &canConfig);
    
    // 发送FD消息
    flexcan_data_info_t dataInfo = {
        .msg_id_type = FLEXCAN_MSG_ID_STD,
        .data_length = 32,          // 32字节数据
        .fd_enable = true,          // FD帧
        .enable_brs = true,         // 启用位速率切换
        .is_remote = false
    };
    
    uint8_t fdData[32];
    // 填充数据...
    
    FLEXCAN_DRV_ConfigTxMb(0, 0, &dataInfo, 0x123);
    FLEXCAN_DRV_Send(0, 0, &dataInfo, 0x123, fdData);
}
6.2.6 错误处理示例
void canErrorCallback(uint8_t instance, flexcan_error_event_type_t eventType,
                      flexcan_state_t *flexcanState)
{
    switch (eventType) {
        case FLEXCAN_TX_WARNING_EVENT:
            // 发送警告处理
            handleTxWarning();
            break;
        case FLEXCAN_RX_WARNING_EVENT:
            // 接收警告处理
            handleRxWarning();
            break;
        case FLEXCAN_BUS_OFF_ENTER_EVENT:
            // 总线关闭处理
            handleBusOff();
            break;
        case FLEXCAN_ERROR_OVERRUN_EVENT:
            // 过载错误处理
            handleOverrun();
            break;
        default:
            break;
    }
}

void can_error_handling_setup(void)
{
    // 安装错误回调函数
    FLEXCAN_DRV_InstallErrorCallback(0, canErrorCallback, NULL);
}

7. 与数据手册的对应关系

根据YTM32B1ME0数据手册中的FlexCAN章节:

  • 消息缓冲区: SDK中的消息缓冲区直接对应硬件的MB结构

  • 位时序参数: 传播段、相位段等参数与硬件寄存器一一对应

  • 过滤器机制: ID过滤器表对应硬件的过滤器寄存器

  • 中断系统: 各种事件中断与硬件中断源匹配

  • 错误管理: 错误计数器和错误状态与硬件错误管理单元对应

8. 最佳实践建议

  1. 位时序配置: 根据总线负载和节点数量选择合适的位时序参数

  2. 过滤器设置: 合理配置过滤器,减少不必要的中断和处理

  3. 错误处理: 实现完善的错误检测和恢复机制

  4. 总线仲裁: 合理分配消息ID优先级

  5. FD使用: 在需要高数据吞吐量时使用CAN FD

  6. DMA优化: 大量数据传输时使用DMA模式

9. 调试技巧

  1. 总线分析: 使用CAN分析仪监控总线通信

  2. 位时序验证: 确认位时序参数符合CAN规范

  3. 错误统计: 监控错误计数器,分析总线质量

  4. 过滤器调试: 验证过滤器配置是否正确

  5. 时序分析: 分析消息发送和接收的时序关系

10. 总结

YTM32B1M的FlexCAN控制器提供了完整的CAN总线通信功能,支持CAN 2.0和CAN FD协议。通过合理配置和使用FlexCAN驱动,可以实现可靠的总线通信,满足各种实时控制和数据传输需求。掌握FlexCAN的配置和使用方法对于开发汽车电子和工业控制应用至关重要。


本文档基于YTM32B1M SDK v1.0,如有更新请参考最新版本文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值