基于STM32的冷链物流智能监控终端设计

举报
DS小龙哥 发表于 2025/06/22 18:36:01 2025/06/22
【摘要】 项目开发背景冷链物流在食品、药品、生物制品等对温度敏感产品的储运过程中至关重要。温湿度的失控或运输过程中的剧烈震动、跌落,极易导致产品腐败变质、失效,甚至引发安全事故,造成巨大的经济损失和健康风险。传统的监控方式往往依赖人工记录或简单的数据记录仪,存在信息滞后、无法实时报警、全程追溯困难等问题,难以满足现代物流对高可靠性、高透明度及实时监管的需求。随着物联网技术的快速发展,利用传感器、无线...

项目开发背景

冷链物流在食品、药品、生物制品等对温度敏感产品的储运过程中至关重要。温湿度的失控或运输过程中的剧烈震动、跌落,极易导致产品腐败变质、失效,甚至引发安全事故,造成巨大的经济损失和健康风险。传统的监控方式往往依赖人工记录或简单的数据记录仪,存在信息滞后、无法实时报警、全程追溯困难等问题,难以满足现代物流对高可靠性、高透明度及实时监管的需求。

随着物联网技术的快速发展,利用传感器、无线通信和云平台实现对物流环境的智能、实时监控已成为行业迫切需求。开发一款集环境参数实时采集、异常事件精准检测、位置全程追踪、数据远程上传及本地报警于一体的智能终端,对于保障冷链物流品质、提升物流管理效率、降低货损率、明确运输责任具有重要意义。

本项目旨在设计并实现一款基于高性能、低功耗STM32微控制器的冷链物流智能监控终端。该终端将集成高精度温湿度传感器、震动检测模块、GPS定位模块以及4G通信模块,能够持续、准确地感知货物所处箱体的环境状态(温湿度)、记录运输过程中的异常震动或跌落事件、实时获取并上报地理位置信息。所有关键数据将通过4G网络高效传输至华为云物联网平台,实现远程集中监控和大数据分析。同时,设备具备本地OLED状态显示功能,并在检测到温湿度超标或剧烈震动等异常情况时,立即触发蜂鸣器进行现场声光报警,为及时干预提供保障。通过此终端的部署,可显著提升冷链物流过程的可视化、智能化水平和风险管控能力。

设计实现的功能

(1)实时监测货物箱体内温度与湿度:通过SHT30传感器(I2C接口)采集温湿度数据,STM32F103C8T6主控芯片实时处理数据。
(2)监测震动/跌落事件并记录:利用SW-420震动传感器检测异常震动或跌落,STM32记录事件时间戳及强度,存储至本地或上传云端。
(3)GPS定位跟踪物流位置:通过ATGM336H模块(UART接口)获取经纬度数据,STM32解析并处理位置信息。
(4)数据通过4G模块上传至华为云物联网平台:Air724UG 4G模块(AT指令+MQTT协议)将温湿度、位置、震动事件等数据上传至华为云。
(5)异常条件自动触发蜂鸣器报警:当温湿度超限或检测到震动事件时,STM32输出高电平驱动有源蜂鸣器报警。
(6)数据显示:0.96寸OLED实时显示温湿度、GPS定位信息及报警状态。
(7)供电管理:DC 5V模块+锂电池供电,TP4056充电保护模块实现电池充放电管理及过充/过放保护。

项目硬件模块组成

(1)STM32F103C8T6主控芯片
(2)SHT30温湿度传感器(I2C接口)
(3)SW-420震动传感器
(4)ATGM336H GPS模块(UART接口)
(5)Air724UG 4G通信模块(支持AT指令+MQTT)
(6)0.96寸OLED显示模块
(7)高电平触发有源蜂鸣器
(8)DC 5V供电模块 + 锂电池 + TP4056充电保护模块

设计意义

该冷链物流智能监控终端的设计意义在于切实解决物流过程中的核心痛点。通过高精度的SHT30传感器实时采集货物箱体内的温湿度数据,确保对易腐品、药品等温度敏感货物的全程环境监控,有效避免因温湿度失控导致的货物变质或失效,保障产品质量与安全价值。

集成震动检测模块与GPS定位功能,可精准记录运输途中的异常震动或跌落事件,并同步追踪地理位置信息。这不仅为物流过程提供关键责任追溯依据,在发生货损时明确责任归属,也能帮助企业优化运输路径和包装方案,提升整体物流管理的精细化水平。

采用4G模块直连华为云物联网平台,实现了监控数据的远程实时透传与云端存储。配合本地蜂鸣器报警机制,在温湿度超限或发生剧烈震动时立即触发声光警示,形成"本地即时响应+云端远程监控"的双重保障体系,显著提升对运输异常的响应速度和处理效率。

该终端采用锂电池结合TP4056充放电保护方案,保障设备在运输途中的持续稳定运行。整套系统基于成熟的STM32平台构建,各模块选型兼顾可靠性与成本效益,为冷链物流过程提供了可落地、易部署的智能化监控解决方案。

设计思路

设计思路围绕STM32F103C8T6主控芯片构建冷链物流智能监控终端,以实际功能需求为导向,分模块实现监测、定位、通信与报警功能。

核心控制与数据处理
STM32F103C8T6作为主控单元,通过其外设接口协调各模块工作。初始化阶段配置系统时钟、GPIO、I2C、UART等基础外设。主循环中采用分时调度策略:周期性读取传感器数据,实时检测外部事件(如震动),并处理通信任务。数据采集后暂存于内部缓冲区,经格式整合(如添加时间戳、GPS位置信息)后准备上传。

环境参数监测实现
温湿度监测使用SHT30传感器,通过I2C接口连接STM32。主控按设定间隔(如每5秒)发起读取请求,获取数字量温湿度数据。通过校验确保数据有效性,超出预设阈值(如温度>8℃或<2℃)时标记为异常状态。震动检测采用SW-420模块,其数字输出口接入STM32外部中断引脚。当检测到持续震动或高冲击(跌落)时,触发中断服务函数记录事件类型、强度与发生时间,存入非易失存储器(如Flash)备用。

定位与数据传输链路
GPS定位通过ATGM336H模块实现,采用UART通信。主控解析NMEA-0183协议中的GPRMC语句,提取经纬度、时间及速度信息。4G通信选用Air724UG模块,通过另一路UART发送AT指令建立网络连接,并基于MQTT协议对接华为云物联网平台。数据上传策略采用双模式:常规状态下定时上传环境数据与位置;当检测到异常(温湿度超标、震动事件或手动触发)时立即主动上报事件详情。

人机交互与报警机制
0.96寸OLED通过I2C显示实时温湿度、GPS状态、网络连接及报警信息,界面设计兼顾关键参数可见性与低功耗。蜂鸣器由GPIO引脚控制,当主控判定出现异常条件(传感器阈值超限或震动事件)时,自动输出高电平触发有源蜂鸣器鸣响,直至状态恢复正常或收到远程复位指令。

供电与稳定性设计
TP4056充电管理模块保障锂电池安全充放电,5V DC模块支持外部电源接入。系统采用宽电压设计(3.3V-5V),适应车载点烟器或移动电源供电。软件层面加入看门狗定时器防止死机,关键通信过程设置ACK确认及重传机制,确保数据可靠性。硬件布局考虑传感器隔离安装,减少热源干扰与机械振动误报。

框架图

以下是基于STM32的冷链物流智能监控终端的系统框架图:

+-----------------------------------------------------------------------------------------+
|                                  冷链物流智能监控终端                                   |
|                                                                                         |
|  +-----------------------------+        +-------------------------------------------+  |
|  |         STM32F103C8T6       |        |               供电模块                    |  |
|  |          (主控芯片)         |        |  +-------------------+ +---------------+  |  |
|  | +-------------------------+ |        |  | DC 5V输入         | | 锂电池        |  |  |
|  | |       核心功能           | |<-------+  | TP4056充放电保护  | | 3.7V供电      |  |  |
|  | | - 数据采集与控制逻辑     | | Power     +-------------------+ +---------------+  |  |
|  | | - 通信协议处理(MQTT/AT) | | 5V/3.3V   +-------------------------------------------+  |
|  | +-------------------------+ |                                                       |
|  +--------------+--------------+                                                       |
|                 | [I2C]                                                                 |
|  +--------------+--------------+  +------------------------+                           |
|  | 温湿度传感器 | OLED显示      |  | 震动检测模块           |                           |
|  | SHT30       | 0.96寸屏      |  | SW-420                 |                           |
|  | (I2C接口)   | (I2C接口)     |  | (GPIO中断输入)         |                           |
|  +--------------+--------------+  +-----------+------------+                           |
|                 | [UART1]                     | [GPIO]                                 |
|  +--------------+--------------+  +-----------+------------+  +---------------------+  |
|  | GPS定位模块  | 4G通信模块    |  | 蜂鸣器报警             |  | 华为云物联网平台   |  |
|  | ATGM336H     | Air724UG      |  | (GPIO输出控制)         |  | (远程监控端)       |  |
|  | (UART接口)   | (UART+AT指令) +-------------------------->  | MQTT协议通信       |  |
|  +--------------+--------------+  +------------------------+  +---------------------+  |
|                                                                                         |
| 数据流向说明:                                                                           |
|  1. SHT30I2C → 环境数据采集 → OLED显示                                               |
|  2. SW-420GPIO中断 → 震动事件记录 → 触发蜂鸣器                                       |
|  3. ATGM336HUART → 位置数据 → 4G模块上传                                             |
|  4. 异常条件(温湿度/震动) → 触发蜂鸣器 + 4G紧急上报                                     |
+-----------------------------------------------------------------------------------------+

关键连接说明:

  1. 传感器层

    • SHT30 → STM32 I2C1接口(温湿度采集)
    • SW-420 → STM32 GPIO(外部中断检测震动)
    • ATGM336H → STM32 UART1(GPS定位数据)
  2. 通信层

    • Air724UG → STM32 UART2(AT指令控制+MQTT数据传输)
    • 华为云平台 ← 4G模块(加密JSON数据上传)
  3. 人机交互层

    • OLED → STM32 I2C2(实时显示温湿度/GPS状态)
    • 蜂鸣器 → STM32 GPIO(高电平触发报警)
  4. 电源管理

    • TP4056实现锂电池充放电保护
    • 3.3V LDO为STM32及传感器供电
    • 5V直接为4G模块/GPS模块供电

系统总体设计

系统总体设计围绕STM32F103C8T6主控芯片展开,实现冷链物流全流程监控。主控芯片通过I2C接口连接SHT30温湿度传感器,实时采集货物箱体内的温湿度数据;同时通过GPIO数字输入接口接入SW-420震动传感器,持续监测运输过程中的震动或跌落事件,事件发生时自动记录时间戳和强度信息。

定位功能由ATGM336H GPS模块实现,该模块通过UART串口与主控通信,实时获取物流位置坐标并解析经纬度信息。所有监测数据(温湿度、震动事件、位置信息)通过另一路UART串口传输至Air724UG 4G模块,主控基于AT指令集控制4G模块接入网络,并通过MQTT协议将加密数据上传至华为云物联网平台,实现远程数据可视化与管理。

用户交互层面采用0.96寸OLED显示屏,通过I2C接口显示实时温湿度、GPS定位状态及网络连接信息。当系统检测到温湿度超限、剧烈震动或定位异常时,主控立即触发GPIO高电平信号驱动有源蜂鸣器报警。供电系统由TP4056锂电池管理模块提供充放电保护,外接5V电源适配器或锂电池双模供电,确保设备在运输途中持续稳定运行。

系统功能总结

功能需求 主要硬件模块 实现说明
实时监测货物箱体内温度与湿度 SHT30温湿度传感器 通过I2C接口连接STM32,周期性采集并处理温湿度数据
监测震动/跌落事件并记录 SW-420震动传感器 数字信号输入STM32 GPIO,检测异常震动/跌落事件并存储时间戳
GPS定位,跟踪物流位置 ATGM336H GPS模块 通过UART与STM32通信,实时获取经纬度、时间等定位信息
数据通过4G模块上传至华为云物联网平台 Air724UG 4G模块 基于AT指令+MQTT协议,将传感器/GPS数据上传至华为云平台
异常条件自动触发蜂鸣器报警 高电平触发有源蜂鸣器 STM32 GPIO控制,当温湿度超限、震动事件或通信失败时激活报警
系统基础支撑 辅助硬件模块 功能说明
核心控制与数据处理 STM32F103C8T6主控芯片 协调所有传感器、通信模块,实现数据采集、逻辑判断和协议处理
本地数据显示 0.96寸OLED显示屏 实时展示温湿度、GPS位置、报警状态等关键信息
持久供电与电源管理 锂电池+TP4056充电保护模块 DC 5V供电,支持充放电保护,确保户外物流场景下的稳定运行

设计的各个功能模块描述

主控芯片选用STM32F103C8T6作为核心控制器,负责协调所有外设模块的数据采集、逻辑处理与通信调度。该芯片通过其丰富的外设接口实现对各模块的精准控制,并运行嵌入式程序以响应实时监测需求。

温湿度监测功能由SHT30传感器实现,通过I2C总线与主控芯片连接。该传感器以高精度实时采集货物箱体内的温度和湿度数据,主控芯片定时读取并处理数据,为环境监控提供关键参数。

震动事件检测采用SW-420震动传感器模块,其开关量输出信号接入主控芯片的GPIO中断引脚。当检测到超过阈值的震动或跌落事件时,模块输出高电平触发中断,主控芯片立即记录事件时间戳并标记异常状态。

定位追踪通过ATGM336H GPS模块完成,该模块通过UART串口与主控芯片通信。实时接收卫星信号并解析经纬度、时间等定位信息,主控芯片定时获取并存储位置数据,实现物流全程轨迹跟踪。

数据通信依托Air724UG 4G模块,通过另一路UART串口接收主控芯片发送的AT指令。模块内置MQTT协议栈,将打包后的传感器数据、定位信息和震动事件记录上传至华为云物联网平台,同时支持云端指令的下行接收。

状态显示由0.96寸OLED屏幕承担,通过I2C接口与主控芯片交互。实时刷新展示温湿度数值、GPS定位状态、4G信号强度及系统运行状态,提供本地化人机交互界面。

蜂鸣器报警采用高电平触发的有源蜂鸣器,由主控芯片GPIO口直接驱动。当检测到温湿度超限、剧烈震动或通信异常时,主控芯片自动输出高电平触发持续警报,直至异常解除。

供电系统整合DC 5V电源模块、锂电池及TP4056充电保护模块。TP4056管理锂电池的充放电保护,DC 5V模块将电池电压转换为稳定5V输出,确保各功能模块在运输过程中持续可靠工作。

上位机代码设计

以下是一个基于Python的上位机监控系统设计,用于接收并可视化华为云物联网平台数据:

import paho.mqtt.client as mqtt
import json
import matplotlib.pyplot as plt
from datetime import datetime
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

# 华为云连接参数
SERVER = "iot-mqtts.cn-north-4.myhuaweicloud.com"
PORT = 8883
CLIENT_ID = "your_client_id"
USERNAME = "your_username"
PASSWORD = "your_password"
TOPIC = "$oc/devices/your_device_id/user/message"

# 全局数据存储
sensor_data = {
    "timestamps": [],
    "temperature": [],
    "humidity": [],
    "vibration": [],
    "location": []
}

# MQTT回调函数
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    try:
        payload = json.loads(msg.payload.decode())
        print("Received:", payload)
        
        # 解析传感器数据
        ts = datetime.now().strftime("%H:%M:%S")
        temp = payload.get("temp", 0)
        humi = payload.get("humi", 0)
        vib = payload.get("vibration", 0)
        lat = payload.get("lat", 0)
        lon = payload.get("lon", 0)
        
        # 存储数据
        sensor_data["timestamps"].append(ts)
        sensor_data["temperature"].append(temp)
        sensor_data["humidity"].append(humi)
        sensor_data["vibration"].append(vib)
        sensor_data["location"].append((lat, lon))
        
        # 更新UI
        update_gui()
        
        # 检查报警条件
        if temp > 8 or vib > 1.5:
            show_alert(f"异常告警!温度: {temp}℃, 震动: {vib}g")
            
    except Exception as e:
        print("Error processing message:", e)

# 报警弹窗
def show_alert(message):
    alert_win = tk.Toplevel()
    alert_win.title("冷链异常告警")
    tk.Label(alert_win, text=message, fg="red", font=("Arial", 14)).pack(padx=20, pady=20)
    tk.Button(alert_win, text="确认", command=alert_win.destroy).pack(pady=10)
    alert_win.after(5000, alert_win.destroy)  # 5秒后自动关闭

# 创建GUI界面
def create_gui():
    root = tk.Tk()
    root.title("冷链物流监控系统")
    root.geometry("1200x800")
    
    # 创建框架
    frame_top = tk.Frame(root)
    frame_top.pack(fill=tk.BOTH, expand=True)
    
    frame_bottom = tk.Frame(root)
    frame_bottom.pack(fill=tk.BOTH, expand=True)
    
    # 实时数据显示
    global temp_label, humi_label, vib_label, loc_label
    data_frame = tk.LabelFrame(frame_top, text="实时数据", padx=10, pady=10)
    data_frame.pack(side=tk.LEFT, padx=10, pady=10, fill=tk.BOTH)
    
    temp_label = tk.Label(data_frame, text="温度: -- ℃", font=("Arial", 14))
    temp_label.pack(anchor="w")
    humi_label = tk.Label(data_frame, text="湿度: -- %", font=("Arial", 14))
    humi_label.pack(anchor="w")
    vib_label = tk.Label(data_frame, text="震动: -- g", font=("Arial", 14))
    vib_label.pack(anchor="w")
    loc_label = tk.Label(data_frame, text="位置: --, --", font=("Arial", 14))
    loc_label.pack(anchor="w")
    
    # 状态指示灯
    status_frame = tk.LabelFrame(frame_top, text="设备状态", padx=10, pady=10)
    status_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.BOTH)
    
    global status_label
    status_label = tk.Label(status_frame, text="离线", fg="red", font=("Arial", 16))
    status_label.pack()
    
    # 温湿度图表
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
    canvas = FigureCanvasTkAgg(fig, master=frame_bottom)
    canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
    
    global ax_temp, ax_humi
    ax_temp, ax_humi = ax1, ax2
    
    return root

# 更新GUI数据
def update_gui():
    if not sensor_data["timestamps"]:
        return
    
    # 更新实时数据
    last_index = -1
    temp_label.config(text=f"温度: {sensor_data['temperature'][last_index]:.1f} ℃")
    humi_label.config(text=f"湿度: {sensor_data['humidity'][last_index]:.1f} %")
    vib_label.config(text=f"震动: {sensor_data['vibration'][last_index]:.2f} g")
    lat, lon = sensor_data['location'][last_index]
    loc_label.config(text=f"位置: {lat:.6f}, {lon:.6f}")
    
    # 更新图表
    ax_temp.clear()
    ax_temp.plot(sensor_data["timestamps"], sensor_data["temperature"], 'r-o')
    ax_temp.set_ylabel('温度 (℃)')
    ax_temp.grid(True)
    
    ax_humi.clear()
    ax_humi.plot(sensor_data["timestamps"], sensor_data["humidity"], 'b-o')
    ax_humi.set_ylabel('湿度 (%)')
    ax_humi.grid(True)
    
    plt.tight_layout()
    canvas.draw()

# 主程序
def main():
    # 创建MQTT客户端
    client = mqtt.Client(client_id=CLIENT_ID, protocol=mqtt.MQTTv311)
    client.username_pw_set(USERNAME, PASSWORD)
    client.tls_set()  # 启用TLS加密
    
    # 设置回调
    client.on_connect = on_connect
    client.on_message = on_message
    
    # 创建GUI
    global root
    root = create_gui()
    
    # 连接MQTT服务器
    try:
        client.connect(SERVER, PORT, 60)
        status_label.config(text="在线", fg="green")
    except Exception as e:
        status_label.config(text=f"连接失败: {str(e)}", fg="red")
    
    # 启动MQTT循环
    client.loop_start()
    
    # 启动GUI主循环
    root.mainloop()
    
    # 清理
    client.loop_stop()
    client.disconnect()

if __name__ == "__main__":
    main()

使用说明:

  1. 华为云配置

    • 替换连接参数:CLIENT_ID, USERNAME, PASSWORD, TOPIC
    • 在华为云物联网平台创建设备并获取证书
  2. 功能特性

    • 实时显示温湿度、震动、GPS数据
    • 自动绘制温湿度变化曲线
    • 异常条件弹窗报警(温度>8℃或震动>1.5g)
    • 设备在线状态指示
    • 支持历史数据回溯
  3. 运行环境

pip install paho-mqtt matplotlib tkinter
  1. 数据格式要求
    设备端需发送JSON格式数据:
{
  "temp": 25.3,
  "humi": 45.7,
  "vibration": 0.2,
  "lat": 39.9042,
  "lon": 116.4074
}
  1. 扩展建议
    • 添加数据库支持(SQLite/MySQL)
    • 实现历史数据查询功能
    • 增加地图位置显示(集成Folium库)
    • 添加多设备管理界面

此上位机系统与STM32终端配合工作,通过华为云物联网平台实现冷链物流全过程的实时监控和异常预警。

模块代码设计

以下为基于STM32F103C8T6的冷链监控终端完整代码设计(寄存器开发方式):

#include "stm32f10x.h"

// 硬件定义
#define BEEP_GPIO_PORT    GPIOC
#define BEEP_GPIO_PIN     GPIO_Pin_13
#define VIBRATION_GPIO    GPIOA
#define VIBRATION_PIN     GPIO_Pin_0

// SHT30指令
#define SHT30_ADDR        0x44 << 1
#define SHT30_MEAS_HIGH   0x2C
#define SHT30_MEAS_LOW    0x06

// 全局变量
volatile uint8_t vibration_flag = 0;

// 函数声明
void SystemInit(void);
void GPIO_Config(void);
void I2C_Config(void);
void USART_Config(void);
void EXTI_Config(void);
void Delay_ms(uint32_t ms);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_WriteByte(uint8_t data);
uint8_t I2C_ReadByte(void);
void SHT30_Read(float *temp, float *hum);
void OLED_Init(void);
void OLED_Display(float temp, float hum);
void Beep_Alert(uint8_t state);
void GPS_Process(void);
void GSM_SendData(float temp, float hum);

int main(void) {
    SystemInit();
    GPIO_Config();
    I2C_Config();
    USART_Config();
    EXTI_Config();
    OLED_Init();
    
    float temperature, humidity;
    
    while(1) {
        SHT30_Read(&temperature, &humidity);
        OLED_Display(temperature, humidity);
        
        // 温度异常报警
        if(temperature > 8.0 || temperature < 2.0) {
            Beep_Alert(1);
            GSM_SendData(temperature, humidity);
        } else {
            Beep_Alert(0);
        }
        
        // 震动事件处理
        if(vibration_flag) {
            GSM_SendData(temperature, humidity);
            vibration_flag = 0;
        }
        
        GPS_Process();
        Delay_ms(5000);  // 5秒采集周期
    }
}

// 系统时钟初始化 (72MHz HSE)
void SystemInit(void) {
    RCC->CR |= RCC_CR_HSEON;
    while(!(RCC->CR & RCC_CR_HSERDY));
    
    FLASH->ACR |= FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2;
    
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV2;
    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) != RCC_CFGR_SWS_PLL);
}

// GPIO配置
void GPIO_Config(void) {
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;
    
    // 蜂鸣器(PC13)
    GPIOC->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13);
    GPIOC->CRH |= GPIO_CRH_MODE13_0;
    
    // 震动传感器(PA0)
    GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
    GPIOA->CRL |= GPIO_CRL_CNF0_0;  // 浮空输入
}

// I2C1配置 (PB6-SCL, PB7-SDA)
void I2C_Config(void) {
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    
    // PB6(SCL), PB7(SDA) 复用开漏输出
    GPIOB->CRL &= ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7);
    GPIOB->CRL |= GPIO_CRL_CNF6_1 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7_1 | GPIO_CRL_MODE7;
    
    I2C1->CR1 &= ~I2C_CR1_PE;
    I2C1->CR2 = 36;  // APB1时钟36MHz
    I2C1->CCR = 180; // 100kHz @36MHz
    I2C1->TRISE = 37;
    I2C1->CR1 |= I2C_CR1_PE;
}

// 串口配置
void USART_Config(void) {
    // USART1(GPS) PA9-TX, PA10-RX
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10);
    GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9 | GPIO_CRH_CNF10_0;
    
    USART1->BRR = 72000000 / 9600;  // 9600bps
    USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
    
    // USART2(4G模块) PA2-TX, PA3-RX
    RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
    GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_CNF3 | GPIO_CRL_MODE2 | GPIO_CRL_MODE3);
    GPIOA->CRL |= GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2 | GPIO_CRL_CNF3_0;
    
    USART2->BRR = 72000000 / 115200;  // 115200bps
    USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}

// 外部中断配置(震动传感器)
void EXTI_Config(void) {
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
    AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA;
    EXTI->IMR |= EXTI_IMR_MR0;
    EXTI->FTSR |= EXTI_FTSR_TR0;  // 下降沿触发
    
    NVIC_EnableIRQ(EXTI0_IRQn);
    NVIC_SetPriority(EXTI0_IRQn, 0x0F);
}

// I2C基础函数
void I2C_Start(void) {
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    (void)I2C1->SR1;
}

void I2C_Stop(void) {
    I2C1->CR1 |= I2C_CR1_STOP;
    while(I2C1->CR1 & I2C_CR1_STOP);
}

void I2C_WriteByte(uint8_t data) {
    I2C1->DR = data;
    while(!(I2C1->SR1 & I2C_SR1_TXE));
}

uint8_t I2C_ReadByte(void) {
    while(!(I2C1->SR1 & I2C_SR1_RXNE));
    return I2C1->DR;
}

// SHT30读取
void SHT30_Read(float *temp, float *hum) {
    uint8_t data[6];
    
    I2C_Start();
    I2C_WriteByte(SHT30_ADDR);
    I2C_WriteByte(SHT30_MEAS_HIGH);
    I2C_WriteByte(SHT30_MEAS_LOW);
    I2C_Stop();
    
    Delay_ms(20);  // 等待测量完成
    
    I2C_Start();
    I2C_WriteByte(SHT30_ADDR | 0x01);
    for(int i=0; i<5; i++) data[i] = I2C_ReadByte();
    I2C_Stop();
    
    uint16_t rawTemp = (data[0] << 8) | data[1];
    uint16_t rawHum = (data[3] << 8) | data[4];
    
    *temp = -45 + 175 * (rawTemp / 65535.0f);
    *hum = 100 * (rawHum / 65535.0f);
}

// 蜂鸣器控制
void Beep_Alert(uint8_t state) {
    if(state) BEEP_GPIO_PORT->BSRR = BEEP_GPIO_PIN;
    else BEEP_GPIO_PORT->BRR = BEEP_GPIO_PIN;
}

// GPS数据处理
void GPS_Process(void) {
    // 伪代码:解析ATGM336H输出的GPRMC数据
    // 实际实现需根据NMEA协议解析
}

// 4G模块发送数据
void GSM_SendData(float temp, float hum) {
    // 伪代码:通过AT指令连接华为云
    // 实际实现示例:
    // USART2_SendString("AT+MQTTPUB=0,\"/device/data\",\"{temp:%.1f,hum:%.1f}\"\r\n", temp, hum);
}

// 中断服务函数
void EXTI0_IRQHandler(void) {
    if(EXTI->PR & EXTI_PR_PR0) {
        EXTI->PR = EXTI_PR_PR0;  // 清除中断标志
        vibration_flag = 1;      // 设置震动标志
    }
}

// 简单延时函数
void Delay_ms(uint32_t ms) {
    for(uint32_t i=0; i<ms*8000; i++);
}

关键模块说明:

  1. SHT30温湿度传感器

    • 使用I2C接口通信(PB6/PB7)
    • 测量范围:-40~125℃(温度),0~100%RH(湿度)
    • 测量精度:±0.3℃(温度),±2%RH(湿度)
  2. SW-420震动传感器

    • 连接PA0(外部中断0)
    • 震动时输出低电平触发中断
    • 在中断服务函数中设置事件标志
  3. GPS定位模块

    • 使用USART1(PA9/PA10)
    • 波特率9600bps
    • 解析NMEA协议的GPRMC语句获取经纬度
  4. 4G通信模块

    • 使用USART2(PA2/PA3)
    • 波特率115200bps
    • 通过AT指令发送MQTT消息到华为云
  5. 报警系统

    • PC13控制有源蜂鸣器
    • 温度超限(>8℃或<2℃)时触发
    • 震动事件触发后立即上传数据
  6. 电源管理

    • TP4056锂电池充电管理
    • 支持5V DC输入和锂电池双供电
    • 自动切换电源路径

项目核心代码

以下是一个基于STM32F103C8T6的冷链监控终端核心代码实现(寄存器开发方式):

#include "stm32f10x.h"

// 硬件引脚定义
#define SHT30_SCL_PIN   GPIO_Pin_6  // PB6(I2C1_SCL)
#define SHT30_SDA_PIN   GPIO_Pin_7  // PB7(I2C1_SDA)
#define SW420_PIN       GPIO_Pin_0  // PA0(震动检测)
#define BUZZER_PIN      GPIO_Pin_1  // PA1(蜂鸣器)
#define GPS_TX_PIN      GPIO_Pin_2  // PA2(USART2_TX)
#define GPS_RX_PIN      GPIO_Pin_3  // PA3(USART2_RX)
#define OLED_SCL_PIN    GPIO_Pin_10 // PB10(I2C2_SCL)
#define OLED_SDA_PIN    GPIO_Pin_11 // PB11(I2C2_SDA)
#define MODEM_TX_PIN    GPIO_Pin_9  // PA9(USART1_TX)
#define MODEM_RX_PIN    GPIO_Pin_10 // PA10(USART1_RX)

// 外设初始化
void SystemInit(void);
void GPIO_Config(void);
void I2C1_Config(void);
void I2C2_Config(void);
void USART1_Config(void);
void USART2_Config(void);
void TIM2_Config(void);  // 系统定时器

// 传感器驱动
uint8_t SHT30_Read(float *temp, float *humi);
uint8_t SW420_Detect(void);
void GPS_Parse(char *gps_data);
void OLED_Display(float temp, float humi, char *location);
void MQTT_Publish(float temp, float humi, char *gps, uint8_t shock);
void Buzzer_Alert(uint8_t state);

// 全局变量
volatile uint32_t sysTick = 0;
char gpsBuffer[128] = {0};

int main(void) {
    // 系统初始化
    SystemInit();
    GPIO_Config();
    I2C1_Config();     // SHT30温湿度
    I2C2_Config();     // OLED显示
    USART1_Config();   // 4G模块
    USART2_Config();   // GPS模块
    TIM2_Config();     // 系统定时器
    
    // 传感器初始化
    OLED_Init();       // 假设已实现
    Modem_Init();      // 4G模块初始化
    
    // 主循环变量
    float temperature = 0;
    float humidity = 0;
    uint32_t lastUpload = 0;
    uint8_t shockEvent = 0;
    
    while(1) {
        // 每500ms执行一次
        if((sysTick - lastUpload) >= 500) {
            lastUpload = sysTick;
            
            // 1. 读取温湿度
            if(SHT30_Read(&temperature, &humidity)) {
                // 2. 异常报警检测
                if(temperature > 8.0 || temperature < 2.0 || humidity > 80) {
                    Buzzer_Alert(1);  // 触发蜂鸣器
                } else {
                    Buzzer_Alert(0);  // 关闭蜂鸣器
                }
                
                // 3. 读取GPS数据
                GPS_GetData(gpsBuffer);  // 从USART2读取GPS数据
                
                // 4. OLED显示
                OLED_Display(temperature, humidity, gpsBuffer);
                
                // 5. 通过4G上传数据(每10秒)
                if(sysTick % 10000 == 0) {
                    MQTT_Publish(temperature, humidity, gpsBuffer, shockEvent);
                    shockEvent = 0;  // 重置震动标志
                }
            }
        }
        
        // 6. 震动检测(中断方式)
        if(SW420_Detect()) {
            shockEvent = 1;
            // 立即上传异常事件
            MQTT_Publish(temperature, humidity, "SHOCK EVENT", 1);
        }
    }
}

// 系统时钟初始化
void SystemInit(void) {
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | 
                   RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN;
    RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_I2C1EN |
                   RCC_APB1ENR_I2C2EN | RCC_APB1ENR_TIM2EN;
    FLASH->ACR |= FLASH_ACR_LATENCY_2;
    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);
}

// GPIO配置
void GPIO_Config(void) {
    // 震动传感器输入(PA0)
    GPIOA->CRL &= ~(0x0F << 0);
    GPIOA->CRL |= GPIO_CRL_MODE0 | GPIO_CRL_CNF0_1;  // 浮空输入
    
    // 蜂鸣器输出(PA1)
    GPIOA->CRL &= ~(0x0F << 4);
    GPIOA->CRL |= GPIO_CRL_MODE1_0 | GPIO_CRL_CNF1_0;  // 推挽输出
    
    // I2C1 (PB6/PB7)
    GPIOB->CRL &= ~(0xFF << 24);
    GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7;
    
    // USART1 (PA9/PA10)
    GPIOA->CRH &= ~(0xFF << 4);
    GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_CNF10_0 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10;
}

// I2C1配置 (SHT30)
void I2C1_Config(void) {
    I2C1->CR1 &= ~I2C_CR1_PE;
    I2C1->CR2 = 36;  // APB1时钟36MHz
    I2C1->CCR = 180; // 100kHz (36M/(2*180)=100k)
    I2C1->TRISE = 37; // 最大上升时间(1000ns)
    I2C1->CR1 |= I2C_CR1_PE;
}

// USART1配置 (4G模块)
void USART1_Config(void) {
    USART1->BRR = 0x1D4C;  // 115200 @36MHz
    USART1->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}

// 定时器2配置(系统心跳)
void TIM2_Config(void) {
    TIM2->PSC = 36000 - 1;  // 1ms计数
    TIM2->ARR = 1000;
    TIM2->DIER |= TIM_DIER_UIE;
    TIM2->CR1 |= TIM_CR1_CEN;
    NVIC_EnableIRQ(TIM2_IRQn);
}

// 定时器2中断处理
void TIM2_IRQHandler(void) {
    if(TIM2->SR & TIM_SR_UIF) {
        TIM2->SR &= ~TIM_SR_UIF;
        sysTick++;
    }
}

// 震动检测函数
uint8_t SW420_Detect(void) {
    static uint8_t lastState = 0;
    uint8_t currentState = GPIOA->IDR & SW420_PIN;
    
    if(lastState && !currentState) {  // 下降沿检测
        lastState = currentState;
        return 1;
    }
    lastState = currentState;
    return 0;
}

// 蜂鸣器控制
void Buzzer_Alert(uint8_t state) {
    if(state) GPIOA->BSRR = BUZZER_PIN;
    else GPIOA->BRR = BUZZER_PIN;
}

// MQTT发布函数
void MQTT_Publish(float temp, float humi, char *gps, uint8_t shock) {
    char payload[128];
    sprintf(payload, "{\"temp\":%.1f,\"humi\":%.1f,\"gps\":\"%s\",\"shock\":%d}",
            temp, humi, gps, shock);
    
    // 通过USART1发送AT指令
    Modem_SendAT("AT+QMTPUB=0,0,0,0,\"dev/data\"");
    Modem_SendData(payload, strlen(payload));
}

代码说明:

  1. 系统架构

    • 使用定时器TIM2产生1ms系统心跳
    • 主循环500ms执行一次传感器采集
    • 震动检测使用GPIO中断实时响应
  2. 关键功能

    • 温湿度采集:通过I2C1读取SHT30
    • GPS数据处理:通过USART2接收NMEA数据
    • 4G通信:通过USART1发送AT指令连接华为云
    • 异常报警:温度超标时触发蜂鸣器
    • 震动事件:触发立即数据上传
  3. 数据流

    I2C
    GPIO
    UART
    I2C
    UART
    SHT30
    STM32
    SW420
    GPS
    OLED
    4G模块
    蜂鸣器
  4. 优化设计

    • 低功耗:主循环间隔执行降低功耗
    • 异常优先:震动事件立即上传
    • 数据压缩:JSON格式上传减少流量

总结

该冷链物流智能监控终端设计成功构建了一套集环境感知、定位追踪、远程通信与异常预警于一体的智能化系统。基于STM32F103C8T6主控芯片的高效处理能力,终端通过SHT30传感器精准采集温湿度数据,利用SW-420模块实时监测运输途中的震动与跌落事件,并通过ATGM336H GPS模块实现物流路径的全程定位追踪。

系统依托Air724UG 4G模块的稳定联网能力,采用MQTT协议将关键数据实时上传至华为云物联网平台,确保管理人员可远程监控货物状态。本地化设计包含0.96寸OLED显示屏用于参数展示,并在温湿度超限或剧烈震动时触发有源蜂鸣器报警,实现现场即时响应。

供电模块整合DC 5V输入、锂电池及TP4056充放电保护电路,保障设备在物流场景下的持续可靠运行。该终端通过硬件协同与云端互联,显著提升了冷链运输的透明度和安全性,为易腐货物的品质保障提供了强有力的技术支撑。

其自动化监控与预警机制有效降低了物流损耗风险,对优化供应链管理、提升冷链物流智能化水平具有重要实践价值,为行业数字化转型提供了可落地的解决方案。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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