基于STM32设计的智能图书馆书籍定位系统设计

举报
DS小龙哥 发表于 2025/12/25 15:19:42 2025/12/25
【摘要】 项目开发背景随着图书馆藏书量的不断增加和读者需求的日益多样化,传统图书馆管理模式面临诸多挑战。书籍错架、查找困难、借还流程效率低下等问题,不仅增加了管理员的工作负担,也降低了读者的体验满意度。人工盘点和管理方式容易导致数据更新延迟,影响图书馆资源的有效利用,亟需引入智能化技术来优化管理流程。物联网和嵌入式技术的快速发展为图书馆智能化改造提供了新的解决方案。RFID技术以其非接触式识别、多目...

项目开发背景

随着图书馆藏书量的不断增加和读者需求的日益多样化,传统图书馆管理模式面临诸多挑战。书籍错架、查找困难、借还流程效率低下等问题,不仅增加了管理员的工作负担,也降低了读者的体验满意度。人工盘点和管理方式容易导致数据更新延迟,影响图书馆资源的有效利用,亟需引入智能化技术来优化管理流程。

物联网和嵌入式技术的快速发展为图书馆智能化改造提供了新的解决方案。RFID技术以其非接触式识别、多目标读取和精确定位能力,成为实现书籍高效管理的理想选择。结合微控制器和无线通信技术,可以构建实时、准确的书籍监控系统,显著提升图书馆的运营效率和服务水平。

本项目基于STM32主控制器,通过集成RFID模块、显示设备和无线传输模块,旨在实现书籍的精准定位、状态监测和读者引导。系统能够自动识别书籍借还状态,实时追踪馆内分布,并通过OLED显示屏和LED指示灯为读者提供直观的寻书导航。同时,数据通过Wi-Fi上传至云平台,结合QT上位机实现书籍分布可视化和流通统计分析,为图书馆管理提供全面的数据支持。

该智能书籍定位系统不仅解决了传统管理中的核心问题,还通过错架报警和智能引导功能,进一步提升了图书馆的自动化水平。其低成本、高可靠性的设计,使得该系统在各类大中小型图书馆中具有广泛的应用潜力,为推动图书馆数字化转型提供了实用参考。

设计实现的功能

(1)实现书籍标签识别
(2)提供寻书导航
(3)指示书籍具体位置
(4)上传数据至华为云

项目硬件模块组成

(1)STM32F103C8T6最小系统核心板作为主控制器
(2)RFID-RC522模块实现书籍标签识别
(3)0.96寸OLED显示屏提供寻书导航
(4)LED指示灯指示书籍具体位置
(5)ESP8266-01S Wi-Fi模块上传数据至华为云
(6)洞洞板焊接RFID天线电路,杜邦线连接各模块

设计意义

这个基于STM32设计的智能图书馆书籍定位系统,通过集成RFID技术和嵌入式硬件,实现了书籍的精准定位与管理,有效提升了图书馆的运营效率。该系统能够自动识别书籍位置,减少人工干预,降低管理成本,同时为图书馆的智能化转型提供了可行的技术方案。

采用RFID-RC522模块进行书籍标签识别,确保了书籍信息的快速采集和准确追踪,避免了传统人工盘点中的错误和遗漏。这不仅提高了图书检索的响应速度,还增强了图书馆对藏书状态的实时掌控能力,为日常管理提供了可靠的数据支持。

实时监测书籍借还状态和馆内分布,使图书馆能够动态跟踪书籍流通情况,及时更新库存信息。通过ESP8266-01S Wi-Fi模块将数据上传至华为云,实现了远程监控和数据分析,便于管理员进行资源调配和决策优化,提升了图书馆的服务响应能力。

读者寻书引导功能通过0.96寸OLED显示屏提供直观的导航指示,帮助读者快速定位目标书籍,显著改善了借阅体验。错架图书报警则通过LED指示灯及时提示错误放置,减少了书籍乱架现象,维护了图书馆的秩序和资源利用率。

QT上位机显示图书馆书籍分布图和流通统计,为管理员提供了可视化的管理界面,便于分析书籍流动趋势和生成统计报告。这有助于图书馆进行长期规划和资源优化,提升了数据驱动的管理能力。

硬件组成如STM32F103C8T6核心板、RFID模块和OLED显示屏的集成,体现了嵌入式系统在现实应用中的稳定性和实用性。使用洞洞板和杜邦线连接方式,降低了系统构建的复杂性和成本,使得该设计易于推广到中小型图书馆,具有较高的实际应用价值。

设计思路

本系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调各模块工作,实现智能图书馆书籍的定位和管理。系统通过RFID-RC522模块读取书籍上的电子标签,获取书籍的唯一标识信息,从而实现对书籍的精确识别和位置追踪。书籍借还状态和馆内分布数据由STM32实时处理,并通过ESP8266-01S Wi-Fi模块将信息上传至华为云平台,确保数据的远程可访问性和实时更新。整体设计利用洞洞板焊接RFID天线电路,并使用杜邦线连接各模块,构建一个稳定可靠的硬件基础。

RFID技术的应用是系统核心,通过部署多个RFID阅读器在书架不同位置,系统能够检测书籍的当前位置和移动状态。当读者借还书籍时,RFID模块读取标签信息,STM32处理这些数据以判断书籍是否在正确位置,如果发现错架情况,会触发报警机制,提醒工作人员及时处理。同时,书籍的借还记录和馆内分布信息被实时更新,并通过Wi-Fi模块发送到云服务器,便于后续统计和分析。

为了提供便捷的用户体验,系统集成0.96寸OLED显示屏和LED指示灯。OLED显示屏用于显示寻书导航信息,例如书籍所在书架区域和路径指引,帮助读者快速定位目标书籍。LED指示灯则安装在书架上,通过点亮特定LED来直观指示书籍的具体位置,减少读者搜索时间。这些交互设计基于STM32的控制逻辑,确保信息准确传达。

数据通信部分依赖ESP8266-01S Wi-Fi模块,它将STM32处理后的书籍状态和分布数据上传至华为云。云平台存储这些信息后,QT上位机可以实时获取并显示图书馆书籍分布图和流通统计,如图书借还频率和热点区域分析。这使管理员能够远程监控图书馆运行状况,并优化资源管理。整个系统设计注重实用性和可靠性,无需额外功能扩展,即可满足智能图书馆的基本需求。

系统工作流程始于RFID模块扫描书籍标签,STM32解析数据后,一方面驱动OLED和LED进行本地导航,另一方面通过Wi-Fi上传数据至云。QT上位机从云平台拉取数据,可视化展示书籍分布和统计信息,实现闭环管理。这种设计确保了书籍定位的准确性、借还状态的可控性,以及错架图书的及时报警,提升了图书馆运营效率。

框架图

智能图书馆书籍定位系统框架图

+----------------+      +-----------------+
|   RFID-RC522   |----->| STM32F103C8T6   |
| (书籍标签识别)  |      |   (主控制器)    |
+----------------+      +-----------------+
                              |
         +-------------------+-------------------+
         |                   |                   |
         v                   v                   v
  +-------------+     +-------------+     +-------------+
  |   OLED      |     |   LED       |     | ESP8266-01S |
  | (寻书导航)  |     | (位置指示)  |     | (Wi-Fi上传) |
  +-------------+     +-------------+     +-------------+
                                              |
                                              v
                                        +-----------+
                                        |  华为云   |
                                        | (数据存储)|
                                        +-----------+
                                              |
                                              v
                                        +-----------+
                                        | QT上位机  |
                                        | (分布图)  |
                                        +-----------+

系统总体设计

本系统基于STM32F103C8T6最小系统核心板作为主控制器,集成RFID技术实现智能图书馆书籍的精确定位和管理。系统通过协调各硬件模块,实现对书籍借还状态和馆内分布的实时监测,并为读者提供寻书引导及错架图书报警功能。硬件组成包括RFID-RC522模块、0.96寸OLED显示屏、LED指示灯、ESP8266-01S Wi-Fi模块以及洞洞板焊接的RFID天线电路,各模块通过杜邦线连接构成完整系统。

RFID-RC522模块负责读取书籍上附着的RFID标签,实现书籍的唯一识别和位置追踪。天线电路焊接在洞洞板上,确保信号覆盖稳定,能够准确检测书籍在书架上的具体位置,并实时更新借还状态。主控制器处理RFID数据,判断书籍是否在正确架位,并在检测到错放时触发报警机制。

用户交互部分通过0.96寸OLED显示屏为读者提供寻书导航信息,例如显示书籍所在架位编号或路径指示。LED指示灯安装在书架上,根据控制器指令点亮以高亮显示目标书籍位置,辅助读者快速定位,减少查找时间。同时,系统通过实时监测书籍状态,自动识别借还操作,确保数据准确性。

数据通信由ESP8266-01S Wi-Fi模块实现,将书籍位置、借还状态和错架信息上传至华为云平台,实现远程数据存储和监控。QT上位机软件从云端获取数据,动态显示图书馆书籍分布图和流通统计,如图书借阅频率和馆内存放情况,便于管理员进行决策和维护。

系统整体设计注重实用性和可靠性,通过硬件模块的协同工作,实现书籍管理的自动化和智能化。所有功能均基于实际硬件实现,无需额外添加,确保了系统的稳定运行和高效服务。

系统功能总结

功能描述 实现方式
采用RFID技术实现书籍精确定位和管理 使用STM32F103C8T6核心板和RFID-RC522模块
实时监测书籍借还状态和馆内分布 通过RFID识别和ESP8266 Wi-Fi模块上传数据至华为云
读者寻书引导和错架图书报警 利用0.96寸OLED显示屏和LED指示灯
QT上位机显示图书馆书籍分布图和流通统计 数据经Wi-Fi上传,由QT上位机软件处理显示

设计的各个功能模块描述

STM32F103C8T6最小系统核心板作为主控制器,负责整个系统的协调与控制,处理来自各个模块的数据输入和输出,执行书籍定位、状态监测和报警逻辑,确保系统稳定运行。

RFID-RC522模块用于读取书籍上的RFID标签,实现书籍的精确定位和管理,检测书籍的借还状态,并通过天线电路识别标签信息,确保数据准确采集。

0.96寸OLED显示屏提供读者寻书引导功能,显示书籍位置信息和导航指示,帮助读者快速定位目标书籍,提升用户体验。

LED指示灯用于指示书籍的具体位置,当读者寻书时,LED灯亮起以标记书籍所在书架,辅助实现错架图书报警和位置提示。

ESP8266-01S Wi-Fi模块负责将书籍状态、馆内分布数据上传至华为云,实现实时监测和数据传输,支持远程管理和统计分析。

洞洞板焊接RFID天线电路和杜邦线连接各模块,确保硬件电路的稳定搭建和信号传输,为系统提供可靠的物理连接基础。

上位机代码设计

#include <QtWidgets>
#include <QtCharts>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTimer>

// 书籍信息结构体
struct BookInfo {
    QString id;
    QString title;
    QString author;
    QString location;
    bool isBorrowed;
    QDateTime lastUpdate;
};

// 主窗口类
class LibrarySystem : public QMainWindow {
    Q_OBJECT

public:
    LibrarySystem(QWidget *parent = nullptr) : QMainWindow(parent) {
        setupUI();
        setupNetwork();
        setupTimer();
        loadSampleData();
    }

private slots:
    void updateData() {
        fetchBookData();
        updateCharts();
    }
    
    void onBookLocated(const QString &bookId) {
        highlightBookLocation(bookId);
        showNavigationPath(bookId);
    }
    
    void onSearchRequested() {
        QString keyword = searchEdit->text();
        searchBooks(keyword);
    }

private:
    void setupUI() {
        // 主窗口设置
        setWindowTitle("智能图书馆管理系统");
        setMinimumSize(1200, 800);
        
        // 中央部件
        QWidget *centralWidget = new QWidget;
        setCentralWidget(centralWidget);
        
        // 主布局
        QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
        
        // 左侧面板 - 图书馆地图
        setupLibraryMap(mainLayout);
        
        // 右侧面板 - 控制和信息显示
        setupControlPanel(mainLayout);
    }
    
    void setupLibraryMap(QLayout *mainLayout) {
        QWidget *mapWidget = new QWidget;
        QVBoxLayout *mapLayout = new QVBoxLayout(mapWidget);
        
        // 地图标题
        QLabel *mapTitle = new QLabel("图书馆平面图");
        mapTitle->setAlignment(Qt::AlignCenter);
        mapTitle->setStyleSheet("font-size: 16pt; font-weight: bold;");
        mapLayout->addWidget(mapTitle);
        
        // 地图图形视图
        mapGraphicsView = new QGraphicsView;
        mapGraphicsScene = new QGraphicsScene;
        mapGraphicsView->setScene(mapGraphicsScene);
        mapGraphicsView->setRenderHint(QPainter::Antialiasing);
        mapLayout->addWidget(mapGraphicsView);
        
        mainLayout->addWidget(mapWidget, 2);
    }
    
    void setupControlPanel(QLayout *mainLayout) {
        QWidget *controlWidget = new QWidget;
        QVBoxLayout *controlLayout = new QVBoxLayout(controlWidget);
        
        // 搜索区域
        setupSearchArea(controlLayout);
        
        // 统计图表
        setupCharts(controlLayout);
        
        // 书籍列表
        setupBookList(controlLayout);
        
        // 状态信息
        setupStatusArea(controlLayout);
        
        mainLayout->addWidget(controlWidget, 1);
    }
    
    void setupSearchArea(QLayout *layout) {
        QGroupBox *searchGroup = new QGroupBox("书籍搜索");
        QVBoxLayout *searchLayout = new QVBoxLayout(searchGroup);
        
        QHBoxLayout *searchInputLayout = new QHBoxLayout;
        searchEdit = new QLineEdit;
        searchEdit->setPlaceholderText("输入书名、作者或ISBN...");
        QPushButton *searchBtn = new QPushButton("搜索");
        connect(searchBtn, &QPushButton::clicked, this, &LibrarySystem::onSearchRequested);
        
        searchInputLayout->addWidget(searchEdit);
        searchInputLayout->addWidget(searchBtn);
        searchLayout->addLayout(searchInputLayout);
        
        // 搜索结果
        searchResultList = new QListWidget;
        connect(searchResultList, &QListWidget::itemClicked, [this](QListWidgetItem *item) {
            onBookLocated(item->data(Qt::UserRole).toString());
        });
        searchLayout->addWidget(searchResultList);
        
        layout->addWidget(searchGroup);
    }
    
    void setupCharts(QLayout *layout) {
        QGroupBox *chartGroup = new QGroupBox("流通统计");
        QVBoxLayout *chartLayout = new QVBoxLayout(chartGroup);
        
        // 借阅统计图表
        borrowChartView = new QChartView;
        borrowChartView->setRenderHint(QPainter::Antialiasing);
        chartLayout->addWidget(borrowChartView);
        
        // 分类统计图表
        categoryChartView = new QChartView;
        categoryChartView->setRenderHint(QPainter::Antialiasing);
        chartLayout->addWidget(categoryChartView);
        
        layout->addWidget(chartGroup);
    }
    
    void setupBookList(QLayout *layout) {
        QGroupBox *bookGroup = new QGroupBox("书籍状态");
        QVBoxLayout *bookLayout = new QVBoxLayout(bookGroup);
        
        bookTable = new QTableWidget;
        bookTable->setColumnCount(5);
        bookTable->setHorizontalHeaderLabels({"书名", "作者", "位置", "状态", "最后更新"});
        bookTable->setSelectionBehavior(QAbstractItemView::SelectRows);
        bookLayout->addWidget(bookTable);
        
        layout->addWidget(bookGroup);
    }
    
    void setupStatusArea(QLayout *layout) {
        QGroupBox *statusGroup = new QGroupBox("系统状态");
        QVBoxLayout *statusLayout = new QVBoxLayout(statusGroup);
        
        statusText = new QTextEdit;
        statusText->setReadOnly(true);
        statusLayout->addWidget(statusText);
        
        // 控制按钮
        QHBoxLayout *buttonLayout = new QHBoxLayout;
        QPushButton *refreshBtn = new QPushButton("刷新数据");
        QPushButton *exportBtn = new QPushButton("导出报告");
        QPushButton *alarmBtn = new QPushButton("错架报警");
        
        connect(refreshBtn, &QPushButton::clicked, this, &LibrarySystem::updateData);
        
        buttonLayout->addWidget(refreshBtn);
        buttonLayout->addWidget(exportBtn);
        buttonLayout->addWidget(alarmBtn);
        statusLayout->addLayout(buttonLayout);
        
        layout->addWidget(statusGroup);
    }
    
    void setupNetwork() {
        networkManager = new QNetworkAccessManager(this);
        connect(networkManager, &QNetworkAccessManager::finished, 
                this, &LibrarySystem::onNetworkReply);
    }
    
    void setupTimer() {
        updateTimer = new QTimer(this);
        connect(updateTimer, &QTimer::timeout, this, &LibrarySystem::updateData);
        updateTimer->start(5000); // 5秒更新一次
    }
    
    void loadSampleData() {
        // 创建图书馆地图
        drawLibraryMap();
        
        // 初始化图表
        initCharts();
        
        // 添加示例书籍
        addSampleBooks();
        
        statusText->append("系统初始化完成 - " + QDateTime::currentDateTime().toString());
    }
    
    void drawLibraryMap() {
        // 清空场景
        mapGraphicsScene->clear();
        
        // 绘制书架
        QPen shelfPen(Qt::black, 2);
        QBrush shelfBrush(QColor(210, 180, 140));
        
        // 区域A
        QGraphicsRectItem *areaA = mapGraphicsScene->addRect(50, 50, 200, 300, shelfPen, shelfBrush);
        areaA->setData(0, "A区");
        
        // 区域B
        QGraphicsRectItem *areaB = mapGraphicsScene->addRect(300, 50, 200, 300, shelfPen, shelfBrush);
        areaB->setData(0, "B区");
        
        // 区域C
        QGraphicsRectItem *areaC = mapGraphicsScene->addRect(550, 50, 200, 300, shelfPen, shelfBrush);
        areaC->setData(0, "C区");
        
        // 添加区域标签
        QFont labelFont("Arial", 12, QFont::Bold);
        mapGraphicsScene->addText("A区 - 文学类", labelFont)->setPos(80, 360);
        mapGraphicsScene->addText("B区 - 科技类", labelFont)->setPos(330, 360);
        mapGraphicsScene->addText("C区 - 社科类", labelFont)->setPos(580, 360);
        
        // 添加入口
        QGraphicsEllipseItem *entrance = mapGraphicsScene->addEllipse(400, 400, 30, 30, QPen(Qt::green), QBrush(Qt::green));
        entrance->setData(0, "入口");
        
        mapGraphicsScene->addText("入口", labelFont)->setPos(430, 410);
    }
    
    void initCharts() {
        // 借阅统计图表
        QChart *borrowChart = new QChart;
        borrowChart->setTitle("今日借阅统计");
        
        QBarSeries *borrowSeries = new QBarSeries;
        QBarSet *borrowSet = new QBarSet("借阅量");
        *borrowSet << 15 << 22 << 18 << 25 << 19 << 17 << 14;
        borrowSeries->append(borrowSet);
        
        borrowChart->addSeries(borrowSeries);
        borrowChart->setAnimationOptions(QChart::SeriesAnimations);
        
        QStringList categories = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        QBarCategoryAxis *axisX = new QBarCategoryAxis;
        axisX->append(categories);
        borrowChart->addAxis(axisX, Qt::AlignBottom);
        borrowSeries->attachAxis(axisX);
        
        QValueAxis *axisY = new QValueAxis;
        axisY->setRange(0, 30);
        borrowChart->addAxis(axisY, Qt::AlignLeft);
        borrowSeries->attachAxis(axisY);
        
        borrowChartView->setChart(borrowChart);
        
        // 分类统计图表
        QChart *categoryChart = new QChart;
        categoryChart->setTitle("书籍分类统计");
        
        QPieSeries *categorySeries = new QPieSeries;
        categorySeries->append("文学类", 35);
        categorySeries->append("科技类", 25);
        categorySeries->append("社科类", 20);
        categorySeries->append("艺术类", 15);
        categorySeries->append("其他", 5);
        
        categoryChart->addSeries(categorySeries);
        categoryChart->setAnimationOptions(QChart::SeriesAnimations);
        
        categoryChartView->setChart(categoryChart);
    }
    
    void addSampleBooks() {
        // 添加示例书籍数据
        QList<BookInfo> sampleBooks = {
            {"B001", "C++程序设计", "李华", "A区-1-01", false, QDateTime::currentDateTime()},
            {"B002", "Qt开发指南", "张明", "A区-1-02", true, QDateTime::currentDateTime()},
            {"B003", "STM32实战", "王强", "B区-2-01", false, QDateTime::currentDateTime()},
            {"B004", "物联网技术", "赵丽", "B区-2-05", false, QDateTime::currentDateTime()},
            {"B005", "人工智能导论", "陈伟", "C区-3-03", true, QDateTime::currentDateTime()}
        };
        
        bookTable->setRowCount(sampleBooks.size());
        
        for (int i = 0; i < sampleBooks.size(); ++i) {
            const BookInfo &book = sampleBooks[i];
            
            bookTable->setItem(i, 0, new QTableWidgetItem(book.title));
            bookTable->setItem(i, 1, new QTableWidgetItem(book.author));
            bookTable->setItem(i, 2, new QTableWidgetItem(book.location));
            bookTable->setItem(i, 3, new QTableWidgetItem(book.isBorrowed ? "已借出" : "在馆"));
            bookTable->setItem(i, 4, new QTableWidgetItem(book.lastUpdate.toString("MM-dd hh:mm")));
            
            // 在地图上标记书籍位置
            markBookOnMap(book);
        }
        
        books = sampleBooks;
    }
    
    void markBookOnMap(const BookInfo &book) {
        // 根据位置信息在地图上标记书籍
        QPointF position = calculateBookPosition(book.location);
        
        QGraphicsEllipseItem *bookMarker = mapGraphicsScene->addEllipse(
            position.x(), position.y(), 10, 10, 
            QPen(Qt::red), 
            QBrush(book.isBorrowed ? Qt::gray : Qt::red)
        );
        
        bookMarker->setData(0, book.id);
        bookMarker->setData(1, book.title);
        bookMarker->setToolTip(book.title + "\n" + book.location);
    }
    
    QPointF calculateBookPosition(const QString &location) {
        // 简化的位置计算逻辑
        if (location.startsWith("A区")) return QPointF(100, 100);
        if (location.startsWith("B区")) return QPointF(350, 150);
        if (location.startsWith("C区")) return QPointF(600, 200);
        return QPointF(200, 200);
    }
    
    void fetchBookData() {
        // 模拟从华为云获取数据
        QNetworkRequest request(QUrl("http://your-huawei-cloud-api/books"));
        networkManager->get(request);
    }
    
    void onNetworkReply(QNetworkReply *reply) {
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray data = reply->readAll();
            processBookData(data);
            statusText->append("数据更新成功 - " + QDateTime::currentDateTime().toString());
        } else {
            statusText->append("数据更新失败: " + reply->errorString());
        }
        reply->deleteLater();
    }
    
    void processBookData(const QByteArray &data) {
        // 解析JSON数据并更新界面
        QJsonDocument doc = QJsonDocument::fromJson(data);
        if (doc.isArray()) {
            QJsonArray bookArray = doc.array();
            updateBookTable(bookArray);
        }
    }
    
    void updateBookTable(const QJsonArray &bookArray) {
        bookTable->setRowCount(bookArray.size());
        
        for (int i = 0; i < bookArray.size(); ++i) {
            QJsonObject bookObj = bookArray[i].toObject();
            
            bookTable->setItem(i, 0, new QTableWidgetItem(bookObj["title"].toString()));
            bookTable->setItem(i, 1, new QTableWidgetItem(bookObj["author"].toString()));
            bookTable->setItem(i, 2, new QTableWidgetItem(bookObj["location"].toString()));
            bookTable->setItem(i, 3, new QTableWidgetItem(bookObj["status"].toString()));
            bookTable->setItem(i, 4, new QTableWidgetItem(QDateTime::currentDateTime().toString("MM-dd hh:mm")));
        }
    }
    
    void updateCharts() {
        // 更新图表数据
        // 这里可以添加实际的统计逻辑
    }
    
    void searchBooks(const QString &keyword) {
        searchResultList->clear();
        
        for (const BookInfo &book : books) {
            if (book.title.contains(keyword, Qt::CaseInsensitive) || 
                book.author.contains(keyword, Qt::CaseInsensitive)) {
                
                QListWidgetItem *item = new QListWidgetItem(book.title + " - " + book.author);
                item->setData(Qt::UserRole, book.id);
                searchResultList->addItem(item);
            }
        }
    }
    
    void highlightBookLocation(const QString &bookId) {
        // 高亮显示书籍位置
        for (QGraphicsItem *item : mapGraphicsScene->items()) {
            if (item->data(0).toString() == bookId) {
                item->setPen(QPen(Qt::yellow, 3));
                item->setZValue(1);
                
                // 显示导航路径
                showNavigationToBook(item->pos());
                break;
            }
        }
    }
    
    void showNavigationPath(const QString &bookId) {
        // 显示寻书导航路径
        for (const BookInfo &book : books) {
            if (book.id == bookId) {
                QString message = QString("导航到: %1\n位置: %2\n状态: %3")
                    .arg(book.title)
                    .arg(book.location)
                    .arg(book.isBorrowed ? "已借出" : "在馆");
                
                QMessageBox::information(this, "寻书导航", message);
                break;
            }
        }
    }
    
    void showNavigationToBook(const QPointF &bookPos) {
        // 绘制导航路径
        QPointF entrancePos(415, 415); // 入口位置
        
        QPen pathPen(QColor(0, 255, 0), 3);
        pathPen.setStyle(Qt::DashLine);
        
        mapGraphicsScene->addLine(entrancePos.x(), entrancePos.y(), 
                                 bookPos.x() + 5, bookPos.y() + 5, pathPen);
    }

private:
    // UI组件
    QGraphicsView *mapGraphicsView;
    QGraphicsScene *mapGraphicsScene;
    QLineEdit *searchEdit;
    QListWidget *searchResultList;
    QTableWidget *bookTable;
    QChartView *borrowChartView;
    QChartView *categoryChartView;
    QTextEdit *statusText;
    
    // 网络和定时器
    QNetworkAccessManager *networkManager;
    QTimer *updateTimer;
    
    // 数据
    QList<BookInfo> books;
};

// 主函数
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    
    // 设置应用程序信息
    QApplication::setApplicationName("智能图书馆管理系统");
    QApplication::setApplicationVersion("1.0");
    
    LibrarySystem window;
    window.show();
    
    return app.exec();
}

#include "main.moc"

这个上位机代码实现了以下功能:

  1. 图书馆地图显示:使用QGraphicsView显示图书馆平面图,包括不同区域的书架布局
  2. 书籍搜索功能:支持按书名、作者搜索书籍
  3. 实时数据监控:通过定时器定期从云端获取最新数据
  4. 统计图表显示:使用Qt Charts显示借阅统计和分类统计
  5. 书籍状态管理:表格显示所有书籍的详细信息
  6. 寻书导航功能:高亮显示书籍位置并绘制导航路径
  7. 系统状态监控:实时显示系统运行状态和错误信息

代码采用模块化设计,便于维护和扩展,可以通过修改网络请求URL连接到实际的华为云服务。

模块代码设计

#include "stm32f10x.h"

// OLED显示屏定义
#define OLED_I2C I2C1
#define OLED_ADDRESS 0x78

// RFID-RC522引脚定义
#define RFID_CS_PIN GPIO_Pin_4
#define RFID_CS_PORT GPIOA
#define RFID_RST_PIN GPIO_Pin_3
#define RFID_RST_PORT GPIOA

// LED指示灯定义
#define LED1_PIN GPIO_Pin_13
#define LED1_PORT GPIOC
#define LED2_PIN GPIO_Pin_14
#define LED2_PORT GPIOC
#define LED3_PIN GPIO_Pin_15
#define LED3_PORT GPIOC

// ESP8266串口定义
#define WIFI_USART USART2

// 延时函数
void delay_ms(uint32_t nCount)
{
    for(; nCount != 0; nCount--){
        for(uint32_t i = 0; i < 8000; i++);
    }
}

// I2C初始化
void I2C_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    
    // PB6-SCL, PB7-SDA
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 400000;
    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);
}

// OLED写命令
void OLED_Write_Cmd(uint8_t cmd)
{
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
    
    I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    
    I2C_SendData(I2C1, 0x00); // 控制字节-命令
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_SendData(I2C1, cmd);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_GenerateSTOP(I2C1, ENABLE);
}

// OLED写数据
void OLED_Write_Data(uint8_t data)
{
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
    
    I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    
    I2C_SendData(I2C1, 0x40); // 控制字节-数据
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_SendData(I2C1, data);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_GenerateSTOP(I2C1, ENABLE);
}

// OLED初始化
void OLED_Init(void)
{
    delay_ms(100);
    OLED_Write_Cmd(0xAE); // 关闭显示
    OLED_Write_Cmd(0x20); // 内存地址模式
    OLED_Write_Cmd(0x10); // 页地址模式
    OLED_Write_Cmd(0xB0); // 设置页起始地址
    OLED_Write_Cmd(0xC8); // 设置扫描方向
    OLED_Write_Cmd(0x00); // 设置低列地址
    OLED_Write_Cmd(0x10); // 设置高列地址
    OLED_Write_Cmd(0x40); // 设置起始行
    OLED_Write_Cmd(0x81); // 设置对比度
    OLED_Write_Cmd(0xFF); // 对比度值
    OLED_Write_Cmd(0xA1); // 设置段重映射
    OLED_Write_Cmd(0xA6); // 正常显示
    OLED_Write_Cmd(0xA8); // 设置多路复用率
    OLED_Write_Cmd(0x3F); // 1/64 duty
    OLED_Write_Cmd(0xA4); // 整个显示打开
    OLED_Write_Cmd(0xD3); // 设置显示偏移
    OLED_Write_Cmd(0x00); // 无偏移
    OLED_Write_Cmd(0xD5); // 设置振荡器频率
    OLED_Write_Cmd(0x80); // 设置分频比
    OLED_Write_Cmd(0xD9); // 设置预充电周期
    OLED_Write_Cmd(0xF1); 
    OLED_Write_Cmd(0xDA); // 设置com引脚硬件配置
    OLED_Write_Cmd(0x12);
    OLED_Write_Cmd(0xDB); // 设置VCOMH
    OLED_Write_Cmd(0x40);
    OLED_Write_Cmd(0x8D); // 设置充电泵
    OLED_Write_Cmd(0x14);
    OLED_Write_Cmd(0xAF); // 开启显示
}

// OLED显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, char *str)
{
    OLED_Write_Cmd(0xB0 + y);
    OLED_Write_Cmd(((x & 0xF0) >> 4) | 0x10);
    OLED_Write_Cmd((x & 0x0F) | 0x01);
    
    while(*str){
        OLED_Write_Data(*str);
        str++;
    }
}

// SPI初始化 (用于RFID)
void SPI_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
    
    // SPI1引脚配置: 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);
    
    // RFID片选和复位引脚
    GPIO_InitStructure.GPIO_Pin = RFID_CS_PIN | RFID_RST_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_SetBits(RFID_CS_PORT, RFID_CS_PIN);
    GPIO_SetBits(RFID_RST_PORT, RFID_RST_PIN);
    
    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_64;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);
    SPI_Cmd(SPI1, ENABLE);
}

// 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);
}

// RFID写寄存器
void RFID_WriteReg(uint8_t addr, uint8_t val)
{
    GPIO_ResetBits(RFID_CS_PORT, RFID_CS_PIN);
    SPI_ReadWriteByte((addr << 1) & 0x7E);
    SPI_ReadWriteByte(val);
    GPIO_SetBits(RFID_CS_PORT, RFID_CS_PIN);
}

// RFID读寄存器
uint8_t RFID_ReadReg(uint8_t addr)
{
    uint8_t val;
    GPIO_ResetBits(RFID_CS_PORT, RFID_CS_PIN);
    SPI_ReadWriteByte(((addr << 1) & 0x7E) | 0x80);
    val = SPI_ReadWriteByte(0x00);
    GPIO_SetBits(RFID_CS_PORT, RFID_CS_PIN);
    return val;
}

// RFID初始化
void RFID_Init(void)
{
    GPIO_SetBits(RFID_RST_PORT, RFID_RST_PIN);
    delay_ms(1);
    GPIO_ResetBits(RFID_RST_PORT, RFID_RST_PIN);
    delay_ms(1);
    GPIO_SetBits(RFID_RST_PORT, RFID_RST_PIN);
    delay_ms(1);
    
    RFID_WriteReg(0x01, 0x0F);
    RFID_WriteReg(0x2A, 0x8D);
    RFID_WriteReg(0x2B, 0x3E);
    RFID_WriteReg(0x2D, 0x1E);
    RFID_WriteReg(0x2C, 0x00);
    RFID_WriteReg(0x15, 0x40);
    RFID_WriteReg(0x11, 0x3D);
    
    RFID_WriteReg(0x26, 0x07);
}

// RFID寻卡
uint8_t RFID_Request(uint8_t req_code, uint8_t *tag_type)
{
    uint8_t status;
    uint32_t backBits;
    
    RFID_WriteReg(0x0D, 0x07);
    
    status = RFID_CommWithTag(req_code, tag_type, &backBits);
    if(status != 0x00)
        return status;
        
    return 0x00;
}

// RFID防冲撞
uint8_t RFID_Anticoll(uint8_t *serNum)
{
    uint8_t status;
    uint8_t i;
    uint32_t backBits;
    uint8_t serNumCheck = 0;
    
    RFID_WriteReg(0x0D, 0x00);
    serNum[0] = 0x93;
    serNum[1] = 0x20;
    
    status = RFID_CommWithTag(0x93, serNum, &backBits);
    if(status == 0x00){
        for(i = 0; i < 4; i++){
            serNumCheck ^= serNum[i];
        }
        if(serNumCheck != serNum[i]){
            status = 0xFF;
        }
    }
    RFID_WriteReg(0x0D, 0x0F);
    return status;
}

// RFID与标签通信
uint8_t RFID_CommWithTag(uint8_t command, uint8_t *pData, uint32_t *pBits)
{
    uint8_t status = 0xFF;
    uint8_t irqEn = 0x00;
    uint8_t waitIRq = 0x00;
    uint8_t n, tmp;
    uint32_t i;
    
    switch(command){
        case 0x26:
            irqEn = 0x12;
            waitIRq = 0x10;
            break;
        case 0x93:
            irqEn = 0x12;
            waitIRq = 0x10;
            break;
    }
    
    RFID_WriteReg(0x02, irqEn | 0x80);
    RFID_WriteReg(0x04, 0x00);
    RFID_WriteReg(0x01, 0x00);
    RFID_WriteReg(0x0C, 0x00);
    
    RFID_WriteReg(0x09, 0x26);
    RFID_WriteReg(0x08, 0x00);
    RFID_WriteReg(0x0B, 0x87);
    
    RFID_WriteReg(0x01, 0x0F);
    
    for(i = 0; ; i++){
        n = RFID_ReadReg(0x04);
        if(n & waitIRq){
            break;
        }
        if(i >= 2000){
            return status;
        }
    }
    
    tmp = RFID_ReadReg(0x06);
    if(tmp & 0x1B){
        status = 0xFF;
    }
    
    if(status == 0x00){
        n = RFID_ReadReg(0x0A);
        tmp = RFID_ReadReg(0x0C);
        *pBits = (uint32_t)((n - 1) * 8 + tmp);
        
        if(n == 0){
            n = 1;
        }
        if(n > 16){
            n = 16;
        }
        
        for(i = 0; i < n; i++){
            pData[i] = RFID_ReadReg(0x09);
        }
    }
    
    return status;
}

// LED初始化
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = LED1_PIN | LED2_PIN | LED3_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    GPIO_SetBits(GPIOC, LED1_PIN | LED2_PIN | LED3_PIN);
}

// 控制LED指示灯
void LED_Control(uint8_t led_num, uint8_t state)
{
    switch(led_num){
        case 1:
            if(state) GPIO_SetBits(LED1_PORT, LED1_PIN);
            else GPIO_ResetBits(LED1_PORT, LED1_PIN);
            break;
        case 2:
            if(state) GPIO_SetBits(LED2_PORT, LED2_PIN);
            else GPIO_ResetBits(LED2_PORT, LED2_PIN);
            break;
        case 3:
            if(state) GPIO_SetBits(LED3_PORT, LED3_PIN);
            else GPIO_ResetBits(LED3_PORT, LED3_PIN);
            break;
    }
}

// 串口初始化 (用于ESP8266)
void USART_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    // USART2 TX-PA2, RX-PA3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    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_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);
    USART_Cmd(USART2, ENABLE);
}

// 串口发送字符串
void USART_SendString(USART_TypeDef* USARTx, char *str)
{
    while(*str){
        while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
        USART_SendData(USARTx, *str++);
    }
}

// ESP8266发送数据到华为云
void ESP8266_SendToCloud(char *book_id, char *location, char *status)
{
    char buffer[100];
    
    // 构建JSON数据
    sprintf(buffer, "AT+HTTPCLISEND=0,\"{\\\"book_id\\\":\\\"%s\\\",\\\"location\\\":\\\"%s\\\",\\\"status\\\":\\\"%s\\\"}\"\r\n", 
            book_id, location, status);
    
    USART_SendString(USART2, buffer);
    delay_ms(1000);
}

// 主函数
int main(void)
{
    uint8_t tag_type[2];
    uint8_t serial_num[5];
    uint8_t status;
    char display_buffer[20];
    
    // 系统时钟初始化
    SystemInit();
    
    // 各模块初始化
    I2C_Configuration();
    OLED_Init();
    SPI_Configuration();
    RFID_Init();
    LED_Init();
    USART_Configuration();
    
    // OLED显示欢迎信息
    OLED_ShowString(0, 0, "Smart Library");
    OLED_ShowString(0, 2, "System Ready");
    
    while(1){
        // RFID寻卡
        status = RFID_Request(0x26, tag_type);
        if(status == 0x00){
            // 防冲撞获取序列号
            status = RFID_Anticoll(serial_num);
            if(status == 0x00){
                // 显示书籍信息
                sprintf(display_buffer, "Book ID: %02X%02X%02X%02X", 
                        serial_num[0], serial_num[1], serial_num[2], serial_num[3]);
                OLED_ShowString(0, 4, display_buffer);
                
                // 根据序列号确定位置并点亮对应LED
                uint8_t location = serial_num[0] % 3 + 1;
                LED_Control(location, 1);
                
                // 发送数据到华为云
                char book_id[9];
                sprintf(book_id, "%02X%02X%02X%02X", 
                        serial_num[0], serial_num[1], serial_num[2], serial_num[3]);
                char loc_str[10];
                sprintf(loc_str, "Shelf%d", location);
                ESP8266_SendToCloud(book_id, loc_str, "detected");
                
                delay_ms(2000);
                LED_Control(location, 0);
                
                // 显示寻书引导
                OLED_ShowString(0, 6, "Go to Shelf");
                sprintf(display_buffer, "Number: %d", location);
                OLED_ShowString(0, 7, display_buffer);
                
                delay_ms(3000);
                OLED_ShowString(0, 4, "                ");
                OLED_ShowString(0, 6, "                ");
                OLED_ShowString(0, 7, "                ");
            }
        }
        delay_ms(500);
    }
}

项目核心代码

#include "stm32f10x.h"
#include "oled.h"
#include "rfid.h"
#include "wifi.h"
#include "led.h"

// 定义图书状态
#define BOOK_AVAILABLE    0
#define BOOK_BORROWED     1
#define BOOK_MISPLACED    2

// 图书信息结构体
typedef struct {
    uint8_t id[5];          // RFID标签ID
    uint8_t status;         // 图书状态
    uint8_t shelf;          // 书架编号
    uint8_t position;       // 位置编号
    uint8_t reader_id[10];  // 读者ID
} BookInfo;

// 全局变量
BookInfo current_book;
uint8_t book_found = 0;
uint8_t wifi_connected = 0;

// 函数声明
void System_Init(void);
void GPIO_Config(void);
void USART_Config(void);
void SPI_Config(void);
void TIM_Config(void);
void Process_RFID_Data(void);
void Update_OLED_Display(void);
void Send_To_Cloud(void);
void LED_Indicator(void);
void Delay_ms(uint32_t nTime);

int main(void)
{
    // 系统初始化
    System_Init();
    
    // 外设初始化
    GPIO_Config();
    USART_Config();
    SPI_Config();
    TIM_Config();
    
    // 模块初始化
    OLED_Init();
    RFID_Init();
    WIFI_Init();
    LED_Init();
    
    // 显示启动界面
    OLED_Clear();
    OLED_ShowString(0, 0, "Smart Library", 16);
    OLED_ShowString(0, 2, "System Starting", 16);
    Delay_ms(2000);
    
    // 连接WiFi
    wifi_connected = WIFI_Connect("Library_WiFi", "password123");
    if(wifi_connected) {
        OLED_ShowString(0, 4, "WiFi Connected", 16);
    } else {
        OLED_ShowString(0, 4, "WiFi Failed", 16);
    }
    Delay_ms(1000);
    
    while(1)
    {
        // 主循环任务
        Process_RFID_Data();
        
        if(book_found) {
            Update_OLED_Display();
            LED_Indicator();
            
            if(wifi_connected) {
                Send_To_Cloud();
            }
            
            book_found = 0;
        }
        
        // 系统延时
        Delay_ms(100);
    }
}

void System_Init(void)
{
    // 开启外设时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | 
                   RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN |
                   RCC_APB2ENR_USART1EN | RCC_APB2ENR_SPI1EN;
    
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_USART2EN;
    
    // 设置系统时钟
    FLASH->ACR |= FLASH_ACR_LATENCY_2;
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
    RCC->CR |= RCC_CR_HSEON;
    while(!(RCC->CR & RCC_CR_HSERDY));
    RCC->CFGR |= RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9;
    RCC->CR |= RCC_CR_PLLON;
    while(!(RCC->CR & RCC_CR_PLLRDY));
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    while(!(RCC->CFGR & RCC_CFGR_SWS_PLL));
}

void GPIO_Config(void)
{
    // LED指示灯配置
    GPIOB->CRH &= 0xFFFF0FFF;
    GPIOB->CRH |= 0x00003000;  // PB12推挽输出
    
    // RFID-RC522片选
    GPIOA->CRL &= 0xFFF0FFFF;
    GPIOA->CRL |= 0x00030000;  // PA4推挽输出
    
    // WiFi模块控制
    GPIOC->CRH &= 0xFF0FFFFF;
    GPIOC->CRH |= 0x00300000;  // PC13推挽输出
}

void USART_Config(void)
{
    // USART1 - WiFi模块
    GPIOA->CRH &= 0xFFFFF00F;
    GPIOA->CRH |= 0x000004B0;  // PA9(TX)推挽复用, PA10(RX)浮空输入
    
    USART1->BRR = 0x1D4C;      // 115200 @72MHz
    USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
    
    // USART2 - 调试输出
    GPIOA->CRL &= 0xFFFF00FF;
    GPIOA->CRL |= 0x00004B00;  // PA2(TX)推挽复用, PA3(RX)浮空输入
    
    USART2->BRR = 0x1D4C;      // 115200 @72MHz
    USART2->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}

void SPI_Config(void)
{
    // SPI1 - RFID模块
    GPIOA->CRL &= 0x000FFFFF;
    GPIOA->CRL |= 0xB4B00000;  // PA5(SCK), PA6(MISO), PA7(MOSI)复用推挽
    
    SPI1->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR | 
                SPI_CR1_BR_0 | SPI_CR1_SPE;
}

void TIM_Config(void)
{
    // TIM2用于延时和定时任务
    TIM2->PSC = 7200 - 1;      // 10kHz
    TIM2->ARR = 10000 - 1;     // 1s
    TIM2->CR1 = TIM_CR1_CEN;
}

void Process_RFID_Data(void)
{
    uint8_t card_id[5];
    
    // 检测RFID卡片
    if(RFID_CheckCard(card_id)) {
        // 读取卡片信息
        RFID_ReadCardData();
        
        // 复制卡片ID
        for(int i = 0; i < 5; i++) {
            current_book.id[i] = card_id[i];
        }
        
        // 查询图书信息(这里简化处理,实际应从数据库查询)
        current_book.shelf = (card_id[0] % 10) + 1;      // 书架1-10
        current_book.position = (card_id[1] % 20) + 1;   // 位置1-20
        
        // 判断图书状态
        if(card_id[2] > 200) {
            current_book.status = BOOK_BORROWED;
        } else if(card_id[3] != current_book.shelf) {
            current_book.status = BOOK_MISPLACED;
        } else {
            current_book.status = BOOK_AVAILABLE;
        }
        
        book_found = 1;
    }
}

void Update_OLED_Display(void)
{
    char buffer[20];
    
    OLED_Clear();
    
    // 显示图书位置
    OLED_ShowString(0, 0, "Book Location:", 16);
    sprintf(buffer, "Shelf:%d Pos:%d", current_book.shelf, current_book.position);
    OLED_ShowString(0, 2, buffer, 16);
    
    // 显示图书状态
    switch(current_book.status) {
        case BOOK_AVAILABLE:
            OLED_ShowString(0, 4, "Status:Available", 16);
            break;
        case BOOK_BORROWED:
            OLED_ShowString(0, 4, "Status:Borrowed", 16);
            break;
        case BOOK_MISPLACED:
            OLED_ShowString(0, 4, "Status:Misplaced!", 16);
            break;
    }
    
    // 显示导航指引
    OLED_ShowString(0, 6, "Go to Shelf", 16);
}

void Send_To_Cloud(void)
{
    char data_buffer[100];
    
    // 构建JSON数据
    sprintf(data_buffer, 
            "{\"book_id\":\"%02X%02X%02X%02X%02X\",\"shelf\":%d,\"position\":%d,\"status\":%d}",
            current_book.id[0], current_book.id[1], current_book.id[2],
            current_book.id[3], current_book.id[4],
            current_book.shelf, current_book.position, current_book.status);
    
    // 通过WiFi发送到华为云
    WIFI_SendData(data_buffer);
}

void LED_Indicator(void)
{
    // 根据图书状态控制LED
    switch(current_book.status) {
        case BOOK_AVAILABLE:
            // 绿灯常亮
            LED_Green_On();
            LED_Red_Off();
            break;
        case BOOK_BORROWED:
            // 红灯闪烁
            LED_Red_Toggle();
            LED_Green_Off();
            break;
        case BOOK_MISPLACED:
            // 红绿交替闪烁
            LED_Red_Toggle();
            LED_Green_Toggle();
            break;
    }
}

void Delay_ms(uint32_t nTime)
{
    TIM2->CNT = 0;
    while(TIM2->CNT < nTime * 10);  // 10kHz计时器
}

// 串口发送函数(用于调试)
void USART_SendString(USART_TypeDef* USARTx, char *str)
{
    while(*str) {
        while(!(USARTx->SR & USART_SR_TXE));
        USARTx->DR = (*str++ & 0xFF);
    }
}

总结

本系统基于STM32微控制器设计,实现了智能图书馆的书籍精确定位与管理功能。通过集成RFID技术,系统能够高效识别书籍标签,实时追踪借还状态和馆内分布,同时提供读者寻书导航和错架图书报警服务,显著提升了图书馆的自动化水平和用户体验。

硬件部分采用STM32F103C8T6核心板作为控制中心,结合RFID-RC522模块进行书籍识别,0.96寸OLED显示屏用于显示导航信息,LED指示灯辅助定位书籍位置。此外,ESP8266-01S Wi-Fi模块将数据上传至华为云平台,实现远程监控,而洞洞板焊接的RFID天线电路和杜邦线连接确保了系统的稳定性和扩展性。

总体而言,该系统通过模块化设计实现了图书馆管理的智能化和可视化,不仅优化了书籍流通流程,还降低了人工管理成本,为现代图书馆的数字化转型提供了实用解决方案。未来,该系统可进一步集成数据分析功能,以支持更高效的资源调度和决策支持。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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