1. 项目概述:基于STM32的智能充电桩计费系统设计
在新能源车快速普及的今天,充电桩作为基础设施的核心部件,其计费系统的可靠性和精准度直接影响用户体验和运营效率。传统计费方案多采用工控机或PLC实现,成本居高不下。而基于STM32的方案,能以1/5的成本实现同等精度的计量功能,这正是本项目的核心价值所在。
我设计的这套系统采用模块化架构,主要包含四大功能单元:电参数采集模块(通过Modbus协议获取电压、电流、电量数据)、射频卡管理模块(实现IC卡读写与用户余额管理)、人机交互模块(通过串口触摸屏显示操作界面)以及双模通信模块(支持蓝牙和RS232数据传输)。这种架构既保证了系统功能的完整性,又便于后期维护和功能扩展。
2. 硬件设计详解
2.1 主控选型与电路设计
选择STM32F103C8T6作为主控芯片主要基于三点考量:首先,其72MHz主频和20KB RAM完全满足实时数据处理需求;其次,内置的3个USART接口可同时连接计量模块、触摸屏和通信模块;最后,丰富的外设资源(如SPI、I2C)便于扩展其他功能。实际PCB布局时,我将数字电路与模拟电路分区布置,并在电源入口处添加了TVS二极管(选用SMBJ15CA),有效解决了现场测试中遇到的浪涌冲击问题。
关键提示:STM32的NRST复位引脚必须接10kΩ上拉电阻,且布线时需远离高频信号线。曾因忽视此细节导致系统频繁异常复位。
2.2 电参数采集模块
采用国产HLW8032计量芯片,通过电流互感器(推荐使用YHDC SCT-013-000)采样交流信号,配合PC817光耦实现强弱电隔离。硬件连接方案如下:
| 计量芯片引脚 | STM32连接 | 功能说明 |
|---|---|---|
| CF | PA0 | 脉冲输出(用于电量校准) |
| TX | PA3 (USART2_RX) | Modbus通信线 |
| VCC | 3.3V | 需经LC滤波 |
Modbus协议解析时需特别注意数据格式转换。例如电流值原始数据为0~65535对应0~20A,实际代码处理如下:
c复制float ConvertCurrent(uint16_t raw) {
return (raw / 65535.0) * 20.0; // 转换为安培值
}
2.3 射频卡管理模块
RC522模块通过SPI接口与STM32通信,天线设计直接影响读卡距离。实测表明,当匹配电路中的电感L0调整为3.3uH(原设计1uH)时,读卡距离可从2cm提升至5cm。用户数据存储选用AT24C256 EEPROM,采用磨损均衡算法延长寿命:
c复制void WriteUserData(uint32_t blockAddr, UserData_t data) {
uint32_t actualAddr = (blockAddr % 256) * sizeof(UserData_t);
HAL_I2C_Mem_Write(&hi2c1, 0xA0, actualAddr, I2C_MEMADD_SIZE_16BIT,
(uint8_t*)&data, sizeof(data), 100);
}
3. 软件架构设计
3.1 实时数据采集处理
采用DMA+USART实现Modbus数据异步接收,通过环形缓冲区管理数据流。关键数据结构设计:
c复制typedef struct {
float voltage; // 电压(V)
float current; // 电流(A)
float power; // 功率(W)
uint32_t energy; // 累计电量(Wh)
uint8_t status; // 设备状态位
} EnergyData_t;
数据校验采用CRC16-Modbus算法,以下为优化后的校验函数:
c复制uint16_t CalcCRC16(uint8_t *data, uint8_t len) {
uint16_t crc = 0xFFFF;
while(len--) {
crc ^= *data++;
for(uint8_t i=0; i<8; i++)
crc = (crc & 1) ? (crc>>1)^0xA001 : (crc>>1);
}
return crc;
}
3.2 状态机设计
系统主逻辑采用有限状态机(FSM)实现,主要状态包括:
- 待机状态:显示欢迎界面
- 读卡状态:验证IC卡有效性
- 充电状态:实时计量并扣费
- 结算状态:打印消费凭证
状态转换示意图如下(伪代码表示):
c复制void MainFSM() {
switch(currentState) {
case STANDBY:
if(DetectCard()) currentState = CARD_READ;
break;
case CARD_READ:
if(ValidateCard()) currentState = CHARGING;
break;
// 其他状态处理...
}
}
4. 人机交互实现
4.1 触摸屏界面开发
选用迪文科技的DGUS屏,其特点是通过配置文件(.icl)定义界面元素,单片机只需发送简单指令。例如扣费界面控制代码:
c复制void ShowDeductPage(float amount) {
char buf[32];
sprintf(buf, "page 5\xFF\xFF\xFF"); // 跳转页面5
UART_Send(USART1, (uint8_t*)buf, strlen(buf));
sprintf(buf, "t0.txt=\"%.2f元\"\xFF\xFF\xFF", amount);
UART_Send(USART1, (uint8_t*)buf, strlen(buf));
}
经验分享:迪文屏的指令必须以0xFF 0xFF 0xFF结尾,初期因遗漏此细节导致多次通信失败。
4.2 多语言支持
通过预存不同语言的文本资源,实现中英文切换:
c复制const char *promptTable[2][5] = {
{"请插卡", "充电中", "余额不足", "扣费成功", "谢谢使用"}, // 中文
{"Insert Card", "Charging", "Low Balance", "Payment OK", "Thank You"} // 英文
};
void ShowPrompt(uint8_t lang, uint8_t msgId) {
printf("t2.txt=\"%s\"\r\n", promptTable[lang][msgId]);
}
5. 通信模块开发
5.1 双模通信切换
通过硬件跳线选择通信模式,软件实现自动识别:
c复制void DetectCommMode() {
if(HAL_GPIO_ReadPin(RS232_JUMPER_GPIO, RS232_JUMPER_PIN) == GPIO_PIN_SET) {
InitRS232(9600); // 初始化RS232
currentMode = MODE_RS232;
} else {
InitBluetooth(38400); // 初始化蓝牙
currentMode = MODE_BT;
}
}
5.2 蓝牙数据传输
使用HC-05模块时,需注意AT指令配置要点:
- 进入AT模式需在上电前按住KEY引脚
- 波特率固定为38400
- 修改设备名称指令:AT+NAME=EV_CHARGER
数据包格式设计为:
| 起始符(0xAA) | 数据长度 | 命令字 | 数据内容 | 校验和 |
|---|
6. 系统调试与优化
6.1 分模块测试流程
-
计量模块测试:
- 使用功率分析仪校准电压/电流精度
- 通过Modbus调试助手验证协议解析
-
射频模块测试:
- 用Mifare Classic Tool验证卡读写功能
- 压力测试:连续读写100次检查稳定性
-
整机联调:
- 模拟各种异常场景(如拔卡中断、通信超时)
- 进行72小时老化测试
6.2 常见问题排查
根据实测经验整理的故障速查表:
| 故障现象 | 可能原因 | 解决方案 |
|---|---|---|
| 读卡距离短 | 天线匹配电感值不准 | 调整L0为3.3uH |
| Modbus通信超时 | 终端电阻未接 | 在总线末端加120Ω电阻 |
| 触摸屏显示乱码 | 波特率不匹配 | 检查双方波特率设置 |
| EEPROM数据丢失 | 写操作未延时 | 每次写操作后加5ms延时 |
7. 安全防护设计
7.1 硬件保护措施
-
电源输入端部署两级防护:
- 前级:压敏电阻(14D471K)吸收大能量浪涌
- 后级:TVS管(SMBJ15CA)抑制残压
-
信号线路保护:
- RS232接口使用MAX3232ESE芯片
- 所有IO口串联100Ω电阻限流
7.2 软件容错机制
- 看门狗配置:
c复制IWDG_HandleTypeDef hiwdg;
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_32; // 32分频
hiwdg.Init.Reload = 0xFFF; // 约1.6s超时
HAL_IWDG_Init(&hiwdg);
- 数据备份策略:
- 关键参数在EEPROM中存双副本
- 每次上电进行数据校验
8. 生产测试方案
8.1 自动化测试夹具
开发基于Python的测试上位机,主要功能:
- 自动发送Modbus指令验证计量精度
- 通过NFC读写器模拟IC卡操作
- 记录测试结果生成报表
测试流程示例:
python复制def test_energy_measure():
send_modbus(0x01, 0x03, 0x0000, 0x0004)
data = receive_data()
assert 215 < data['voltage'] < 225 # 验证220V电压测量
8.2 老化测试标准
- 高温测试:55℃环境下连续运行48小时
- 电压波动测试:输入电压在180V-250V间波动
- 插拔测试:模拟500次IC卡插拔操作
9. 项目优化方向
在实际部署中,我发现还可以从三个方面进一步提升系统性能:
-
计量精度优化:采用软件校准算法,通过采集100个周期的波形数据计算RMS值,可将电流测量误差从1%降低到0.5%以内。
-
射频卡兼容性扩展:当前仅支持Mifare Classic卡,通过升级RC522固件可增加对DESFire卡的支持,这对需要更高安全性的场景尤为重要。
-
远程监控功能:在现有蓝牙通信基础上,增加4G模块选配项,通过MQTT协议上传数据到云平台。一个简单的实现方案是使用ESP8266作为协处理器:
c复制void SendToCloud(EnergyData_t data) {
char msg[128];
sprintf(msg, "{\"vol\":%.1f,\"cur\":%.3f,\"kwh\":%.2f}",
data.voltage, data.current, data.energy/1000.0);
UART_Send(USART3, (uint8_t*)msg, strlen(msg));
}
这个项目从原型到量产历时6个月,期间最大的收获是认识到嵌入式系统开发中"细节决定成败"的真谛。比如最初忽视TVS管导致现场故障率飙升,后来增加二级防护后完全解决了问题。建议开发者在设计阶段就充分考虑各种异常工况,预留足够的防护余量。