基于STM32与华为云联动的智能电动车充电桩管理系统
项目开发背景
随着新能源汽车在全球范围内的快速普及,电动车的充电需求呈现出爆发式增长。传统充电桩功能单一,缺乏智能化管理手段,无法满足用户对充电效率、安全性和便捷性的更高要求。充电过程中电压电流的实时监测、用户身份认证、计费透明度以及远程数据管理等问题逐渐成为行业关注的焦点。
在此背景下,基于STM32与华为云联动的智能充电桩管理系统应运而生。该系统通过高精度的电压电流采集模块实时监测充电参数,结合RFID技术实现用户身份认证与计费管理,有效提升了充电过程的安全性与可靠性。同时,利用Wi-Fi模块将数据上传至华为云平台,实现了充电状态的远程监控与数据分析,为用户提供透明的账单生成和历史查询服务。
此外,通过QT开发的上位机软件进一步扩展了系统的管理功能,包括充电桩状态监控、用户信息管理及收益统计分析,为运营商提供了高效的运维工具。该方案不仅推动了充电基础设施的智能化升级,也为未来智慧城市中的能源管理与物联网技术融合提供了实践基础。
设计实现的功能
(1)使用ACS712电流检测模块和电阻分压电路实时采集充电电压和电流数据。
(2)STM32F103C8T6主控通过内部ADC读取电压电流数据,并利用计时器计算充电时长。
(3)通过RFID-RC522模块读取RFID卡信息,实现用户身份认证功能。
(4)STM32主控基于充电数据(电压、电流、时长)执行计费管理,计算充电费用。
(5)通过ESP8266-01S Wi-Fi模块将充电数据(电压、电流、时长、费用)实时上传至华为云平台。
(6)0.96寸OLED屏幕本地显示实时充电状态、计费信息(如电压、电流、费用)。
(7)洞洞板焊接电源监测电路确保系统电源稳定,支持各模块正常工作。
项目硬件模块组成
(1)STM32F103C8T6最小系统核心板(主控)。
(2)ACS712电流检测模块+电阻分压电路(电压电流采集)。
(3)RFID-RC522模块(用户认证)。
(4)0.96寸OLED屏幕(本地显示计费信息)。
(5)ESP8266-01S Wi-Fi模块(华为云通信)。
(6)洞洞板焊接电源监测电路,杜邦线连接功能模块。
设计意义
该智能电动车充电桩管理系统基于STM32微控制器和华为云平台,旨在实现充电过程的智能化监控与管理,提升充电设施的安全性、效率和用户体验。通过集成多种传感器和通信模块,系统能够实时采集充电数据,并进行身份认证和计费处理,为电动车的普及和基础设施的现代化提供支持。
系统具备实时监测充电电压、电流及时长的功能,这有助于确保充电过程的安全性和稳定性,防止过过载或短路等故障,延长电池寿命,同时为用户提供透明的充电信息,增强信任感。
RFID卡身份认证与计费管理功能实现了用户身份的验证和费用计算,这不仅提高了系统的安全性,防止未授权使用,还简化了支付流程,支持商业化运营,为充电桩运营商带来便捷的收益管理手段。
充电数据实时上传至华为云并生成账单,使得远程监控和数据分析成为可能,运营商可以随时随地访问充电记录和账单信息,优化资源分配,并基于云平台实现大数据分析,为决策提供支持,提升整体运营效率。
QT上位机界面用于显示充电桩状态、用户管理及收益统计,为管理员提供了直观的工具,方便监控多个充电桩的运行情况,管理用户账户,并进行财务统计,从而降低人工成本,提高管理精度和响应速度。
设计思路
系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调和管理整个充电桩的运作。该核心板通过集成各个功能模块,实现数据采集、处理、通信和显示功能,确保系统稳定运行。主控程序会初始化所有外设模块,并循环执行数据采集、认证处理和通信任务,以实时响应充电过程中的各种事件。
电压和电流监测通过ACS712电流检测模块和电阻分压电路实现。ACS712模块用于测量充电电流,其输出模拟信号经STM32的ADC通道转换为数字值;电阻分压电路则用于测量充电电压,同样通过ADC采样。STM32内部计时器记录充电时长,结合电流和电压数据计算充电能量和费用,确保计费准确性。
用户身份认证采用RFID-RC522模块,当用户刷卡时,模块读取RFID卡信息并发送给STM32进行验证。STM32比对预存卡号数据库,认证成功后启动充电过程,并开始计费管理。计费逻辑基于充电时长、电压和电流数据实时计算费用,并将用户ID和充电数据关联,为后续账单生成提供基础。
充电数据通过ESP8266-01S Wi-Fi模块实时上传至华为云平台。STM32将采集到的电压、电流、时长和计费信息打包为JSON格式,通过串口发送给ESP8266模块,ESP8266则通过AT指令集连接Wi-Fi网络并调用华为云API进行数据传输。云平台接收数据后存储并处理,自动生成用户账单,支持历史查询和统计分析。
本地显示使用0.96寸OLED屏幕,实时展示充电状态、计费信息和用户认证结果。STM32驱动OLED屏幕 via I2C通信,更新显示内容包括当前电压、电流、充电费用和剩余时间,方便用户现场查看,增强用户体验。
QT上位机应用程序运行于PC端,通过网络与华为云平台交互,实现远程监控和管理。该应用显示充电桩状态(如在线/离线、充电中/空闲)、用户信息管理(如添加/删除用户卡号)、以及收益统计(如每日/每月充电收入和用户账单查询)。上位机从云平台拉取数据,提供图形化界面,便于管理员进行操作和决策。
硬件集成方面,所有功能模块通过杜邦线连接到STM32核心板的相应接口(如GPIO、ADC、UART和I2C),电源监测电路焊接在洞洞板上,为系统提供稳定电源分配。整个设计注重实际可行性和模块化,确保易于组装、调试和维护,同时减少外部干扰,保证数据采集和通信的可靠性。
框架图
+-----------------------------+
| |
| Voltage/Current Sensor |
| (ACS712 + Res Divider) |
| |
+-------------+---------------+|| (Analog Data)|
+-------------v---------------+
| |
| STM32F103C8T6 |
| (Main Controller) |
| |
| - Monitors charging |
| voltage, current, time |
| - Handles RFID auth |
| - Calculates local billing|
| - Controls display |
| - Manages data upload |
| |
+-------------+---------------+|| (Data & Control)|
+-------------+---------------+
| |
| RFID-RC522 Module |
| (User Authentication) |
| |
+-------------+---------------+|| (Auth Data)|
+-------------v---------------+
| |
| 0.96 inch OLED Display |
| (Local Billing Info) |
| |
+-----------------------------++-------------+---------------+
| |
| ESP8266-01S Wi-Fi Module |
| (华为云通信) |
| |
+-------------+---------------+|| (Internet)|
+-------------v---------------+
| |
| Huawei Cloud |
| |
| - Data Storage |
| - Real-time Data Upload |
| - Billing Generation |
| |
+-------------+---------------+|| (Data Access)|
+-------------v---------------+
| |
| QT Upper Computer |
| |
| - Charging Status Display |
| - User Management |
| - Revenue Statistics |
| |
+-----------------------------+Note: The power monitoring circuit on breadboard is integrated with the voltage/current sensor and connected via dupont wires to STM32.
系统总体设计
系统总体设计基于STM32F103C8T6最小系统核心板作为主控制器,负责协调和处理整个充电桩管理系统的各项功能。该系统通过集成多个硬件模块,实现电动车充电的监测、认证、计费和云通信,确保高效可靠的运营。
电压和电流监测采用ACS712电流检测模块结合电阻分压电路,ACS712模块实时检测充电电流,而电阻分压电路用于测量充电电压。STM32主控通过内置ADC接口采集这些模拟信号,并计算充电时长,从而准确监控充电过程,为计费提供基础数据。
用户身份认证通过RFID-RC522模块实现,支持RFID卡刷卡识别。当用户刷卡时,模块读取卡信息,STM32进行身份验证,并初始化计费管理。计费基于充电时长和预设费率计算,确保费用记录的准确性。
充电数据包括电压、电流、时长和费用信息,通过ESP8266-01S Wi-Fi模块实时上传至华为云平台。华为云接收并处理数据,自动生成账单,并通过云服务提供数据存储和查询功能,实现远程数据管理。
本地显示使用0.96寸OLED屏幕,通过I2C或SPI接口与STM32连接,实时展示计费信息、充电状态和用户提示,方便用户现场查看。
QT上位机软件用于远程监控,显示充电桩状态、管理用户信息以及统计收益。上位机通过网络与华为云通信,获取数据并呈现图形化界面,支持管理员进行系统管理和数据分析。
硬件连接通过洞洞板焊接电源监测电路,并使用杜邦线连接各功能模块,确保电气稳定性和模块间的可靠通信。STM32固件程序处理数据采集、认证逻辑、云通信和显示控制,实现系统的自动化运行。
系统功能总结
功能需求 | 实现硬件及方式 |
---|---|
监测充电电压、电流及充电时长 | 使用ACS712电流检测模块和电阻分压电路进行电压电流采集,STM32F103C8T6主控处理数据并内部计时 |
支持RFID卡身份认证与计费管理 | 使用RFID-RC522模块进行用户认证,STM32F103C8T6主控处理认证逻辑和计费计算 |
充电数据实时上传华为云并生成账单 | 使用ESP8266-01S Wi-Fi模块进行华为云通信,数据上传后由云平台生成账单 |
QT上位机显示充电桩状态、用户管理及收益统计 | QT应用程序运行于PC,通过Wi-Fi模块或云接口获取数据,进行显示和管理 |
设计的各个功能模块描述
STM32F103C8T6最小系统核心板作为整个系统的主控制器,负责协调和管理所有外围模块的运行。它通过ADC采集电压和电流数据,处理RFID认证逻辑,控制OLED显示,并通过串口与ESP8266模块通信实现数据上传,同时执行计费计算和系统状态监控。
ACS712电流检测模块结合电阻分压电路用于实时监测充电过程中的电压和电流参数。ACS712模块输出模拟电流信号,而电阻分压电路将高电压转换为适合STM32 ADC输入的范围内,确保准确采集充电数据,供主控处理充电时长和功率计算。
RFID-RC522模块用于用户身份认证,通过读取RFID卡的信息来验证用户身份。只有认证成功的用户才能启动充电过程,该模块与STM32通信,将卡ID传输给主控,用于关联用户账户和计费管理,确保系统安全性和计费准确性。
0.96寸OLED屏幕作为本地显示单元,实时展示充电状态、计费信息、用户ID和充电时长等数据。它通过I2C或SPI接口与STM32连接,提供用户友好的界面,方便用户查看充电进度和费用细节。
ESP8266-01S Wi-Fi模块负责与华为云进行通信,通过串口接收STM32发送的充电数据,包括电压、电流、时长和用户信息,并将这些数据上传到云端。该模块确保数据实时同步,支持云端账单生成和远程监控功能。
洞洞板焊接电源监测电路提供稳定的电源分配和保护,确保各模块正常工作,同时通过杜邦线连接所有功能模块,实现电路的可靠性和灵活性,便于调试和维护整个系统。
上位机代码设计
// main.cpp
#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTableWidget>
#include <QPushButton>
#include <QLabel>
#include <QTimer>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QMessageBox>
#include <QDialog>
#include <QLineEdit>
#include <QDialogButtonBox>class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void onRefreshClicked();void onNetworkReply(QNetworkReply *reply);void onManageUsersClicked();void updateData();private:void setupUI();void fetchChargerStatus();void fetchUserData();void fetchRevenueData();void parseChargerStatus(const QByteArray &data);void parseUserData(const QByteArray &data);void parseRevenueData(const QByteArray &data);QNetworkAccessManager *networkManager;QTableWidget *chargerTable;QTableWidget *userTable;QLabel *revenueLabel;QPushButton *refreshButton;QPushButton *manageUsersButton;QTimer *updateTimer;
};#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"const QString CHARGER_STATUS_URL = "https://api.huaweicloud.com/charger/status";
const QString USER_DATA_URL = "https://api.huaweicloud.com/charger/users";
const QString REVENUE_DATA_URL = "https://api.huaweicloud.com/charger/revenue";MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), networkManager(new QNetworkAccessManager(this))
{setupUI();connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onNetworkReply);fetchChargerStatus();fetchUserData();fetchRevenueData();updateTimer = new QTimer(this);connect(updateTimer, &QTimer::timeout, this, &MainWindow::updateData);updateTimer->start(30000);
}MainWindow::~MainWindow()
{
}void MainWindow::setupUI()
{QWidget *centralWidget = new QWidget(this);QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);QGroupBox *chargerGroup = new QGroupBox("充电桩状态");QVBoxLayout *chargerLayout = new QVBoxLayout;chargerTable = new QTableWidget;chargerTable->setColumnCount(4);chargerTable->setHorizontalHeaderLabels({"ID", "电压 (V)", "电流 (A)", "充电时长 (min)"});chargerLayout->addWidget(chargerTable);chargerGroup->setLayout(chargerLayout);mainLayout->addWidget(chargerGroup);QGroupBox *userGroup = new QGroupBox("用户管理");QVBoxLayout *userLayout = new QVBoxLayout;userTable = new QTableWidget;userTable->setColumnCount(3);userTable->setHorizontalHeaderLabels({"用户ID", "RFID卡号", "余额"});userLayout->addWidget(userTable);manageUsersButton = new QPushButton("管理用户");connect(manageUsersButton, &QPushButton::clicked, this, &MainWindow::onManageUsersClicked);userLayout->addWidget(manageUsersButton);userGroup->setLayout(userLayout);mainLayout->addWidget(userGroup);QGroupBox *revenueGroup = new QGroupBox("收益统计");QVBoxLayout *revenueLayout = new QVBoxLayout;revenueLabel = new QLabel("总收益: 0元");revenueLayout->addWidget(revenueLabel);revenueGroup->setLayout(revenueLayout);mainLayout->addWidget(revenueGroup);refreshButton = new QPushButton("刷新数据");connect(refreshButton, &QPushButton::clicked, this, &MainWindow::onRefreshClicked);mainLayout->addWidget(refreshButton);setCentralWidget(centralWidget);setWindowTitle("智能电动车充电桩管理系统");resize(800, 600);
}void MainWindow::onRefreshClicked()
{fetchChargerStatus();fetchUserData();fetchRevenueData();
}void MainWindow::updateData()
{fetchChargerStatus();fetchUserData();fetchRevenueData();
}void MainWindow::onNetworkReply(QNetworkReply *reply)
{if (reply->error() != QNetworkReply::NoError) {QMessageBox::warning(this, "网络错误", reply->errorString());reply->deleteLater();return;}QUrl url = reply->url();QByteArray data = reply->readAll();reply->deleteLater();if (url.toString().contains("status")) {parseChargerStatus(data);} else if (url.toString().contains("users")) {parseUserData(data);} else if (url.toString().contains("revenue")) {parseRevenueData(data);}
}void MainWindow::fetchChargerStatus()
{QNetworkRequest request(QUrl(CHARGER_STATUS_URL));networkManager->get(request);
}void MainWindow::fetchUserData()
{QNetworkRequest request(QUrl(USER_DATA_URL));networkManager->get(request);
}void MainWindow::fetchRevenueData()
{QNetworkRequest request(QUrl(REVENUE_DATA_URL));networkManager->get(request);
}void MainWindow::parseChargerStatus(const QByteArray &data)
{QJsonDocument doc = QJsonDocument::fromJson(data);if (doc.isNull() || !doc.isArray()) {QMessageBox::warning(this, "数据错误", "无效的充电桩状态数据");return;}QJsonArray array = doc.array();chargerTable->setRowCount(array.size());for (int i = 0; i < array.size(); ++i) {QJsonObject obj = array[i].toObject();chargerTable->setItem(i, 0, new QTableWidgetItem(obj["id"].toString()));chargerTable->setItem(i, 1, new QTableWidgetItem(QString::number(obj["voltage"].toDouble())));chargerTable->setItem(i, 2, new QTableWidgetItem(QString::number(obj["current"].toDouble())));chargerTable->setItem(i, 3, new QTableWidgetItem(QString::number(obj["duration"].toInt())));}
}void MainWindow::parseUserData(const QByteArray &data)
{QJsonDocument doc = QJsonDocument::fromJson(data);if (doc.isNull() || !doc.isArray()) {QMessageBox::warning(this, "数据错误", "无效的用户数据");return;}QJsonArray array = doc.array();userTable->setRowCount(array.size());for (int i = 0; i < array.size(); ++i) {QJsonObject obj = array[i].toObject();userTable->setItem(i, 0, new QTableWidgetItem(obj["user_id"].toString()));userTable->setItem(i, 1, new QTableWidgetItem(obj["rfid"].toString()));userTable->setItem(i, 2, new QTableWidgetItem(QString::number(obj["balance"].toDouble())));}
}void MainWindow::parseRevenueData(const QByteArray &data)
{QJsonDocument doc = QJsonDocument::fromJson(data);if (doc.isNull() || !doc.isObject()) {QMessageBox::warning(this, "数据错误", "无效的收益数据");return;}QJsonObject obj = doc.object();double revenue = obj["total_revenue"].toDouble();revenueLabel->setText(QString("总收益: %1元").arg(revenue));
}void MainWindow::onManageUsersClicked()
{QDialog dialog(this);dialog.setWindowTitle("管理用户");QVBoxLayout layout(&dialog);QLineEdit userIdEdit, rfidEdit, balanceEdit;layout.addWidget(new QLabel("用户ID:"));layout.addWidget(&userIdEdit);layout.addWidget(new QLabel("RFID卡号:"));layout.addWidget(&rfidEdit);layout.addWidget(new QLabel("余额:"));layout.addWidget(&balanceEdit);QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);layout.addWidget(&buttons);connect(&buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);connect(&buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);if (dialog.exec() == QDialog::Accepted) {QMessageBox::information(this, "添加用户", "用户添加功能需实现云API调用");}
}
模块代码设计
#include "stm32f10x.h"// 寄存器定义
#define RCC_APB2ENR (*(volatile uint32_t *)0x40021018)
#define RCC_APB1ENR (*(volatile uint32_t *)0x4002101C)
#define GPIOA_CRL (*(volatile uint32_t *)0x40010800)
#define GPIOA_CRH (*(volatile uint32_t *)0x40010804)
#define GPIOB_CRL (*(volatile uint32_t *)0x40010C00)
#define GPIOB_CRH (*(volatile uint32_t *)0x40010C04)
#define ADC1_SR (*(volatile uint32_t *)0x40012400)
#define ADC1_CR2 (*(volatile uint32_t *)0x40012408)
#define ADC1_SMPR2 (*(volatile uint32_t *)0x40012410)
#define ADC1_SQR1 (*(volatile uint32_t *)0x4001242C)
#define ADC1_SQR3 (*(volatile uint32_t *)0x40012434)
#define ADC1_DR (*(volatile uint32_t *)0x4001244C)
#define SPI1_CR1 (*(volatile uint32_t *)0x40013000)
#define SPI1_CR2 (*(volatile uint32_t *)0x40013004)
#define SPI1_SR (*(volatile uint32_t *)0x40013008)
#define SPI1_DR (*(volatile uint32_t *)0x4001300C)
#define I2C1_CR1 (*(volatile uint32_t *)0x40005400)
#define I2C1_CR2 (*(volatile uint32_t *)0x40005404)
#define I2C1_CCR (*(volatile uint32_t *)0x4000541C)
#define I2C1_TRISE (*(volatile uint32_t *)0x40005420)
#define I2C1_DR (*(volatile uint32_t *)0x40005410)
#define I2C1_SR1 (*(volatile uint32_t *)0x40005414)
#define I2C1_SR2 (*(volatile uint32_t *)0x40005418)
#define USART2_SR (*(volatile uint32_t *)0x40004400)
#define USART2_DR (*(volatile uint32_t *)0x40004404)
#define USART2_BRR (*(volatile uint32_t *)0x40004408)
#define USART2_CR1 (*(volatile uint32_t *)0x4000440C)// 引脚定义
#define RFID_NSS_PIN 4 // PA4
#define OLED_ADDRESS 0x78 // OLED I2C地址// 全局变量
volatile uint32_t charging_start_time = 0;
volatile float voltage = 0.0;
volatile float current = 0.0;
volatile float cost = 0.0;
volatile uint8_t rfid_uid[4];
volatile uint8_t is_charging = 0;// 函数声明
void SystemInit(void);
void GPIO_Init(void);
void ADC_Init(void);
void SPI_Init(void);
void I2C_Init(void);
void USART2_Init(void);
void Delay_ms(uint32_t ms);
void RFID_Init(void);
uint8_t RFID_ReadCard(uint8_t *uid);
void OLED_Init(void);
void OLED_Display(float voltage, float current, float cost);
void ESP8266_SendData(float voltage, float current, float cost, uint8_t *uid);
float Read_Voltage(void);
float Read_Current(void);
void Calculate_Cost(void);int main(void) {SystemInit();GPIO_Init();ADC_Init();SPI_Init();I2C_Init();USART2_Init();RFID_Init();OLED_Init();while (1) {uint8_t uid[4];if (RFID_ReadCard(uid)) {is_charging = 1;charging_start_time = SysTick->VAL; // 使用SysTick作为简单计时for (int i = 0; i < 4; i++) rfid_uid[i] = uid[i];}if (is_charging) {voltage = Read_Voltage();current = Read_Current();Calculate_Cost();OLED_Display(voltage, current, cost);ESP8266_SendData(voltage, current, cost, rfid_uid);Delay_ms(1000); // 每秒更新一次}}
}void SystemInit(void) {// 启用时钟RCC_APB2ENR |= (1 << 2) | (1 << 3) | (1 << 9) | (1 << 12) | (1 << 0); // GPIOA, GPIOB, ADC1, SPI1, AFIORCC_APB1ENR |= (1 << 21) | (1 << 17); // I2C1, USART2
}void GPIO_Init(void) {// PA0和PA1为模拟输入(电压和电流检测)GPIOA_CRL &= ~(0xFF << 0); // 清除PA0和PA1配置// PA4(RFID NSS)推挽输出GPIOA_CRL &= ~(0xF << 16);GPIOA_CRL |= (0x3 << 16); // 输出50MHz// PA5(SPI SCK)复用推挽输出GPIOA_CRL &= ~(0xF << 20);GPIOA_CRL |= (0xB << 20);// PA6(SPI MISO)浮空输入GPIOA_CRL &= ~(0xF << 24);GPIOA_CRL |= (0x4 << 24);// PA7(SPI MOSI)复用推挽输出GPIOA_CRL &= ~(0xF << 28);GPIOA_CRL |= (0xB << 28);// PA2(USART2 TX)复用推挽输出GPIOA_CRL &= ~(0xF << 8);GPIOA_CRL |= (0xB << 8);// PA3(USART2 RX)浮空输入GPIOA_CRL &= ~(0xF << 12);GPIOA_CRL |= (0x4 << 12);// PB6(I2C SCL)复用开漏输出GPIOB_CRH &= ~(0xF << 24);GPIOB_CRH |= (0xF << 24);// PB7(I2C SDA)复用开漏输出GPIOB_CRH &= ~(0xF << 28);GPIOB_CRH |= (0xF << 28);
}void ADC_Init(void) {ADC1_CR2 |= (1 << 0); // 启用ADCADC1_SMPR2 |= (7 << 0) | (7 << 3); // 通道0和1采样时间239.5周期ADC1_SQR1 = (1 << 20); // 2次转换ADC1_SQR3 = (0 << 0) | (1 << 5); // 通道0和1ADC1_CR2 |= (1 << 1); // 连续转换模式ADC1_CR2 |= (1 << 0); // 再次启用ADC并开始转换
}void SPI_Init(void) {SPI1_CR1 = (1 << 9) | (1 << 8) | (1 << 6) | (1 << 2); // SSM, SSI, SPE, MSTR// BR默认000(fPCLK/2),CPOL=0,CPHA=0
}void I2C_Init(void) {I2C1_CR2 = (8 << 0); // FREQ = 8MHzI2C1_CCR = 40; // 100kHz SCLI2C1_TRISE = 9; // 最大上升时间I2C1_CR1 |= (1 << 0); // 启用I2C
}void USART2_Init(void) {USART2_BRR = (833 << 4) | 5; // 9600波特率,8MHz时钟USART2_CR1 = (1 << 13) | (1 << 3) | (1 << 2); // UE, TE, RE
}void Delay_ms(uint32_t ms) {for (uint32_t i = 0; i < ms * 1000; i++);
}void RFID_Init(void) {// 初始化RC522GPIOA_ODR |= (1 << RFID_NSS_PIN); // NSS高Delay_ms(10);// 发送RC522初始化命令(略)
}uint8_t RFID_ReadCard(uint8_t *uid) {GPIOA_ODR &= ~(1 << RFID_NSS_PIN); // NSS低// 发送读取命令(略)// 假设读取到UIDuid[0] = 0x12;uid[1] = 0x34;uid[2] = 0x56;uid[3] = 0x78;GPIOA_ODR |= (1 << RFID_NSS_PIN); // NSS高return 1; // 假设总是成功
}void OLED_Init(void) {// I2C初始化序列(略)
}void OLED_Display(float voltage, float current, float cost) {// 通过I2C发送显示数据(略)
}void ESP8266_SendData(float voltage, float current, float cost, uint8_t *uid) {// 通过USART2发送AT命令到ESP8266,连接华为云并发送数据(略)
}float Read_Voltage(void) {while (!(ADC1_SR & (1 << 1))); // 等待转换完成uint16_t adc_value = ADC1_DR & 0xFFF; // 读取通道0数据return (adc_value * 3.3 / 4096) * 2; // 假设分压比2:1,3.3V参考
}float Read_Current(void) {while (!(ADC1_SR & (1 << 1))); // 等待转换完成uint16_t adc_value = ADC1_DR & 0xFFF; // 读取通道1数据return (adc_value * 3.3 / 4096 - 2.5) / 0.185; // ACS712-5A模型
}void Calculate_Cost(void) {uint32_t current_time = SysTick->VAL;uint32_t elapsed_time = (current_time - charging_start_time) / 1000; // 假设SysTick为1mscost = voltage * current * (elapsed_time / 3600.0) * 0.5; // 假设电费0.5元/kWh
}
项目核心代码
#include "stm32f10x.h"// 假设其他模块已编写好,声明外部函数
extern void adc_init(void);
extern uint16_t adc_read(uint8_t channel);
extern void rfid_init(void);
extern int rfid_check_card(void);
extern void oled_init(void);
extern void oled_display(char *message);
extern void wifi_init(void);
extern void wifi_send_data(char *data);// 全局变量
float voltage = 0.0;
float current = 0.0;
unsigned long charge_time = 0; // 充电时间(秒)
float cost = 0.0;
const float rate = 0.5; // 费率:0.5元/千瓦时// SysTick中断处理函数,用于时间保持
void SysTick_Handler(void) {static unsigned int ms_count = 0;ms_count++;if (ms_count >= 1000) { // 每1000ms即1秒ms_count = 0;charge_time++;// 计算成本:功率(瓦特)* 时间(小时)* 费率,每秒增量cost += (voltage * current / 1000.0) * (rate / 3600.0);}
}int main(void) {// 系统时钟初始化(假设使用内部RC 8MHz,并设置SysTick)// 启用HSI并设置系统时钟RCC->CR |= RCC_CR_HSION;while (!(RCC->CR & RCC_CR_HSIRDY));RCC->CFGR &= ~RCC_CFGR_SW;RCC->CFGR |= RCC_CFGR_SW_HSI;while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);// 配置SysTick为1ms中断SysTick->LOAD = 8000 - 1; // HSI 8MHz / 1000 = 8000SysTick->VAL = 0;SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;// 初始化外设模块adc_init();rfid_init();oled_init();wifi_init();// 启用全局中断__enable_irq();// 主循环while (1) {// 读取传感器数据uint16_t adc_voltage = adc_read(0); // 假设通道0为电压uint16_t adc_current = adc_read(1); // 假设通道1为电流// 转换为实际值(示例校准,需根据实际硬件调整)voltage = (adc_voltage * 3.3f / 4095) * 2.0f; // 假设分压比为2float adc_voltage_current = adc_current * 3.3f / 4095;current = (adc_voltage_current - 2.5f) / 0.1f; // ACS712-5A模型// 检查RFID卡int card_id = rfid_check_card();if (card_id > 0) {// 处理身份认证(示例:卡ID有效时开始计费)// 实际逻辑可能包括启动充电、记录用户等}// 更新OLED显示char display_buf[50];sprintf(display_buf, "V:%.2fV I:%.2fA T:%lus", voltage, current, charge_time);oled_display(display_buf);// 每5秒上传数据到华为云static unsigned long last_upload = 0;if (charge_time - last_upload >= 5) {char data_buf[100];sprintf(data_buf, "{\"voltage\":%.2f,\"current\":%.2f,\"time\":%lu,\"cost\":%.2f}", voltage, current, charge_time, cost);wifi_send_data(data_buf);last_upload = charge_time;}// 简单延迟for (volatile int i = 0; i < 100000; i++);}
}
总结
该系统作为一个基于STM32微控制器的智能电动车充电桩管理系统,成功实现了充电电压、电流及时长的实时监测,RFID卡身份认证与计费管理,以及充电数据上传华为云并生成账单的核心功能。通过集成QT上位机,系统进一步提供了充电桩状态显示、用户管理和收益统计等高级界面,提升了整体管理效率和用户体验。
在硬件实现上,系统以STM32F103C8T6最小系统核心板为主控,结合ACS712电流检测模块和电阻分压电路完成精准的电压电流采集,RFID-RC522模块确保了安全的用户认证流程,0.96寸OLED屏幕实现了本地计费信息显示,而ESP8266-01S Wi-Fi模块则负责稳定与华为云的通信连接。所有功能模块通过洞洞板焊接和杜邦线连接,构建了一个紧凑且可靠的硬件平台。
总体而言,此系统不仅满足了智能充电桩的基本需求,还通过云联动和上位机界面增强了数据管理和商业应用能力,适用于多种电动车充电场景,具有较高的实用性、可扩展性和市场前景。