基于STM32的智能车位监测系统设计

举报
DS小龙哥 发表于 2025/06/22 18:39:42 2025/06/22
【摘要】 项目开发背景随着城市化进程加速和机动车保有量持续攀升,"停车难"已成为困扰城市管理和民生体验的普遍问题。传统停车场依赖人工引导或简易刷卡系统,存在空位信息不透明、车主绕行寻找车位效率低下、高峰期拥堵加剧等问题,不仅造成时间与能源浪费,也降低了停车场资源利用率。为解决上述痛点,物联网技术在智慧停车领域的应用需求日益迫切。基于STM32的智能车位监测系统通过在每个车位部署超声波传感器实时采集车...

项目开发背景

随着城市化进程加速和机动车保有量持续攀升,"停车难"已成为困扰城市管理和民生体验的普遍问题。传统停车场依赖人工引导或简易刷卡系统,存在空位信息不透明、车主绕行寻找车位效率低下、高峰期拥堵加剧等问题,不仅造成时间与能源浪费,也降低了停车场资源利用率。

为解决上述痛点,物联网技术在智慧停车领域的应用需求日益迫切。基于STM32的智能车位监测系统通过在每个车位部署超声波传感器实时采集车辆在位状态,将物理空间数字化。该系统以高性价比的STM32F103C8T6微控制器为核心,结合HC-SR04模块实现精准非接触测距,通过本地OLED屏与红绿LED双色指示,为车主及管理员提供直观的车位状态反馈。

同时,系统通过ESP8266 Wi-Fi模块将车位数据以MQTT协议上传至华为云物联网平台,打破信息孤岛。云端数据整合与分析能力使得车位利用率监控、历史数据统计及远程管理成为可能。配套开发的Qt上位机软件进一步为停车场运营方提供可视化监管界面,实现车位状态动态展示、异常报警及数据报表生成,显著提升管理效率和用户停车体验,为智慧城市基础设施建设提供可靠的技术支撑。

设计实现的功能

(1)使用HC-SR04超声波模块实时检测车位车辆状态(有车/无车)
(2)通过红绿双色LED指示车位状态:红灯表示有车,绿灯表示无车
(3)在0.96寸SPI OLED显示屏上本地显示车位状态信息(如车位编号、占用情况)
(4)通过ESP8266模块建立WiFi连接,采用MQTT协议将车位数据上传至华为云物联网平台
(5)基于Qt5.12开发的上位机程序(C++实现)远程查看车位使用状态及统计信息
(6)系统由STM32F103C8T6主控协调各模块,DC 5V电源稳压模块提供稳定供电

项目硬件模块组成

(1)STM32F103C8T6主控芯片
(2)HC-SR04超声波测距模块(每个车位一个)
(3)红绿双色LED指示灯(每个车位一个)
(4)0.96寸SPI OLED显示模块
(5)ESP8266 WiFi联网模块
(6)DC 5V电源稳压模块

设计意义

设计意义:
随着城市化进程加快和汽车保有量激增,停车资源日益紧张,传统停车场管理效率低下,车主寻找车位耗时耗力,加剧了交通拥堵与能源浪费。基于STM32的智能车位监测系统通过实时检测与数据可视化,为解决上述问题提供了技术支撑。

本系统在每个车位部署超声波模块,精准识别车辆停放状态,并通过本地OLED显示屏与红绿LED指示灯直观展示车位占用情况,帮助车主快速定位空余车位,大幅缩短寻泊时间,提升停车场周转效率。同时,系统通过ESP8266模块将实时数据上传至华为云物联网平台,实现车位状态的远程监控与集中管理,为停车场运营者提供动态调度依据,优化资源配置。

支持Qt开发的上位机可视化界面,使管理人员可远程查看全场车位使用热力图与统计数据,简化管理流程,降低人工巡检成本。系统采用模块化设计,硬件成本低、部署灵活,可扩展应用于各类室内外停车场,推动传统停车场向智能化、数字化转型升级,对缓解城市停车压力、构建智慧交通体系具有重要实践价值。

设计思路

设计思路

系统以STM32F103C8T6为核心控制器,通过多路GPIO接口连接车位检测模块。每个车位部署一个HC-SR04超声波模块,由STM32的定时器产生触发信号并捕获回波时间,根据公式距离=声速×时间/2实时计算车顶距离。设定距离阈值(如30cm),当测量值持续低于阈值时判定为车位占用,否则为空闲状态。

检测结果通过双色LED现场指示:每个车位对应一组红绿LED,红色亮表示占用,绿色亮表示空闲。同时,STM32驱动0.96寸SPI接口OLED屏幕,动态显示所有车位编号及状态(如“01:占用”),采用分页刷新机制降低功耗。

数据上传通过串口UART连接ESP8266模块实现。STM32将车位状态封装为JSON格式(如{"park1":1}),基于AT指令集控制ESP8266连接Wi-Fi,通过MQTT协议按固定间隔(如5秒)上报至华为云物联网平台。设计心跳包机制维持长连接,并加入数据校验确保传输可靠性。

上位机采用Qt5.12开发,调用华为云API订阅MQTT主题。界面以网格化图形展示车位状态(红色方块表占用,绿色表空闲),支持自动刷新(轮询间隔可调)。使用C++多线程架构分离UI渲染与数据获取逻辑,通过QChart组件实现历史占用率统计曲线。

供电由5V DC电源经AMS1117稳压芯片转换为3.3V,为STM32及外设供电。硬件布局采用星型接地减少干扰,超声波模块电源独立滤波以提高测距精度。所有功能模块通过状态机调度,确保实时响应与低功耗运行。

框架图

基于STM32的智能车位监测系统框架图

+--------------------------------------------------------------------------------------------------+
|                                       智能车位监测系统框架                                         |
+--------------------------------------------------------------------------------------------------+
|                                                                                                  |
|   +---------------------+     +---------------------+     +---------------------+                |
|   |   车位检测模块      |     |   车位检测模块      |     |   车位检测模块      |                |
|   |  [HC-SR04超声波]    |     |  [HC-SR04超声波]    | ... |  [HC-SR04超声波]    |                |
|   |  (每个车位独立)     |     |  (每个车位独立)     |     |  (每个车位独立)     |                |
|   +----------+----------+     +----------+----------+     +----------+----------+                |
|              | GPIO                      | GPIO                      | GPIO                     |
|              |                          |                          |                          |
|   +----------v--------------------------v--------------------------v----------+                |
|   |                              STM32F103C8T6 主控制器                         |                |
|   |  +-----------------------------------------------------------------------+  |                |
|   |  | 功能实现:                                                            |  |                |
|   |  |  1. 超声波测距数据处理(判断车位状态)                                |  |                |
|   |  |  2. LED状态控制(红/绿)                                            |  |                |
|   |  |  3. OLED显示驱动(SPI接口)                                         |  |                |
|   |  |  4. ESP8266通信协议(UART串口)                                     |  |                |
|   |  +-----------------------------------------------------------------------+  |                |
|   +----+----------------+----------------+----------------+---------------------+                |
|        |                |                |                |                                    |
|        | GPIO           | SPI            | UART           | GPIO                                |
|        | (控制LED)      | (显示数据)     | (数据传输)     | (更多车位扩展)                     |
|        |                |                |                |                                    |
|   +----v----+     +-----v------+   +-----v------+   +-----v------+                              |
|   | 双色LED |     | 0.96OLED |   | ESP8266    |   | 其他车位   |                              |
|   | (/绿) |     | (SPI接口)  |   | WiFi模块   |   | 检测模块   |                              |
|   +---------+     +------------+   +-----+------+   +------------+                              |
|                                          | MQTT协议                                              |
|                                   +------v------+                                               |
|                                   | 华为云物联网平台 |                                           |
|                                   | (数据存储/转发) |                                           |
|                                   +------+------+                                               |
|                                          | API/WebSocket                                       |
|                                   +------v------+                                               |
|                                   |  Qt上位机程序 |                                             |
|                                   | (C++开发)    |                                             |
|                                   | 功能:       |                                             |
|                                   | 1. 实时车位图|                                             |
|                                   | 2. 数据分析  |                                             |
|                                   +--------------+                                               |
|                                                                                                  |
|   +----------------+                                                                             |
|   |  5V电源稳压模块 |                                                                           |
|   | (系统供电)     |                                                                           |
|   +----------------+                                                                             |
|                                                                                                  |
+--------------------------------------------------------------------------------------------------+

框架说明:

  1. 检测层

    • 多个HC-SR04超声波模块独立检测每个车位状态(有车/无车)
  2. 控制层

    • STM32F103C8T6核心功能:
      • 处理超声波数据,判断车位状态
      • 控制双色LED(红灯=占用,绿灯=空闲)
      • 驱动OLED显示车位状态摘要
      • 通过UART与ESP8266通信
  3. 通信层

    • ESP8266通过MQTT协议将数据上传至华为云物联网平台
  4. 云端与上位机

    • 华为云平台存储/转发数据
    • Qt上位机通过API获取数据,实现可视化车位管理界面
  5. 供电层

    • 5V稳压模块为整个系统供电(包括STM32、传感器、OLED和ESP8266)

系统总体设计

系统以STM32F103C8T6微控制器为核心,协调各硬件模块实现车位状态监测功能。每个车位部署的HC-SR04超声波模块通过发射接收声波测量车顶距离,STM32实时处理距离数据并设定阈值判定车位状态:低于阈值判定为占用状态,反之为空闲状态。

检测结果通过双通道本地反馈机制呈现。红绿双色LED直接指示车位状态:绿灯表示空闲,红灯表示占用。同时,0.96寸SPI接口OLED屏幕综合显示所有车位状态信息,包括车位编号、实时状态(占用/空闲)及系统运行参数,提供现场可视化监控。

网络传输层采用ESP8266 WiFi模块,通过UART串口与STM32通信。STM32将车位状态数据封装为JSON格式,驱动ESP8266通过MQTT协议连接华为云物联网平台,实现车位状态数据的定时上传与云端存储,确保数据远程可访问性。

上位机监控端采用Qt5.12开发的C++应用程序,通过华为云API接口获取实时车位数据。该程序以图形化界面展示停车场平面图,使用颜色编码(绿色/红色)动态标注各车位使用状态,支持管理员远程查看全局车位占用情况。

系统由DC 5V稳压模块统一供电,为STM32主控、超声波传感器、LED指示灯、OLED显示屏及ESP8266模块提供稳定工作电压,确保各硬件单元协同运行。

系统功能总结

功能模块 实现方式
车位状态检测 通过HC-SR04超声波模块实时测距,根据距离阈值判断车位占用状态(有车/无车)
本地状态指示 双色LED显示:红灯表示车位占用,绿灯表示空闲
本地信息显示 0.96寸SPI OLED实时展示车位状态、系统参数及网络连接状态
云端数据上传 ESP8266通过MQTT协议将车位状态上传至华为云物联网平台
远程监控管理 基于Qt5.12的上位机程序可视化展示车位使用情况(空/占)、支持数据统计分析
系统供电管理 DC 5V电源稳压模块为STM32、传感器及外设提供稳定电源

设计的各个功能模块描述

主控芯片模块基于STM32F103C8T6微控制器构建系统核心,负责协调各外设模块的数据处理与逻辑控制。通过定时器触发和中断机制管理超声波测距流程,同时处理网络通信协议转换及显示驱动任务。

车位检测模块采用HC-SR04超声波传感器阵列部署于每个车位,通过发射40kHz超声波并计算回波时间差实时获取车距数据。主控芯片根据预设阈值(典型值30cm)动态判定车位占用状态,实现毫秒级响应检测。

状态指示模块集成红绿双色LED灯组,直接由主控GPIO口驱动。检测到车辆占用时红色LED常亮,车位空闲时绿色LED点亮,通过物理光信号提供现场直观状态反馈。

显示模块配置0.96寸SPI接口OLED屏幕,采用SSD1306驱动芯片。实时刷新显示车位编号、占用状态百分比、网络连接标识等关键信息,支持多级菜单界面切换展示系统运行参数。

网络通信模块依托ESP8266 Wi-Fi模组,通过AT指令集与主控建立UART串行通信。基于MQTT协议封装车位状态JSON数据包(含时间戳、设备ID、车位状态码),定时上传至华为云物联网平台,同时订阅平台下发的控制指令。

上位机交互模块使用Qt5.12框架开发跨平台监控程序,通过华为云API网关获取实时车位数据。采用QCustomPlot库实现车位热力图可视化,支持历史记录查询、占用率统计图表生成及异常状态弹窗告警功能。

供电管理模块采用LM2596降压稳压方案,将外部7-24V宽电压输入转换为稳定5V/2A系统电源,为微控制器、传感器阵列及显示单元提供纹波系数低于3%的纯净电力供应,内置过流保护与ESD防护电路。

上位机代码设计

以下是一个基于Qt5.12的智能车位监测系统上位机完整代码实现:

// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMqttClient>
#include <QGraphicsScene>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void connectToBroker();
    void disconnectFromBroker();
    void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic);
    void updateParkingStatus(int spaceId, bool occupied);

private:
    Ui::MainWindow *ui;
    QMqttClient *m_client;
    QGraphicsScene *m_scene;
    QVector<QGraphicsRectItem*> parkingSpaces;
    QVector<QGraphicsTextItem*> idLabels;
    QVector<QGraphicsEllipseItem*> statusLights;

    void setupParkingLayout();
    void updateStatusLight(int index, bool occupied);
    void createLegend();
};
#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("智能车位监测系统");
    
    // 初始化MQTT客户端
    m_client = new QMqttClient(this);
    m_client->setHostname("你的华为云MQTT地址"); // 替换实际地址
    m_client->setPort(1883); // 替换实际端口
    m_client->setUsername("用户名"); // 替换实际用户名
    m_client->setPassword("密码"); // 替换实际密码
    
    // 连接信号槽
    connect(ui->connectButton, &QPushButton::clicked, this, &MainWindow::connectToBroker);
    connect(ui->disconnectButton, &QPushButton::clicked, this, &MainWindow::disconnectFromBroker);
    connect(m_client, &QMqttClient::messageReceived, this, &MainWindow::onMessageReceived);
    
    // 初始化图形场景
    m_scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(m_scene);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);
    
    // 创建车位布局
    setupParkingLayout();
    createLegend();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setupParkingLayout()
{
    parkingSpaces.clear();
    idLabels.clear();
    statusLights.clear();
    
    int spaceWidth = 80;
    int spaceHeight = 50;
    int spacing = 20;
    int startX = 50;
    int startY = 50;
    
    // 创建8个车位 (2行 x 4列)
    for (int row = 0; row < 2; ++row) {
        for (int col = 0; col < 4; ++col) {
            int spaceId = row * 4 + col + 1;
            int x = startX + col * (spaceWidth + spacing);
            int y = startY + row * (spaceHeight + spacing);
            
            // 创建车位矩形
            QGraphicsRectItem *space = new QGraphicsRectItem(x, y, spaceWidth, spaceHeight);
            space->setBrush(Qt::lightGray);
            space->setPen(QPen(Qt::black, 2));
            m_scene->addItem(space);
            parkingSpaces.append(space);
            
            // 添加车位编号
            QGraphicsTextItem *idLabel = new QGraphicsTextItem(QString::number(spaceId));
            idLabel->setPos(x + spaceWidth/2 - 10, y + 5);
            idLabel->setDefaultTextColor(Qt::black);
            m_scene->addItem(idLabel);
            idLabels.append(idLabel);
            
            // 添加状态指示灯
            QGraphicsEllipseItem *light = new QGraphicsEllipseItem(x + spaceWidth - 20, y + spaceHeight - 20, 15, 15);
            light->setBrush(Qt::gray); // 初始灰色
            light->setPen(QPen(Qt::black, 1));
            m_scene->addItem(light);
            statusLights.append(light);
        }
    }
}

void MainWindow::createLegend()
{
    int yPos = 200;
    
    // 空闲车位图例
    QGraphicsEllipseItem *freeLight = new QGraphicsEllipseItem(50, yPos, 15, 15);
    freeLight->setBrush(Qt::green);
    m_scene->addItem(freeLight);
    
    QGraphicsTextItem *freeText = new QGraphicsTextItem("空闲车位");
    freeText->setPos(70, yPos);
    m_scene->addItem(freeText);
    
    // 占用车位图例
    QGraphicsEllipseItem *occLight = new QGraphicsEllipseItem(150, yPos, 15, 15);
    occLight->setBrush(Qt::red);
    m_scene->addItem(occLight);
    
    QGraphicsTextItem *occText = new QGraphicsTextItem("占用车位");
    occText->setPos(170, yPos);
    m_scene->addItem(occText);
}

void MainWindow::updateStatusLight(int index, bool occupied)
{
    if (index >= 0 && index < statusLights.size()) {
        statusLights[index]->setBrush(occupied ? Qt::red : Qt::green);
    }
}

void MainWindow::connectToBroker()
{
    if (m_client->state() == QMqttClient::Disconnected) {
        m_client->connectToHost();
        ui->statusLabel->setText("正在连接到服务器...");
        connect(m_client, &QMqttClient::connected, [this]() {
            ui->statusLabel->setText("已连接到服务器");
            m_client->subscribe("parking/status"); // 订阅主题
        });
    }
}

void MainWindow::disconnectFromBroker()
{
    if (m_client->state() == QMqttClient::Connected) {
        m_client->disconnectFromHost();
        ui->statusLabel->setText("已断开连接");
    }
}

void MainWindow::onMessageReceived(const QByteArray &message, const QMqttTopicName &topic)
{
    QJsonDocument doc = QJsonDocument::fromJson(message);
    if (!doc.isNull() && doc.isObject()) {
        QJsonObject obj = doc.object();
        int spaceId = obj["space_id"].toInt();
        bool occupied = obj["status"].toString() == "occupied";
        
        updateParkingStatus(spaceId, occupied);
    }
}

void MainWindow::updateParkingStatus(int spaceId, bool occupied)
{
    int index = spaceId - 1;
    if (index >= 0 && index < parkingSpaces.size()) {
        updateStatusLight(index, occupied);
        
        // 更新状态栏信息
        QString status = occupied ? "占用" : "空闲";
        QString message = QString("车位 %1 状态: %2").arg(spaceId).arg(status);
        ui->statusBar->showMessage(message, 3000);
    }
}
// main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.resize(800, 600);
    w.show();
    return a.exec();
}
# parking_monitor.pro
QT       += core gui network mqtt
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = parking_monitor
TEMPLATE = app

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

使用说明:

  1. 界面功能

    • 顶部控制栏:连接/断开华为云MQTT服务器
    • 中央显示区:8个车位状态可视化(2×4布局)
    • 状态指示灯:绿色=空闲,红色=占用
    • 底部状态栏:实时显示车位状态变化
  2. 配置要求

    • 替换代码中的MQTT连接参数:

      m_client->setHostname("你的华为云MQTT地址");
      m_client->setPort(1883); // 实际端口
      m_client->setUsername("用户名");
      m_client->setPassword("密码");
      
  3. 数据格式要求
    从华为云接收的JSON数据格式:

    {
      "space_id": 1,
      "status": "occupied"  // 或 "vacant"
    }
    
  4. 编译运行

    • 使用Qt Creator打开项目
    • 配置Qt5.12编译环境
    • 构建并运行程序
  5. 操作流程

    1. 点击"连接"按钮接入华为云
    2. 实时接收车位状态更新
    3. 图形化显示车位占用情况
    4. 底部状态栏显示最新状态变化

模块代码设计

基于STM32的智能车位监测系统设备端代码设计

#include "stm32f10x.h"

// 宏定义
#define LED_RED_PIN   GPIO_Pin_0   // PA0 红灯
#define LED_GREEN_PIN GPIO_Pin_1   // PA1 绿灯
#define TRIG_PIN      GPIO_Pin_2   // PA2 超声波触发
#define ECHO_PIN      GPIO_Pin_3   // PA3 超声波回波
#define OLED_CS_PIN   GPIO_Pin_4   // PA4 SPI片选
#define OLED_DC_PIN   GPIO_Pin_5   // PA5 数据/命令
#define OLED_RES_PIN  GPIO_Pin_6   // PA6 复位
#define ESP8266_TX_PIN GPIO_Pin_2  // PA9 USART1_TX
#define ESP8266_RX_PIN GPIO_Pin_3  // PA10 USART1_RX

// 全局变量
volatile uint32_t pulse_start = 0;
volatile uint32_t pulse_end = 0;
volatile uint32_t pulse_duration = 0;
volatile uint8_t distance_cm = 0;
volatile uint8_t car_detected = 0;

// OLED显示缓存
uint8_t oled_buffer[128 * 64 / 8];

// 华为云配置
const char* mqtt_server = "your_huaweicloud_address";
const char* client_id = "your_device_id";
const char* username = "your_username";
const char* password = "your_password";
const char* topic = "parking/status";

// 函数声明
void SystemClock_Config(void);
void GPIO_Init(void);
void TIM2_Init(void);
void USART1_Init(void);
void SPI1_Init(void);
void OLED_Init(void);
void OLED_DisplayText(char* text);
void HC_SR04_Trigger(void);
void ESP8266_SendCmd(char* cmd);
void MQTT_Publish(char* payload);
void Delay_ms(uint32_t ms);

int main(void) {
    // 系统初始化
    SystemClock_Config();
    GPIO_Init();
    TIM2_Init();
    USART1_Init();
    SPI1_Init();
    OLED_Init();
    
    // ESP8266初始化
    ESP8266_SendCmd("AT+RST\r\n");
    Delay_ms(1000);
    ESP8266_SendCmd("AT+CWMODE=1\r\n");
    Delay_ms(500);
    ESP8266_SendCmd("AT+CWJAP=\"your_wifi_ssid\",\"your_wifi_pass\"\r\n");
    Delay_ms(3000);
    ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"your_huaweicloud_address\",1883\r\n");
    Delay_ms(2000);
    ESP8266_SendCmd("AT+CIPMODE=1\r\n");
    ESP8266_SendCmd("AT+CIPSEND\r\n");
    Delay_ms(500);
    
    while(1) {
        // 触发超声波测距
        HC_SR04_Trigger();
        Delay_ms(100);
        
        // 计算距离 (声速340m/s)
        distance_cm = (pulse_duration * 0.034) / 2;
        
        // 判断车位状态 (阈值40cm)
        if(distance_cm < 40 && distance_cm > 2) {
            car_detected = 1;
            GPIO_SetBits(GPIOA, LED_RED_PIN);    // 红灯亮
            GPIO_ResetBits(GPIOA, LED_GREEN_PIN);
        } else {
            car_detected = 0;
            GPIO_SetBits(GPIOA, LED_GREEN_PIN);  // 绿灯亮
            GPIO_ResetBits(GPIOA, LED_RED_PIN);
        }
        
        // OLED显示状态
        if(car_detected) {
            OLED_DisplayText("Status: OCCUPIED");
        } else {
            OLED_DisplayText("Status: EMPTY");
        }
        
        // 上传到华为云
        if(car_detected) {
            MQTT_Publish("occupied");
        } else {
            MQTT_Publish("empty");
        }
        
        Delay_ms(2000);  // 每2秒检测一次
    }
}

// 超声波触发函数
void HC_SR04_Trigger(void) {
    GPIO_SetBits(GPIOA, TRIG_PIN);
    Delay_ms(10);
    GPIO_ResetBits(GPIOA, TRIG_PIN);
}

// MQTT发布函数
void MQTT_Publish(char* payload) {
    char mqtt_cmd[128];
    sprintf(mqtt_cmd, "AT+MQTTPUB=0,\"%s\",\"%s\",1,0\r\n", topic, payload);
    ESP8266_SendCmd(mqtt_cmd);
}

// ESP8266命令发送
void ESP8266_SendCmd(char* cmd) {
    while(*cmd) {
        USART_SendData(USART1, *cmd++);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    }
}

// 定时器2中断处理 (捕获回波)
void TIM2_IRQHandler(void) {
    if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
        if(GPIO_ReadInputDataBit(GPIOA, ECHO_PIN)) {
            pulse_start = TIM_GetCapture1(TIM2);
        } else {
            pulse_end = TIM_GetCapture1(TIM2);
            pulse_duration = pulse_end - pulse_start;
        }
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
    }
}

// 系统时钟配置 (72MHz)
void SystemClock_Config(void) {
    RCC->CFGR |= 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) != RCC_CFGR_SWS_PLL);
}

// GPIO初始化
void GPIO_Init(void) {
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    
    // LED配置 (推挽输出)
    GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_MODE1);
    GPIOA->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_MODE1_0);
    
    // 超声波TRIG (推挽输出)
    GPIOA->CRL &= ~GPIO_CRL_MODE2;
    GPIOA->CRL |= GPIO_CRL_MODE2_0;
    
    // 超声波ECHO (浮空输入)
    GPIOA->CRL &= ~(GPIO_CRL_CNF3 | GPIO_CRL_MODE3);
    GPIOA->CRL |= GPIO_CRL_CNF3_0;
    
    // OLED控制引脚 (推挽输出)
    GPIOA->CRL &= ~(GPIO_CRL_MODE4 | GPIO_CRL_MODE5 | GPIO_CRL_MODE6);
    GPIOA->CRL |= (GPIO_CRL_MODE4_0 | GPIO_CRL_MODE5_0 | GPIO_CRL_MODE6_0);
}

// 定时器2初始化 (输入捕获)
void TIM2_Init(void) {
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    
    TIM2->PSC = 72 - 1;       // 1MHz计数频率
    TIM2->ARR = 0xFFFF;       // 最大计数值
    TIM2->CCMR1 |= TIM_CCMR1_CC1S_0; // CC1通道输入
    TIM2->CCER |= TIM_CCER_CC1E;     // 捕获使能
    TIM2->DIER |= TIM_DIER_CC1IE;    // 捕获中断使能
    TIM2->CR1 |= TIM_CR1_CEN;        // 启动定时器
    
    NVIC_EnableIRQ(TIM2_IRQn);
}

// USART1初始化 (ESP8266通信)
void USART1_Init(void) {
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    
    // PA9(TX)复用推挽输出, PA10(RX)浮空输入
    GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9 | GPIO_CRH_CNF10);
    GPIOA->CRH |= (GPIO_CRH_MODE9_0 | GPIO_CRH_CNF9_1);
    
    USART1->BRR = 72000000 / 115200; // 波特率115200
    USART1->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}

// SPI1初始化 (OLED控制)
void SPI1_Init(void) {
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
    
    // PA7(MOSI), PA5(SCK) 复用推挽输出
    GPIOA->CRL &= ~(GPIO_CRL_CNF5 | GPIO_CRL_CNF7);
    GPIOA->CRL |= (GPIO_CRL_MODE5 | GPIO_CRL_MODE7);
    
    SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_0 | SPI_CR1_SPE;
}

// OLED初始化
void OLED_Init(void) {
    // OLED硬件复位
    GPIO_ResetBits(GPIOA, OLED_RES_PIN);
    Delay_ms(100);
    GPIO_SetBits(GPIOA, OLED_RES_PIN);
    
    // 初始化命令序列
    uint8_t init_cmds[] = {
        0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40,
        0x8D, 0x14, 0x20, 0x00, 0xA1, 0xC8, 0xDA, 0x12,
        0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6, 0xAF
    };
    
    for(uint8_t i = 0; i < sizeof(init_cmds); i++) {
        OLED_WriteCmd(init_cmds[i]);
    }
    OLED_Clear();
}

// OLED清屏
void OLED_Clear(void) {
    for(uint16_t i = 0; i < sizeof(oled_buffer); i++) {
        oled_buffer[i] = 0x00;
    }
    OLED_Refresh();
}

// OLED显示文本
void OLED_DisplayText(char* text) {
    OLED_Clear();
    // 文本显示实现(简化)
    // 实际需要实现字符点阵渲染
    OLED_Refresh();
}

// OLED刷新显示
void OLED_Refresh(void) {
    for(uint8_t page = 0; page < 8; page++) {
        OLED_WriteCmd(0xB0 + page);
        OLED_WriteCmd(0x00);
        OLED_WriteCmd(0x10);
        
        for(uint8_t col = 0; col < 128; col++) {
            OLED_WriteData(oled_buffer[page * 128 + col]);
        }
    }
}

// OLED写命令
void OLED_WriteCmd(uint8_t cmd) {
    GPIO_ResetBits(GPIOA, OLED_DC_PIN); // 命令模式
    GPIO_ResetBits(GPIOA, OLED_CS_PIN);
    
    while(!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = cmd;
    while(SPI1->SR & SPI_SR_BSY);
    
    GPIO_SetBits(GPIOA, OLED_CS_PIN);
}

// OLED写数据
void OLED_WriteData(uint8_t data) {
    GPIO_SetBits(GPIOA, OLED_DC_PIN); // 数据模式
    GPIO_ResetBits(GPIOA, OLED_CS_PIN);
    
    while(!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = data;
    while(SPI1->SR & SPI_SR_BSY);
    
    GPIO_SetBits(GPIOA, OLED_CS_PIN);
}

// 毫秒延时
void Delay_ms(uint32_t ms) {
    for(uint32_t i = 0; i < ms * 8000; i++) {
        __NOP();
    }
}

关键代码说明:

  1. 超声波测距模块

    • 使用TIM2输入捕获模式测量回波脉冲宽度
    • 通过公式计算距离:距离(cm) = (脉冲时间×0.034)/2
    • 设置40cm阈值判断车位状态
  2. 双色LED控制

    • PA0控制红灯(有车时亮)
    • PA1控制绿灯(空闲时亮)
    • 互斥点亮逻辑
  3. OLED显示

    • SPI接口驱动0.96寸OLED
    • 显示车位状态(OCCUPIED/EMPTY)
    • 支持清屏和刷新操作
  4. ESP8266联网

    • USART1实现AT指令通信
    • 支持WiFi连接和MQTT协议
    • 实现华为云数据上传
  5. 系统工作流程

    • 每2秒检测一次车位状态
    • 更新本地LED和OLED显示
    • 通过MQTT上传状态到华为云
    • 支持Qt上位机远程监控

项目核心代码

以下是基于STM32F103C8T6的智能车位监测系统main.c完整代码(寄存器开发方式):

#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "hc_sr04.h"
#include "esp8266_mqtt.h"

// 硬件定义
#define LED_RED_GPIO     GPIOC
#define LED_RED_PIN      GPIO_Pin_13
#define LED_GREEN_GPIO   GPIOC
#define LED_GREEN_PIN    GPIO_Pin_14
#define CAR_DISTANCE_THRESHOLD  50  // 车位距离阈值(厘米)

// 状态枚举
typedef enum {
    EMPTY = 0,
    OCCUPIED = 1
} CarState;

volatile uint32_t sysTickCount = 0;  // 系统滴答计数器

// 系统时钟初始化(72MHz)
void SystemClock_Config(void) {
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN;
    
    // 使用外部8MHz晶振
    RCC->CR |= RCC_CR_HSEON;
    while(!(RCC->CR & RCC_CR_HSERDY));
    
    // PLL配置: HSE * 9 = 72MHz
    RCC->CFGR |= RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC;
    RCC->CR |= RCC_CR_PLLON;
    while(!(RCC->CR & RCC_CR_PLLRDY));
    
    // 设置系统时钟
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
    
    // 配置SysTick定时器(1ms中断)
    SysTick_Config(SystemCoreClock / 1000);
}

// LED初始化
void LED_Init(void) {
    // PC13(红灯), PC14(绿灯) 推挽输出
    GPIOC->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_CNF14);
    GPIOC->CRH |= GPIO_CRH_MODE13 | GPIO_CRH_MODE14;
    GPIOC->BSRR = LED_RED_PIN | LED_GREEN_PIN;  // 初始关闭
}

// 更新LED状态
void UpdateLED(CarState state) {
    if(state == EMPTY) {
        LED_GREEN_GPIO->BRR = LED_GREEN_PIN;  // 绿灯亮
        LED_RED_GPIO->BSRR = LED_RED_PIN;     // 红灯灭
    } else {
        LED_RED_GPIO->BRR = LED_RED_PIN;      // 红灯亮
        LED_GREEN_GPIO->BSRR = LED_GREEN_PIN;  // 绿灯灭
    }
}

// 更新OLED显示
void UpdateOLED(CarState state, float distance) {
    OLED_Clear();
    OLED_ShowString(0, 0, "Parking Status:");
    
    if(state == EMPTY) {
        OLED_ShowString(0, 2, "State: EMPTY");
        OLED_ShowString(0, 4, "Distance: ---");
    } else {
        OLED_ShowString(0, 2, "State: OCCUPIED");
        OLED_ShowString(0, 4, "Distance:");
        OLED_ShowFloat(70, 4, distance);
        OLED_ShowString(110, 4, "cm");
    }
}

// SysTick中断处理
void SysTick_Handler(void) {
    sysTickCount++;
}

int main(void) {
    // 初始化系统
    SystemClock_Config();
    Delay_Init();
    LED_Init();
    OLED_Init();
    HC_SR04_Init();
    ESP8266_Init();  // 初始化WiFi模块
    
    // 连接华为云
    ESP8266_ConnectCloud();
    
    CarState currentState = EMPTY;
    CarState lastState = EMPTY;
    float distance = 0.0f;
    
    while(1) {
        // 每500ms检测一次
        if(sysTickCount >= 500) {
            sysTickCount = 0;
            
            // 获取超声波距离
            distance = HC_SR04_GetDistance();
            
            // 判断车位状态
            currentState = (distance < CAR_DISTANCE_THRESHOLD) ? OCCUPIED : EMPTY;
            
            // 更新LED指示
            UpdateLED(currentState);
            
            // 更新OLED显示
            UpdateOLED(currentState, distance);
            
            // 状态变化时上传数据
            if(currentState != lastState) {
                ESP8266_SendData(currentState);  // MQTT发送状态
                lastState = currentState;
            }
        }
    }
}

代码说明:

  1. 系统初始化

    • 配置72MHz系统时钟(HSE外部晶振)
    • 初始化SysTick定时器(1ms中断)
    • 初始化外设:LED、OLED、超声波、ESP8266
  2. 车位状态检测

    • 每500ms测量一次超声波距离
    • 距离阈值50cm判断车位状态(小于阈值有车)
  3. 状态指示

    • LED:绿灯(空位)/红灯(占用)
    • OLED显示实时状态和距离数据
  4. 数据上传

    • 通过ESP8266连接华为云物联网平台
    • 使用MQTT协议在状态变化时上传数据
  5. 关键驱动依赖

    • delay.c:延时函数库
    • oled.c:SPI OLED驱动
    • hc_sr04.c:超声波测距驱动
    • esp8266_mqtt.c:ESP8266 MQTT通信驱动

总结

本设计成功实现了基于STM32F103C8T6的智能车位监测系统,通过模块化硬件与分层软件架构的协同工作,全面满足了车位状态监测、本地显示、云端交互及远程管理的功能需求。系统以HC-SR04超声波模块为核心检测单元,实时采集车位距离数据,经STM32主控芯片进行阈值分析后判定车辆状态,并通过双色LED(红灯示占用,绿灯示空闲)和SPI接口OLED屏实现直观的本地状态反馈。

通过ESP8266 WiFi模块建立MQTT协议连接,系统将车位状态数据稳定上传至华为云物联网平台,实现了数据的云端存储与远程可访问性。配合自主开发的Qt5.12上位机程序,管理员可在PC端通过可视化界面实时监控全局车位使用情况,显著提升了停车场管理效率。整个系统由5V稳压电源供电,确保了各模块的稳定运行。

综上所述,该系统深度融合了嵌入式感知技术、物联网通信及桌面应用开发,构建了完整的"端-云-端"解决方案。其低成本的硬件实现、可靠的数据传输机制以及人性化的交互设计,为智慧停车管理提供了可推广的实践范例,具有较高的工程应用价值与市场潜力。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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