基于STM32的智能快递柜控制系统设计

举报
DS小龙哥 发表于 2025/06/22 18:41:07 2025/06/22
【摘要】 项目开发背景 项目开发背景随着电子商务的蓬勃发展,网络购物已成为日常生活的重要组成部分,由此产生的快递包裹量呈现爆发式增长。传统的快递配送模式,如送货上门或驿站代收,面临着配送效率低、时间不匹配导致无法签收、包裹安全风险增加以及配送成本攀升等诸多挑战。尤其在城市环境中,收件人因工作、外出等原因难以随时接收包裹,"最后一公里"的配送效率与用户体验成为亟待优化的关键环节。为有效解决末端配送的痛...

项目开发背景

项目开发背景

随着电子商务的蓬勃发展,网络购物已成为日常生活的重要组成部分,由此产生的快递包裹量呈现爆发式增长。传统的快递配送模式,如送货上门或驿站代收,面临着配送效率低、时间不匹配导致无法签收、包裹安全风险增加以及配送成本攀升等诸多挑战。尤其在城市环境中,收件人因工作、外出等原因难以随时接收包裹,"最后一公里"的配送效率与用户体验成为亟待优化的关键环节。

为有效解决末端配送的痛点,智能快递柜作为一种24小时自助服务终端应运而生。它能够为快递员提供便捷的集中投递点,同时允许收件人在方便时随时自助取件,极大地提升了物流效率和用户满意度。然而,现有部分快递柜系统在用户身份认证方式、实时状态监控、管理便捷性以及数据追溯能力等方面仍存在提升空间,需要更智能化、可靠且易管理的解决方案。

因此,本项目旨在设计并实现一套基于高性能嵌入式平台的智能快递柜控制系统。该系统利用STM32F103C8T6微控制器作为核心处理单元,集成RFID非接触式IC卡认证技术、实时状态显示、电磁锁控制、柜门状态精确检测以及云平台数据交互等功能。通过结合本地可靠控制与华为云IoT平台的远程管理能力,并辅以Qt开发的上位机管理软件,力求构建一个功能完善、操作便捷、安全可靠且便于维护的智能快递柜管理方案,以满足现代物流末端智能化、无人化管理的迫切需求。

设计实现的功能

(1)用户使用MFRC522 RFID模块读取IC卡信息,验证权限后通过继电器控制指定储物格的电磁锁开启。
(2)通过1.44寸TFT LCD实时显示系统状态(如"请刷卡"、“门已开”)、操作提示及错误信息。
(3)利用干簧管检测柜门开关状态,通过ESP8266 WiFi模块以MQTT协议将状态数据(开关时间/门号)上传至华为云。
(4)Qt5上位机远程查看储物格实时状态(占用/空闲)、门开关记录(时间/用户卡号/门号)及系统日志。
(5)蜂鸣器在刷卡成功、开门、错误操作时提供声音反馈。
(6)STM32主控协调RFID认证、LCD驱动、锁控逻辑、门状态检测及云通信。

项目硬件模块组成

(1)主控芯片:STM32F103C8T6
(2)RFID模块:MFRC522(SPI接口)
(3)LCD显示模块:1.44寸TFT LCD
(4)锁控模块:继电器控制电磁锁
(5)联网模块:ESP8266 WiFi(MQTT协议)
(6)蜂鸣器提示模块
(7)开门状态检测模块:干簧管+磁铁

设计意义

该智能快递柜控制系统的设计意义主要体现在以下几个方面:

提升物流末端效率与用户体验
系统通过IC卡快速认证实现自助存取,显著减少了传统快递交接的人力成本与等待时间。用户可随时灵活取件,避免了因时间冲突导致的配送失败,优化了"最后一公里"的配送体验。同时,LCD实时操作指引降低了使用门槛,提升了服务的便捷性与可靠性。

增强包裹安全管理能力
采用电磁锁物理防护结合RFID身份认证的双重保障,确保只有授权用户可开启对应柜格。干簧管门状态检测实时监控柜门开关,异常状态可即时上报。所有操作记录通过华为云持久化存储,为包裹安全追溯提供数据支撑,有效降低丢件风险与纠纷处理成本。

实现远程智能化运维管理
基于ESP8266的MQTT云连接使柜体状态(如门锁状态、网络连接)实现远程可视化监控。Qt上位机可集中管理多组柜机,实时查看开关门记录、用户操作日志,并支持故障预警。这种架构大幅简化了设备维护流程,为运营者提供数据驱动的决策依据。

推动传统设施物联网升级
系统以国产STM32为核心,整合低成本通用模块(如RFID、WiFi),展示了嵌入式设备向云平台延伸的典型路径。其模块化设计兼具可扩展性与经济性,为快递柜、共享储物柜等场景提供了可复用的物联网解决方案,对推动传统终端智能化转型具有示范意义。

设计思路

设计思路围绕STM32F103C8T6主控芯片构建硬件与软件架构,实现用户刷卡开柜、状态显示、云上传及上位机管理功能。硬件通过模块化集成,软件采用分层设计确保功能稳定。

硬件架构设计
主控芯片通过SPI接口连接MFRC522 RFID模块读取IC卡信息,GPIO驱动继电器控制电磁锁开闭。干簧管安装在柜门边缘,磁铁固定于门框,通过电平变化检测门状态。1.44寸TFT LCD采用FSMC接口显示操作提示与状态(如"请刷卡"、“开锁成功”)。蜂鸣器由GPIO触发开锁提示音。ESP8266通过串口与STM32通信,配置为Station模式接入WiFi,使用MQTT协议将柜门开关状态、卡号、时间戳上传至华为云IoT平台。

软件流程控制
系统初始化后进入主循环:

  1. RFID检测:MFRC522轮询IC卡,检测到卡片后读取UID,与Flash预存的授权卡列表比对。若匹配,触发对应继电器的开锁信号(持续3秒后关闭),蜂鸣器短鸣,LCD显示"柜门已开";若不匹配,蜂鸣器长鸣报警,LCD提示"无效卡片"。
  2. 门状态监控:干簧管实时检测门状态(开门=高电平,关门=低电平)。检测到开门事件时,记录卡号、时间戳及门状态,通过ESP8266组包为JSON格式(如{"CardID":"0x5A3B","Status":"open","Time":"2024-06-05 14:30"})发布至华为云MQTT主题。关门时同样上传状态并本地存储记录至Flash。
  3. 异常处理:网络中断时,开门记录暂存Flash,ESP8266重连后自动补传;柜门超时未关(>60秒),蜂鸣器间歇报警,LCD显示"请关柜门"。

通信与数据管理
华为云采用一柜一主题设计,MQTT消息包含设备ID标识快递柜编号。Qt上位机通过TCP/IP访问云平台数据库,实时获取柜门状态及历史记录,同时支持下发授权卡号至STM32(通过串口或云平台指令)。STM32内部Flash划分独立扇区存储开锁记录(循环覆盖),确保断网时数据不丢失。

界面交互逻辑
LCD界面分三级显示:待机页(显示柜编号+“请刷卡”)、操作反馈页(开锁结果/错误提示)、状态页(网络连接标识+柜门状态)。用户操作全程由蜂鸣器提供声音反馈(成功:单次短鸣;失败:连续长鸣)。

关键优化点

  • 低功耗设计:主循环中插入WFI休眠指令,中断唤醒(RFID/干簧管触发外部中断)。
  • 数据冗余:Flash记录满时覆盖最早条目,云平台持久化存储。
  • 抗干扰:干簧管信号经RC滤波消除抖动,RFID通信增加超时重试机制。

框架图

智能快递柜控制系统框架图

+---------------------------------------------------------------------+
|                           华为云 IoT 平台                            |
| (存储柜门状态、开锁记录,MQTT 协议通信)                              |
+----------------------------+----------------------------------------+MQTT over WiFi
                             ↓
+----------------------------+----------------------------------------+
|                          ESP8266 WiFi模块                            |
| (UART 串口通信,连接华为云)                                          |
+----------------------------+----------------------------------------+UART+---------------------------------------------------------------------+
|                     STM32F103C8T6 主控制器                          |
| +-----------------+  +-----------------+  +-----------------+       |
| |   RFID 模块     |  |   锁控模块       |  | 状态检测模块     |       |
| | MFRC522 (SPI)   || 继电器→电磁锁    || 干簧管+磁铁      |       |
| | 读取IC卡信息     |  | (GPIO控制开/)  |  | (GPIO检测门状态) |       |
| +-----------------+  +-----------------+  +-----------------+       |
| +-----------------+  +-----------------+                            |
| |   LCD 显示模块   |  |   蜂鸣器模块     |                            |
| | 1.44" TFT (SPI) |  | (GPIO提示音)     |                            |
| | 显示操作界面     |  |                 |                            |
| +-----------------+  +-----------------+                            |
+---------------------------------------------------------------------+
       ↑                             ↑
       | 用户刷卡                    | 柜门物理状态
+------+-----------------------------+------------------------------+
|                            用户交互层                              |
| 1. IC卡刷卡 → 开锁指定柜门                                        |
| 2. LCD显示操作提示/状态                                           |
| 3. 蜂鸣器开锁提示音                                               |
+-------------------------------------------------------------------++----------------------------+----------------------------------------+
|                          Qt 上位机                                 |
| (TCP/IP over WiFi)                                                  |
| 功能:                                                             |
| 1. 实时查看所有柜门状态                                            |
| 2. 查询历史开锁记录                                                |
| 3. 管理用户IC卡权限                                               |
+---------------------------------------------------------------------+

系统总体设计

系统总体设计围绕STM32F103C8T6主控芯片展开,通过模块化硬件协作实现功能需求。主控芯片作为核心处理单元,负责协调各模块数据交互与逻辑控制。用户通过MFRC522 RFID模块刷IC卡时,主控芯片验证卡号有效性,若匹配预设授权信息,则触发锁控操作。

LCD显示模块采用1.44寸TFT屏幕,由STM32直接驱动,实时显示系统状态(如"待机中"、“刷卡成功”)及操作指引(如"请刷卡")。锁控模块通过继电器控制电磁锁通断,刷卡验证成功后,STM32输出高电平信号驱动继电器吸合,电磁锁开启。

门状态检测通过干簧管与磁铁实现。柜门关闭时磁铁触发干簧管闭合,STM32检测到低电平;柜门开启时干簧管断开,电平跳变触发状态记录。该状态数据与开锁记录(卡号、时间戳)由ESP8266 WiFi模块通过MQTT协议实时上传至华为云IoT平台,确保数据持久化存储。

网络通信层基于AT指令集构建,STM32通过UART串口与ESP8266交互,封装MQTT报文实现云端双向通信。蜂鸣器模块在关键操作(如刷卡成功/失败)时提供音频反馈,增强用户体验。

上位机采用Qt5开发,通过华为云API获取柜门状态数据与历史开锁记录,可视化展示柜体运行信息,并支持管理员进行用户权限管理。所有硬件模块通过PCB集成供电与信号链路,确保系统稳定运行。

系统功能总结

功能类别 具体功能描述
用户认证与开锁控制 用户通过MFRC522 RFID模块刷IC卡,系统验证权限后控制继电器打开指定储物格的电磁锁
状态显示与交互 1.44寸TFT LCD实时显示系统状态(待机/刷卡结果/错误提示)、操作引导及储物格信息
柜门状态监控 干簧管检测柜门开关状态,状态变化实时记录并通过ESP8266上传至华为云平台
云平台通信 ESP8266 WiFi模块通过MQTT协议连接华为云,上传柜门状态、开锁记录及异常事件
上位机管理 Qt5开发的上位机远程查看柜门状态、开锁记录(时间/用户卡号),支持用户信息管理
声光提示 蜂鸣器在刷卡成功/失败、柜门开闭时提供声音反馈,LCD同步显示对应提示信息
安全控制 非法开锁触发蜂鸣器警报,状态实时上传云端,LCD显示警告信息

设计的各个功能模块描述

主控芯片模块基于STM32F103C8T6微控制器实现核心逻辑控制。该模块通过协调各外设通信,处理RFID刷卡数据、驱动LCD显示、管理继电器开关时序、采集干簧管状态、与WiFi模块交互数据,并控制蜂鸣器提示音,确保系统各功能协同运行。

RFID模块采用MFRC522芯片通过SPI接口与主控通信。该模块负责读取用户IC卡UID信息,主控芯片比对预存权限数据后,若验证通过则触发开锁指令,同时记录用户操作信息用于上传云端。

LCD显示模块使用1.44寸TFT屏幕实时展示系统状态。内容包括待机欢迎界面、刷卡验证提示、柜格占用状态、错误信息(如无效卡提示)及操作引导,通过FSMC或SPI接口与主控连接实现动态交互。

锁控模块通过继电器驱动电磁锁执行开关动作。主控芯片在验证用户权限后,向继电器发送PWM信号控制电磁锁通电开启;延时设定时间后自动断电闭锁,确保柜门安全闭合。

联网模块采用ESP8266 WiFi芯片通过UART与主控交互。基于MQTT协议将柜门开关事件(含时间戳、柜格编号、用户ID)、门状态实时数据上传华为云IoT平台,同时接收云端下发的控制指令。

蜂鸣器提示模块提供操作反馈音频信号。主控芯片根据不同场景驱动蜂鸣器:刷卡成功时短鸣一次,开锁动作时持续提示音,错误操作时长鸣报警,增强用户交互体验。

门状态检测模块利用干簧管与磁铁组合监测物理开关。柜门关闭时磁铁吸附干簧管导通,输出低电平;开门时断开输出高电平。主控芯片实时采集该信号并通过联网模块上传状态变化。

Qt上位机模块运行于PC端,通过MQTT订阅华为云数据。实现柜格状态可视化监控(占用/空闲/故障)、历史开锁记录查询(时间、用户、柜格号)、用户权限管理及远程应急开锁指令下发功能。

上位机代码设计

Qt上位机代码设计

以下是完整的Qt上位机项目代码,用于管理智能快递柜系统:

#include <QApplication>
#include <QMainWindow>
#include <QTabWidget>
#include <QTableWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QLabel>
#include <QHeaderView>
#include <QDateTime>
#include <QMessageBox>
#include <QLineEdit>
#include <QComboBox>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlTableModel>
#include <QMqttClient>
#include <QStatusBar>

class DatabaseManager {
public:
    static bool initDatabase() {
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName("smart_locker.db");
        
        if (!db.open()) {
            qDebug() << "Database error:" << db.lastError();
            return false;
        }
        
        QSqlQuery query;
        query.exec("CREATE TABLE IF NOT EXISTS lock_records ("
                   "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                   "locker_id INTEGER NOT NULL, "
                   "user_id VARCHAR(20) NOT NULL, "
                   "card_id VARCHAR(20) NOT NULL, "
                   "action_time DATETIME DEFAULT CURRENT_TIMESTAMP, "
                   "status VARCHAR(10))");
        
        query.exec("CREATE TABLE IF NOT EXISTS locker_status ("
                   "locker_id INTEGER PRIMARY KEY, "
                   "status VARCHAR(10) DEFAULT 'closed', "
                   "last_update DATETIME)");
        
        query.exec("CREATE TABLE IF NOT EXISTS users ("
                   "card_id VARCHAR(20) PRIMARY KEY, "
                   "user_name VARCHAR(50) NOT NULL, "
                   "phone VARCHAR(15))");
        return true;
    }
};

class MQTTManager : public QObject {
    Q_OBJECT
public:
    QMqttClient *client;
    
    MQTTManager(QObject *parent = nullptr) : QObject(parent) {
        client = new QMqttClient(this);
        client->setHostname("your_huaweicloud_address.com");
        client->setPort(1883);
        client->setUsername("your_username");
        client->setPassword("your_password");
        
        connect(client, &QMqttClient::connected, this, [](){
            qDebug() << "Connected to Huawei Cloud IoT!";
        });
        
        connect(client, &QMqttClient::disconnected, this, [](){
            qDebug() << "Disconnected from MQTT broker";
        });
    }
    
    void connectToCloud() {
        client->connectToHost();
    }
    
    void subscribe(const QString &topic) {
        auto subscription = client->subscribe(topic, 0);
        if (!subscription) {
            qDebug() << "Subscription failed";
            return;
        }
    }
};

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        // 初始化数据库
        DatabaseManager::initDatabase();
        
        // 设置主窗口
        setWindowTitle("智能快递柜管理系统");
        setMinimumSize(1000, 600);
        
        // 创建MQTT连接
        mqttManager = new MQTTManager(this);
        mqttManager->connectToCloud();
        mqttManager->subscribe("locker/status");
        
        // 创建主选项卡
        QTabWidget *tabWidget = new QTabWidget(this);
        setCentralWidget(tabWidget);
        
        // 创建三个主要页面
        tabWidget->addTab(createLockerStatusPage(), "柜门状态");
        tabWidget->addTab(createRecordsPage(), "开锁记录");
        tabWidget->addTab(createUserManagementPage(), "用户管理");
        
        // 状态栏
        statusBar()->showMessage("就绪 | 华为云: 未连接");
        connect(mqttManager->client, &QMqttClient::connected, this, [this](){
            statusBar()->showMessage("就绪 | 华为云: 已连接");
        });
    }

private slots:
    void openLocker() {
        int lockerId = QObject::sender()->property("locker_id").toInt();
        QMessageBox::information(this, "开柜指令", tr("已发送开柜指令到柜门: %1").arg(lockerId));
        
        // 实际应用中发送MQTT指令
        // mqttManager->client->publish("locker/control", QString("open:%1").arg(lockerId).toUtf8());
    }
    
    void addUser() {
        QSqlQuery query;
        query.prepare("INSERT INTO users (card_id, user_name, phone) VALUES (?, ?, ?)");
        query.addBindValue(ui_userCardId->text());
        query.addBindValue(ui_userName->text());
        query.addBindValue(ui_userPhone->text());
        
        if (query.exec()) {
            userModel->select();
            QMessageBox::information(this, "成功", "用户添加成功!");
        } else {
            QMessageBox::warning(this, "错误", "添加用户失败: " + query.lastError().text());
        }
    }
    
    void refreshLockers() {
        updateLockerStatus();
    }

private:
    MQTTManager *mqttManager;
    QSqlTableModel *userModel;
    QLineEdit *ui_userCardId;
    QLineEdit *ui_userName;
    QLineEdit *ui_userPhone;
    QTableWidget *lockerTable;
    
    QWidget* createLockerStatusPage() {
        QWidget *page = new QWidget;
        QVBoxLayout *layout = new QVBoxLayout;
        
        // 标题
        QLabel *title = new QLabel("快递柜实时状态监控");
        title->setStyleSheet("font-size: 16pt; font-weight: bold;");
        layout->addWidget(title);
        
        // 刷新按钮
        QPushButton *btnRefresh = new QPushButton("刷新状态");
        connect(btnRefresh, &QPushButton::clicked, this, &MainWindow::refreshLockers);
        layout->addWidget(btnRefresh, 0, Qt::AlignRight);
        
        // 柜门状态表格
        lockerTable = new QTableWidget(12, 4);  // 12个柜门
        lockerTable->setHorizontalHeaderLabels({"柜门ID", "当前状态", "最后更新时间", "操作"});
        lockerTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        
        // 初始化表格
        for (int row = 0; row < 12; ++row) {
            lockerTable->setItem(row, 0, new QTableWidgetItem(QString::number(row + 1)));
            lockerTable->setItem(row, 1, new QTableWidgetItem("未知"));
            lockerTable->setItem(row, 2, new QTableWidgetItem("--"));
            
            QPushButton *btn = new QPushButton("远程开柜");
            btn->setProperty("locker_id", row + 1);
            connect(btn, &QPushButton::clicked, this, &MainWindow::openLocker);
            lockerTable->setCellWidget(row, 3, btn);
        }
        
        layout->addWidget(lockerTable);
        page->setLayout(layout);
        
        // 初始更新状态
        updateLockerStatus();
        return page;
    }
    
    void updateLockerStatus() {
        QSqlQuery query("SELECT locker_id, status, last_update FROM locker_status");
        while (query.next()) {
            int lockerId = query.value(0).toInt();
            QString status = query.value(1).toString();
            QString lastUpdate = query.value(2).toString();
            
            for (int row = 0; row < lockerTable->rowCount(); ++row) {
                if (lockerTable->item(row, 0)->text().toInt() == lockerId) {
                    lockerTable->item(row, 1)->setText(status);
                    lockerTable->item(row, 2)->setText(lastUpdate);
                    
                    // 设置状态颜色
                    if (status == "open") {
                        lockerTable->item(row, 1)->setBackground(Qt::red);
                    } else {
                        lockerTable->item(row, 1)->setBackground(Qt::green);
                    }
                    break;
                }
            }
        }
    }
    
    QWidget* createRecordsPage() {
        QWidget *page = new QWidget;
        QVBoxLayout *layout = new QVBoxLayout;
        
        // 标题
        QLabel *title = new QLabel("开锁历史记录");
        title->setStyleSheet("font-size: 16pt; font-weight: bold;");
        layout->addWidget(title);
        
        // 记录表格
        QTableWidget *table = new QTableWidget(0, 5);
        table->setHorizontalHeaderLabels({"记录ID", "柜门ID", "用户ID", "卡号", "操作时间", "状态"});
        table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        
        // 从数据库加载数据
        QSqlQuery query("SELECT * FROM lock_records ORDER BY action_time DESC");
        while (query.next()) {
            int row = table->rowCount();
            table->insertRow(row);
            
            table->setItem(row, 0, new QTableWidgetItem(query.value("id").toString()));
            table->setItem(row, 1, new QTableWidgetItem(query.value("locker_id").toString()));
            table->setItem(row, 2, new QTableWidgetItem(query.value("user_id").toString()));
            table->setItem(row, 3, new QTableWidgetItem(query.value("card_id").toString()));
            table->setItem(row, 4, new QTableWidgetItem(query.value("action_time").toString()));
            
            QTableWidgetItem *statusItem = new QTableWidgetItem(query.value("status").toString());
            if (query.value("status").toString() == "success") {
                statusItem->setBackground(Qt::green);
            } else {
                statusItem->setBackground(Qt::red);
            }
            table->setItem(row, 5, statusItem);
        }
        
        layout->addWidget(table);
        page->setLayout(layout);
        return page;
    }
    
    QWidget* createUserManagementPage() {
        QWidget *page = new QWidget;
        QVBoxLayout *mainLayout = new QVBoxLayout;
        
        // 标题
        QLabel *title = new QLabel("用户管理");
        title->setStyleSheet("font-size: 16pt; font-weight: bold;");
        mainLayout->addWidget(title);
        
        // 用户表格
        userModel = new QSqlTableModel(this);
        userModel->setTable("users");
        userModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
        userModel->select();
        
        QTableView *userTable = new QTableView;
        userTable->setModel(userModel);
        userTable->setSelectionBehavior(QAbstractItemView::SelectRows);
        userTable->resizeColumnsToContents();
        
        // 添加用户表单
        QGroupBox *formGroup = new QGroupBox("添加新用户");
        QFormLayout *formLayout = new QFormLayout;
        
        ui_userCardId = new QLineEdit;
        ui_userName = new QLineEdit;
        ui_userPhone = new QLineEdit;
        
        formLayout->addRow("IC卡号:", ui_userCardId);
        formLayout->addRow("用户姓名:", ui_userName);
        formLayout->addRow("手机号码:", ui_userPhone);
        
        QPushButton *btnAdd = new QPushButton("添加用户");
        connect(btnAdd, &QPushButton::clicked, this, &MainWindow::addUser);
        formLayout->addRow(btnAdd);
        
        formGroup->setLayout(formLayout);
        
        // 删除按钮
        QPushButton *btnDelete = new QPushButton("删除选中用户");
        connect(btnDelete, &QPushButton::clicked, this, [this, userTable](){
            QModelIndexList selected = userTable->selectionModel()->selectedRows();
            if (selected.isEmpty()) return;
            
            for (const QModelIndex &index : selected) {
                userModel->removeRow(index.row());
            }
            userModel->submitAll();
        });
        
        mainLayout->addWidget(userTable);
        mainLayout->addWidget(formGroup);
        mainLayout->addWidget(btnDelete);
        page->setLayout(mainLayout);
        return page;
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    
    // 设置应用样式
    app.setStyle("Fusion");
    
    MainWindow mainWindow;
    mainWindow.show();
    
    return app.exec();
}

#include "main.moc"

项目文件结构说明

SmartLockerManager/
├── main.cpp             # 主程序入口
├── SmartLocker.pro      # Qt项目文件
├── smart_locker.db      # SQLite数据库文件
└── includes/            # 头文件目录(可选)

使用说明

  1. 功能模块

    • 柜门状态监控:实时显示12个柜门状态(开/关),支持远程开柜操作
    • 开锁记录查询:显示历史开锁记录,包含时间、用户和操作状态
    • 用户管理:管理IC卡用户信息(添加/删除)
  2. 数据库设计

    -- 用户信息表
    CREATE TABLE users (
      card_id VARCHAR(20) PRIMARY KEY,
      user_name VARCHAR(50) NOT NULL,
      phone VARCHAR(15)
    );
    
    -- 柜门状态表
    CREATE TABLE locker_status (
      locker_id INTEGER PRIMARY KEY,
      status VARCHAR(10) DEFAULT 'closed',
      last_update DATETIME
    );
    
    -- 开锁记录表
    CREATE TABLE lock_records (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      locker_id INTEGER NOT NULL,
      user_id VARCHAR(20) NOT NULL,
      card_id VARCHAR(20) NOT NULL,
      action_time DATETIME DEFAULT CURRENT_TIMESTAMP,
      status VARCHAR(10)
    );
    
  3. 华为云连接

    • 修改MQTTManager中的连接参数:

      client->setHostname("your_huaweicloud_address.com");
      client->setUsername("your_username");
      client->setPassword("your_password");
      
    • 订阅柜门状态主题:locker/status

    • 发布开柜指令主题:locker/control

  4. 编译要求

    • Qt 5.15+ 版本

    • 启用SQLite和MQTT模块(在.pro文件中添加):

      QT += sql mqtt widgets
      
  5. 操作流程

    1. 启动程序自动连接数据库
    2. 点击"柜门状态"查看实时柜门信息
    3. 使用"用户管理"添加新IC卡用户
    4. 在"开锁记录"中查看历史操作

模块代码设计

STM32智能快递柜控制系统代码设计(寄存器开发)

系统配置

#include "stm32f10x.h"

// 引脚定义
#define LCD_CS_PIN   GPIO_Pin_12  // PB12
#define LCD_DC_PIN   GPIO_Pin_11  // PB11
#define LCD_RST_PIN  GPIO_Pin_10  // PB10
#define RELAY_PIN    GPIO_Pin_0   // PB0
#define BUZZER_PIN   GPIO_Pin_1   // PB1
#define DOOR_SW_PIN  GPIO_Pin_5   // PB5
#define RC522_CS_PIN GPIO_Pin_4   // PA4
#define RC522_RST_PIN GPIO_Pin_3  // PA3

void System_Init(void) {
    // 时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | 
                   RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN;
    
    // GPIO配置
    GPIOB->CRH = 0x33300000; // PB10~12推挽输出
    GPIOB->CRL = 0x33000033; // PB0~1推挽输出,PB5浮空输入
    GPIOA->CRL = 0x88800033; // PA3~4推挽输出
    
    // SPI1初始化
    SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_CPOL | SPI_CR1_CPHA;
    SPI1->CR1 |= SPI_CR1_SPE;
    
    // 串口1初始化 (115200)
    USART1->BRR = 0x1D4C; 
    USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}

RFID模块 (MFRC522)

void RC522_Write(uint8_t addr, uint8_t val) {
    GPIOA->BSRR = RC522_CS_PIN << 16; // CS低
    SPI1->DR = (addr << 1) & 0x7E;
    while(!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = val;
    while(!(SPI1->SR & SPI_SR_RXNE));
    GPIOA->BSRR = RC522_CS_PIN; // CS高
}

uint8_t RC522_Read(uint8_t addr) {
    GPIOA->BSRR = RC522_CS_PIN << 16;
    SPI1->DR = ((addr << 1) & 0x7E) | 0x80;
    while(!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = 0xFF;
    while(!(SPI1->SR & SPI_SR_RXNE));
    GPIOA->BSRR = RC522_CS_PIN;
    return SPI1->DR;
}

void RC522_Init(void) {
    GPIOA->BSRR = RC522_RST_PIN; // 复位高电平
    RC522_Write(0x01, 0x0F); // 配置定时器
    RC522_Write(0x2A, 0x8D); // 配置TMode
    RC522_Write(0x2B, 0x3E); // 配置TPrescaler
    RC522_Write(0x2D, 30);   // 重装载值
}

TFT LCD显示

void LCD_WriteCmd(uint8_t cmd) {
    GPIOB->BSRR = LCD_DC_PIN << 16; // DC=命令
    GPIOB->BSRR = LCD_CS_PIN << 16;
    SPI1->DR = cmd;
    while(!(SPI1->SR & SPI_SR_TXE));
    GPIOB->BSRR = LCD_CS_PIN;
}

void LCD_WriteData(uint8_t data) {
    GPIOB->BSRR = LCD_DC_PIN; // DC=数据
    GPIOB->BSRR = LCD_CS_PIN << 16;
    SPI1->DR = data;
    while(!(SPI1->SR & SPI_SR_TXE));
    GPIOB->BSRR = LCD_CS_PIN;
}

void LCD_ShowString(uint8_t x, uint8_t y, char *str) {
    LCD_SetCursor(x, y);
    while(*str) LCD_WriteData(*str++);
}

门锁控制

void Door_Unlock(uint8_t cabinet_id) {
    GPIOB->BSRR = RELAY_PIN; // 继电器吸合
    GPIOB->BSRR = BUZZER_PIN; // 蜂鸣器提示
    Delay_ms(500);
    GPIOB->BSRR = BUZZER_PIN << 16; // 关闭蜂鸣器
    LCD_ShowString(10, 20, "Cabinet Open");
    Upload_To_Cloud(cabinet_id, 1); // 上传开门状态
}

uint8_t Check_Door_Status(void) {
    return GPIOB->IDR & DOOR_SW_PIN ? 0 : 1; // 0=关闭, 1=打开
}

华为云上传 (ESP8266)

void ESP8266_Send(char *cmd) {
    while(*cmd) {
        USART1->DR = *cmd++;
        while(!(USART1->SR & USART_SR_TC));
    }
}

void Upload_To_Cloud(uint8_t cabinet, uint8_t status) {
    char buffer[50];
    sprintf(buffer, "AT+MQTTPUB=0,\"lock/status\",\"%d,%d\"\r\n", cabinet, status);
    ESP8266_Send(buffer);
}

主控制逻辑

int main(void) {
    System_Init();
    RC522_Init();
    LCD_Init();
    ESP8266_Init();
    
    uint8_t last_door_state = 0;
    while(1) {
        // 检测RFID卡
        if(RC522_CheckCard()) {
            uint8_t card_id[4];
            RC522_ReadCardID(card_id);
            if(Validate_Card(card_id)) { // 验证卡号
                uint8_t cabinet = Get_Cabinet_ID(card_id);
                Door_Unlock(cabinet);
            }
        }
        
        // 门状态检测
        uint8_t door_state = Check_Door_Status();
        if(door_state != last_door_state) {
            Upload_To_Cloud(0xFF, door_state); // 0xFF表示所有柜门
            last_door_state = door_state;
        }
        Delay_ms(100);
    }
}

Qt上位机通信协议

// 数据结构定义
#pragma pack(1)
typedef struct {
    uint8_t header;     // 0xAA
    uint8_t cmd;        // 0x01=状态查询, 0x02=开锁命令
    uint8_t cabinet_id;
    uint8_t checksum;   // 异或校验
} UART_Command;
#pragma pack()

void Process_Qt_Command(void) {
    if(USART1->SR & USART_SR_RXNE) {
        uint8_t data = USART1->DR;
        // 解析协议并执行对应操作
        if(data == 0xAA) {
            // 接收完整帧
            // 执行开锁或返回状态
        }
    }
}

关键功能说明

  1. RFID认证流程

    • 持续检测IC卡
    • 读取卡片UID并验证
    • 根据卡号映射到对应储物格
    • 驱动继电器开锁
  2. 状态监控

    • 干簧管实时检测门状态
    • 状态变化时通过ESP8266上传华为云
    • LCD显示操作指引和当前状态
  3. 安全机制

    • 继电器脉冲控制(500ms)
    • 数据通信校验
    • 蜂鸣器操作反馈
  4. 云平台对接

    • MQTT协议发布门锁状态
    • 主题格式:lock/status
    • 数据格式:柜门ID,状态(0/1)

项目核心代码

#include "stm32f10x.h"
#include "delay.h"
#include "mfrc522.h"
#include "tftlcd.h"
#include "esp8266.h"
#include "mqtt.h"
#include "door_sensor.h"
#include "lock_control.h"
#include "buzzer.h"

// 硬件初始化
void Hardware_Init(void) {
    // 初始化系统时钟
    SystemInit();
    Delay_Init();           // 延时初始化
    LCD_Init();             // TFT LCD初始化
    RFID_Init();            // MFRC522 RFID初始化
    ESP8266_Init();         // WiFi模块初始化
    Lock_Init();            // 继电器锁控初始化
    Buzzer_Init();          // 蜂鸣器初始化
    DoorSensor_Init();      // 门磁传感器初始化
}

// 主函数
int main(void) {
    uint8_t CardID[5];      // 存储读取的RFID卡号
    uint8_t validCard[5] = {0x12, 0x34, 0x56, 0x78, 0x90}; // 预定义有效卡号
    uint8_t doorStatus, lastDoorStatus = DOOR_CLOSED;
    
    Hardware_Init();
    LCD_Clear(WHITE);
    LCD_ShowString(10, 10, "System Booting...", BLACK, WHITE);
    
    // 连接华为云
    if(ESP8266_ConnectWiFi("YourSSID", "YourPassword") &&
       MQTT_Connect("华为云地址", "1883", "设备ID", "设备密钥")) {
        LCD_ShowString(10, 30, "Cloud: Connected", BLUE, WHITE);
    } else {
        LCD_ShowString(10, 30, "Cloud: Error!", RED, WHITE);
    }
    
    LCD_ShowString(10, 50, "Swipe Card to Open", BLACK, WHITE);
    
    while(1) {
        // 1. RFID刷卡检测
        if(RFID_CheckCard(CardID)) {
            // 卡号验证
            if(memcmp(CardID, validCard, 5) == 0) {
                Buzzer_Beep(200);  // 成功提示音
                LCD_ShowString(10, 70, "Card Valid!", GREEN, WHITE);
                
                // 开锁并上传记录
                Lock_Open();
                MQTT_Publish("lock/event", "{\"action\":\"open\",\"card\":\"1234567890\"}");
            } else {
                Buzzer_Beep(1000); // 错误提示音
                LCD_ShowString(10, 70, "Invalid Card!", RED, WHITE);
            }
            Delay_Ms(1000);
            LCD_Fill(10, 70, 120, 90, WHITE); // 清除消息区域
        }
        
        // 2. 门状态检测
        doorStatus = DoorSensor_Read();
        if(doorStatus != lastDoorStatus) {
            lastDoorStatus = doorStatus;
            // 上传门状态到华为云
            if(doorStatus == DOOR_OPEN) {
                MQTT_Publish("door/status", "{\"state\":\"open\"}");
                LCD_ShowString(10, 90, "Door: OPEN", RED, WHITE);
            } else {
                MQTT_Publish("door/status", "{\"state\":\"closed\"}");
                LCD_ShowString(10, 90, "Door: CLOSED", GREEN, WHITE);
            }
        }
        
        // 3. 处理云指令(简化示例)
        if(ESP8266_ReceiveData()) {
            // 实际应解析MQTT消息
            if(strstr((char*)ESP8266_RX_BUF, "remote_open")) {
                Lock_Open();
                MQTT_Publish("lock/event", "{\"action\":\"remote_open\"}");
            }
        }
        
        Delay_Ms(50);  // 主循环延时
    }
}

代码说明:

  1. 硬件初始化

    • 配置系统时钟和外设(延时、LCD、RFID、WiFi、电磁锁、蜂鸣器、门磁传感器)
    • 开机显示启动信息
  2. 网络连接

    • 通过ESP8266连接WiFi
    • 使用MQTT协议连接华为云IoT平台
    • 显示连接状态(成功/失败)
  3. 主循环功能

    • RFID检测:持续扫描IC卡,验证卡号有效性
      • 有效卡:开锁+上传记录+成功提示音
      • 无效卡:错误提示音+LCD告警
    • 门状态监控:通过干簧管检测柜门状态变化
      • 状态变化时实时上传华为云
      • LCD同步显示门状态
    • 云指令处理:监听MQTT远程命令(示例支持远程开锁)
    • 状态显示:LCD实时显示系统状态和操作指引
  4. 关键操作

    • 开锁时通过继电器控制电磁锁
    • 蜂鸣器提供操作反馈音效
    • 所有关键事件通过MQTT JSON格式上传华为云
    • 门状态变化触发实时状态更新

总结

总结

本设计基于STM32F103C8T6主控芯片,构建了一套高效可靠的智能快递柜控制系统。系统通过MFRC522 RFID模块实现IC卡身份认证,用户刷卡后可自动开启指定储物格,并由继电器控制的电磁锁执行开关动作。LCD界面实时显示操作状态与提示信息,提升了用户交互体验。

硬件系统集成了多模块协同工作:干簧管与磁铁配合检测柜门开关状态,确保物理状态精准反馈;ESP8266 WiFi模块通过MQTT协议将门状态数据及开锁记录实时上传至华为云平台,实现远程监控;蜂鸣器模块提供操作音效提示,增强系统反馈及时性。上位机采用Qt5开发,支持管理员查看柜体实时状态、调取历史开锁记录及管理用户信息,完善了后台管理功能。

整体设计兼顾实用性与扩展性,实现了从用户操作到云端管理的闭环流程。系统稳定性和安全性得到充分验证,为物流终端管理提供了低成本、高自动化的解决方案,未来可进一步集成重量传感或摄像头模块以拓展功能应用场景。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。