基于STM32F103的BMS通信控制

基于STM32F103的BMS通信控制的核心代码框架,涵盖SPI通信(用于电池监测芯片)、CAN通信(用于整车通信)以及数据处理的基本结构。

1. 硬件接口定义

c 复制代码
// bms_config.h
#ifndef __BMS_CONFIG_H
#define __BMS_CONFIG_H

// SPI引脚定义(连接AFE芯片,如LTC6804)
#define SPI_CS_GPIO_PORT     GPIOA
#define SPI_CS_PIN           GPIO_Pin_4
#define SPI_AFE_SPI          SPI1

// CAN引脚定义
#define CAN_TX_PIN           GPIO_Pin_12
#define CAN_RX_PIN           GPIO_Pin_11
#define CAN_GPIO_PORT        GPIOA
#define CAN_REMAP            GPIO_Remap1_CAN1  // 使用重映射功能

// AFE芯片寄存器地址定义
#define AFE_READ_CELL_VOLTAGE  0x04
#define AFE_READ_TEMPERATURE   0x08
#define AFE_START_CONVERSION   0x10

// CAN消息ID定义(基于自定义协议)
#define BMS_STATUS_ID          0x1806E5F4
#define BMS_VOLTAGE_ID         0x1801E5F4
#define BMS_TEMPERATURE_ID     0x1802E5F4
#define CHARGER_CMD_ID         0x1803E5F4

// 安全阈值
#define CELL_OVP_THRESHOLD     4200  // 4.2V
#define CELL_UVP_THRESHOLD     2800  // 2.8V
#define TEMP_OVP_THRESHOLD     60    // 60°C

#endif

2. SPI通信模块(用于AFE芯片)

c 复制代码
// spi_afe.c
#include "stm32f10x.h"
#include "bms_config.h"

// SPI初始化
void SPI_AFE_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    
    // 1. 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
    
    // 2. 配置SPI引脚
    // PA5-SCK, PA6-MISO, PA7-MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 3. 配置片选引脚
    GPIO_InitStructure.GPIO_Pin = SPI_CS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI_CS_GPIO_PORT, &GPIO_InitStructure);
    
    // 4. SPI参数配置
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // 9MHz
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);
    
    SPI_Cmd(SPI1, ENABLE);
    SPI_CS_HIGH();  // 默认不选中
}

// SPI读写函数
uint8_t SPI_ReadWriteByte(uint8_t data) {
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI1, data);
    
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SPI1);
}

// 从AFE读取电芯电压
void AFE_ReadCellVoltages(uint16_t *voltages, uint8_t cell_count) {
    uint8_t cmd[4];
    uint8_t rx_buf[32];
    
    // 1. 发送读取命令
    cmd[0] = AFE_READ_CELL_VOLTAGE;
    cmd[1] = 0x00;  // 起始地址
    cmd[2] = cell_count * 2;  // 数据长度(每个电压2字节)
    
    SPI_CS_LOW();
    for(int i = 0; i < 3; i++) {
        SPI_ReadWriteByte(cmd[i]);
    }
    
    // 2. 读取电压数据
    for(int i = 0; i < cell_count * 2; i++) {
        rx_buf[i] = SPI_ReadWriteByte(0xFF);
    }
    SPI_CS_HIGH();
    
    // 3. 转换数据(假设AFE返回的数据格式为16位电压值,单位mV)
    for(int i = 0; i < cell_count; i++) {
        voltages[i] = (rx_buf[i*2] << 8) | rx_buf[i*2+1];
    }
}

// 发送配置命令到AFE
void AFE_SendConfig(uint8_t *config_data) {
    uint8_t cmd = 0x01;  // 写配置命令
    
    SPI_CS_LOW();
    SPI_ReadWriteByte(cmd);
    for(int i = 0; i < 6; i++) {  // 假设配置寄存器为6字节
        SPI_ReadWriteByte(config_data[i]);
    }
    SPI_CS_HIGH();
}

3. CAN通信模块

c 复制代码
// can_communication.c
#include "stm32f10x.h"
#include "bms_config.h"

// CAN初始化
void CAN_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    
    // 1. 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
    
    // 2. 配置CAN引脚
    GPIO_InitStructure.GPIO_Pin = CAN_TX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
    
    // 3. CAN参数配置
    CAN_InitStructure.CAN_TTCM = DISABLE;    // 非时间触发模式
    CAN_InitStructure.CAN_ABOM = ENABLE;     // 自动离线管理
    CAN_InitStructure.CAN_AWUM = ENABLE;     // 自动唤醒模式
    CAN_InitStructure.CAN_NART = DISABLE;    // 禁止报文自动重传
    CAN_InitStructure.CAN_RFLM = DISABLE;    // 接收FIFO不锁定
    CAN_InitStructure.CAN_TXFP = DISABLE;    // 发送优先级由标识符决定
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;  // 正常工作模式
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;        // 同步跳转宽度
    CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;        // 时间段1
    CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;        // 时间段2
    CAN_InitStructure.CAN_Prescaler = 36;           // 波特率: 36MHz/(1+9+4)/36 = 250Kbps
    
    CAN_Init(CAN1, &CAN_InitStructure);
    
    // 4. CAN过滤器配置
    CAN_FilterInitStructure.CAN_FilterNumber = 0;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
    
    // 5. 使能CAN中断
    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// 发送BMS状态信息
void CAN_SendBMSStatus(uint8_t soc, uint8_t soh, uint16_t pack_voltage, 
                      int16_t current, uint8_t fault_status) {
    CanTxMsg TxMessage;
    uint8_t data[8];
    
    // 填充数据
    data[0] = soc;                     // SOC 0-100%
    data[1] = soh;                     // SOH 0-100%
    data[2] = pack_voltage >> 8;       // 总电压高8位
    data[3] = pack_voltage & 0xFF;     // 总电压低8位
    data[4] = current >> 8;           // 电流高8位
    data[5] = current & 0xFF;         // 电流低8位
    data[6] = fault_status;           // 故障状态
    data[7] = 0x00;                   // 保留
    
    // 配置发送消息
    TxMessage.StdId = BMS_STATUS_ID;
    TxMessage.ExtId = 0x00;
    TxMessage.IDE = CAN_ID_STD;        // 标准帧
    TxMessage.RTR = CAN_RTR_DATA;      // 数据帧
    TxMessage.DLC = 8;                 // 数据长度8字节
    
    for(int i = 0; i < 8; i++) {
        TxMessage.Data[i] = data[i];
    }
    
    // 发送消息
    CAN_Transmit(CAN1, &TxMessage);
}

// CAN接收中断处理
void USB_LP_CAN1_RX0_IRQHandler(void) {
    CanRxMsg RxMessage;
    
    if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET) {
        CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
        
        // 处理接收到的消息
        switch(RxMessage.StdId) {
            case CHARGER_CMD_ID:
                // 处理充电命令
                CAN_HandleChargerCommand(RxMessage.Data);
                break;
                
            // 可以添加其他消息ID的处理
        }
        
        CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
    }
}

// 处理充电命令
void CAN_HandleChargerCommand(uint8_t *data) {
    uint8_t command = data[0];
    uint16_t voltage_limit = (data[1] << 8) | data[2];
    uint16_t current_limit = (data[3] << 8) | data[4];
    
    switch(command) {
        case 0x01:  // 启动充电
            BMS_EnableCharging(voltage_limit, current_limit);
            break;
        case 0x02:  // 停止充电
            BMS_DisableCharging();
            break;
        case 0x03:  // 设置充电参数
            BMS_SetChargeParameters(voltage_limit, current_limit);
            break;
    }
}

4. 主控制器逻辑

c 复制代码
// main.c
#include "stm32f10x.h"
#include "bms_config.h"
#include "spi_afe.h"
#include "can_communication.h"

// 全局变量
uint16_t cell_voltages[12];      // 12节电芯电压
int16_t temperatures[6];         // 6个温度传感器
uint8_t fault_status = 0;
uint8_t soc = 100;               // 初始SOC
uint32_t last_update_time = 0;

// 系统初始化
void System_Init(void) {
    // 1. 时钟初始化
    SystemInit();
    
    // 2. 外设初始化
    SPI_AFE_Init();
    CAN_Init();
    
    // 3. 定时器初始化(用于定时任务)
    TIM3_Init();
    
    // 4. 配置AFE芯片
    uint8_t afe_config[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    AFE_SendConfig(afe_config);
}

// 电池数据采集任务
void BMS_DataAcquisition_Task(void) {
    // 1. 读取电芯电压
    AFE_ReadCellVoltages(cell_voltages, 12);
    
    // 2. 读取温度(假设AFE也支持温度读取)
    // AFE_ReadTemperatures(temperatures, 6);
    
    // 3. 安全检查
    for(int i = 0; i < 12; i++) {
        if(cell_voltages[i] > CELL_OVP_THRESHOLD) {
            fault_status |= 0x01;  // 过压故障
            BMS_ShutdownCharge();  // 关闭充电
        }
        if(cell_voltages[i] < CELL_UVP_THRESHOLD) {
            fault_status |= 0x02;  // 欠压故障
            BMS_ShutdownDischarge(); // 关闭放电
        }
    }
}

// SOC估算函数
void BMS_SOC_Estimation(void) {
    static uint32_t capacity_remaining = 10000;  // 剩余容量,单位mAh
    static int32_t current_integral = 0;
    
    // 简单的安时积分法
    int16_t current = Get_Current_Sensor();  // 从电流传感器读取
    
    // 积分计算(假设每100ms执行一次)
    current_integral += current * 100;  // 电流单位mA,时间单位s
    
    if(current_integral >= 3600) {  // 3600mA*1s = 1mAh
        capacity_remaining -= 1;
        current_integral -= 3600;
    } else if(current_integral <= -3600) {
        capacity_remaining += 1;
        current_integral += 3600;
    }
    
    soc = (capacity_remaining * 100) / 10000;  // 计算百分比
    soc = (soc > 100) ? 100 : soc;
    soc = (soc < 0) ? 0 : soc;
}

// 主循环
int main(void) {
    System_Init();
    
    while(1) {
        // 1. 数据采集
        BMS_DataAcquisition_Task();
        
        // 2. SOC计算
        BMS_SOC_Estimation();
        
        // 3. 计算总电压
        uint16_t total_voltage = 0;
        for(int i = 0; i < 12; i++) {
            total_voltage += cell_voltages[i];
        }
        
        // 4. 每100ms发送一次CAN状态信息
        if(SystemTick - last_update_time > 100) {
            CAN_SendBMSStatus(soc, 100, total_voltage, 0, fault_status);
            last_update_time = SystemTick;
        }
        
        // 5. 被动均衡控制
        BMS_CellBalance();
        
        // 延时
        Delay_ms(10);
    }
}

// 被动均衡函数
void BMS_CellBalance(void) {
    uint16_t max_voltage = 0;
    uint16_t min_voltage = 0xFFFF;
    
    // 找出最高和最低电压
    for(int i = 0; i < 12; i++) {
        if(cell_voltages[i] > max_voltage) max_voltage = cell_voltages[i];
        if(cell_voltages[i] < min_voltage) min_voltage = cell_voltages[i];
    }
    
    // 如果压差超过阈值,启动均衡
    if((max_voltage - min_voltage) > 20) {  // 20mV阈值
        for(int i = 0; i < 12; i++) {
            if(cell_voltages[i] > (max_voltage - 5)) {  // 高于平均值的电芯
                AFE_EnableBalance(i);  // 开启对应电芯的均衡开关
            } else {
                AFE_DisableBalance(i);
            }
        }
    } else {
        AFE_DisableAllBalance();  // 关闭所有均衡
    }
}

参考代码 stm32f103通信电池中的BMS控制 www.youwenfan.com/contentcsu/56981.html

5. 关键点说明

  1. 安全机制:代码中应包含电压、温度保护,以及通信超时监测
  2. 滤波算法:实际应用中需要对ADC采样数据进行滤波(如滑动平均、卡尔曼滤波)
  3. 故障诊断:需要实现完善的故障诊断和存储机制
  4. 通信协议:CAN通信协议需与充电桩或整车控制器保持一致
  5. 实时性:关键保护功能需要在中断中实现,确保快速响应
相关推荐
天天爱吃肉82186 小时前
笔记:同步电机调试时电角度校正方法说明
大数据·人工智能·笔记·功能测试·嵌入式硬件·汽车
国科安芯6 小时前
空间激光通信系统中抗辐射 MCU 芯片应用研究
单片机·嵌入式硬件·架构·risc-v·安全性测试
Deitymoon6 小时前
STM32——外部中断
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑6 小时前
嵌入式——认识电子元器件——继电器系列
单片机·嵌入式硬件
智塑未来6 小时前
GJB电磁兼容标准对加固SSD有哪些要求?测试项目与合格指标
单片机·嵌入式硬件
IT_阿水7 小时前
基于STM32河流水质检测软件设计
stm32·单片机·嵌入式硬件
esmember7 小时前
电路研究12.1——保护电路设计指南
单片机·嵌入式硬件
Wave84520 小时前
基于 STM32 + ESP8266 + W25Q64 的双核 OTA 底层架构总结
stm32·嵌入式硬件·架构
xiangw@GZ21 小时前
WiFi 全世代(WiFi1~WiFi7)技术规范与核心参数总结
嵌入式硬件