用C语言写得一个国标充电解析框架

一个基于 GB/T 27930-2015 电动汽车充电通信标准的简化版CAN通信框架示例。该代码模拟充电桩(充电机)与车辆BMS之间的CAN通信流程,涵盖握手、参数配置、充电控制等阶段。


  1. CAN通信基础定义
    c
    include <stdint.h>
    include <stdbool.h>
    include <string.h>

// CAN报文ID定义(GB/T 27930-2015)
define BMS_HANDSHAKE_ID 0x1801F456 // BMS握手报文ID
define CHARGER_HANDSHAKE_ID 0x1802F456 // 充电机握手报文ID
define BMS_PARAM_ID 0x1810F456 // BMS参数报文ID
define CHARGER_PARAM_ID 0x1820F456 // 充电机参数报文ID
define BMS_REALTIME_ID 0x1811F456 // BMS实时数据报文ID
define CHARGER_REALTIME_ID 0x1821F456 // 充电机实时数据报文ID

// CAN报文结构体
typedef struct {
uint32_t id; // CAN ID
uint8_t data8; // 数据域(8字节)
uint8_t len; // 数据长度
} CAN_Frame;

// 充电状态机
typedef enum {
STATE_INIT, // 初始化
STATE_HANDSHAKE, // 握手阶段
STATE_PARAM_CONFIG, // 参数配置
STATE_CHARGING, // 充电中
STATE_STOP // 停止
} ChargingState;


  1. CAN接口模拟函数(需根据实际硬件实现)
    c
    // 模拟CAN发送函数(需适配具体CAN控制器,如SocketCAN、STM32 HAL等)
    void can_send_frame(const CAN_Frame* frame) {
    // 实际代码中需调用硬件驱动发送CAN报文
    printf(“CAN发送: ID=0x%08X, 数据=”, frame->id);
    for (int i = 0; i < frame->len; i++) {
    printf("%02X “, frame->datai);
    }
    printf(”\n");
    }

// 模拟CAN接收函数(非阻塞式)
bool can_receive_frame(CAN_Frame* frame) {
// 实际代码中需从CAN缓冲区读取报文
// 此处模拟接收到BMS握手报文
static bool simulated_recv = false;
if (!simulated_recv) {
frame->id = BMS_HANDSHAKE_ID;
frame->len = 8;
memset(frame->data, 0, 8);
frame->data0 = 0xAA; // 模拟BMS握手数据
simulated_recv = true;
return true;
}
return false;
}


  1. 充电流程处理函数
    3.1 发送充电机握手报文
    c
    void send_charger_handshake() {
    CAN_Frame frame;
    frame.id = CHARGER_HANDSHAKE_ID;
    frame.len = 8;
    // 数据填充示例(具体字段需参考GB/T 27930)
    frame.data0 = 0x01; // 协议版本
    frame.data1 = 0x02; // 充电机类型
    // … 其他字段按标准填充
    can_send_frame(&frame);
    }

3.2 解析BMS握手报文
c
bool parse_bms_handshake(const CAN_Frame* frame) {
if (frame->id != BMS_HANDSHAKE_ID || frame->len < 8) return false;
// 解析BMS协议版本、电池类型等
uint8_t protocol_ver = frame->data0;
uint8_t battery_type = frame->data1;
// … 校验有效性
return true;
}

3.3 发送充电机参数报文
c
void send_charger_parameters(uint16_t max_voltage, uint16_t max_current) {
CAN_Frame frame;
frame.id = CHARGER_PARAM_ID;
frame.len = 8;
// 电压电流按大端格式填充
frame.data0 = (max_voltage >> 8) & 0xFF;
frame.data1 = max_voltage & 0xFF;
frame.data2 = (max_current >> 8) & 0xFF;
frame.data3 = max_current & 0xFF;
// … 其他参数
can_send_frame(&frame);
}


  1. 主状态机逻辑
    c
    int main() {
    ChargingState state = STATE_INIT;
    CAN_Frame rx_frame;

    while (1) {
    switch (state) {
    case STATE_INIT:
    printf(“进入初始化状态\n”);
    state = STATE_HANDSHAKE;
    break;

        case STATE_HANDSHAKE:
            // 发送充电机握手报文
            send_charger_handshake();
            // 等待BMS握手响应
            if (can_receive_frame(&rx_frame)) {
                if (parse_bms_handshake(&rx_frame)) {
                    printf("握手成功!\n");
                    state = STATE_PARAM_CONFIG;
                }
            }
            break;
    
        case STATE_PARAM_CONFIG:
            // 发送充电机最大输出电压、电流
            send_charger_parameters(7500, 200);  // 750V, 200A
            // 等待BMS参数报文(此处省略解析代码)
            state = STATE_CHARGING;
            break;
    
        case STATE_CHARGING: {
            // 模拟充电循环
            static uint32_t charge_time = 0;
            printf("充电中... 时间: %d秒\n", charge_time++);
            // 发送实时数据(电压、电流)
            CAN_Frame realtime_frame;
            realtime_frame.id = CHARGER_REALTIME_ID;
            realtime_frame.len = 8;
            // 模拟数据:电压=7500mV,电流=20000mA
            realtime_frame.data0 = 0x75;  // 7500mV高字节
            realtime_frame.data1 = 0x00;  // 7500mV低字节
            realtime_frame.data2 = 0x4E;  // 20000mA高字节
            realtime_frame.data3 = 0x20;  // 20000mA低字节
            can_send_frame(&realtime_frame);
            // 持续10秒后停止
            if (charge_time > 10) state = STATE_STOP;
            break;
        }
    
        case STATE_STOP:
            printf("充电结束!\n");
            return 0;
    }
    

    }
    }


  1. 关键流程说明

  2. 握手阶段:

    • 充电机发送 CHARGER_HANDSHAKE_ID 报文。
    • BMS回复 BMS_HANDSHAKE_ID 报文,双方确认协议版本和参数。
  3. 参数配置:

    • 充电机发送最大输出电压/电流(CHARGER_PARAM_ID)。
    • BMS发送电池参数(BMS_PARAM_ID),代码中需补充解析逻辑。
  4. 充电阶段:

    • 双方周期性发送实时数据(CHARGER_REALTIME_IDBMS_REALTIME_ID)。
    • 监测电压、电流是否超限,实现过压/过流保护。
  5. 停止条件:

    • 达到预设充电时间或BMS发送停止指令。

  1. 扩展建议

  2. 超时重试机制:
    c
    define HANDSHAKE_TIMEOUT_MS 3000
    uint32_t handshake_start_time = get_current_time();
    while (state == STATE_HANDSHAKE) {
    if (get_current_time() - handshake_start_time > HANDSHAKE_TIMEOUT_MS) {
    printf(“握手超时!\n”);
    state = STATE_STOP;
    }
    // … 接收处理
    }

  3. 校验和验证:
    c
    bool validate_checksum(const CAN_Frame* frame) {
    uint8_t checksum = 0;
    for (int i = 0; i < frame->len - 1; i++) {
    checksum += frame->datai;
    }
    return (checksum == frame->dataframe->len - 1);
    }

  4. 多线程处理:

    • 使用独立线程处理CAN接收和状态机逻辑(需平台支持)。

  1. 测试输出示例
    进入初始化状态
    CAN发送: ID=0x1802F456, 数据=01 02 00 00 00 00 00 00
    CAN接收: ID=0x1801F456, 数据=AA 00 00 00 00 00 00 00
    握手成功!
    CAN发送: ID=0x1820F456, 数据=75 00 4E 20 00 00 00 00
    充电中… 时间: 0秒
    CAN发送: ID=0x1821F456, 数据=75 00 4E 20 00 00 00 00
    充电中… 时间: 1秒

    充电结束!

该代码为简化实现,实际开发需根据GB/T 27930标准完善以下内容:

  • 完整报文字段解析(如电池类型、充电模式等)。
  • 错误状态处理(NRC码)。
  • 硬件CAN驱动适配(如STM32的HAL库、Linux SocketCAN)。
  • 实时性优化(中断驱动、DMA传输)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

最后一个bug

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值