铁路列车车辆监控系统设计方案(双串口PC机实现)

铁路列车车辆监控系统设计方案(双串口PC机实现)

一、系统概述

1.1 系统定位

铁路列车车辆监控系统是基于PC机的双串口通信平台,用于实时采集列车车辆运行状态数据、与地面监控中心交互,并实现异常状态报警与控制。系统通过两个独立串口分别连接车载数据采集模块地面监控终端,满足铁路环境下多源数据融合与远程监控需求。

1.2 核心需求

二、系统架构设计

2.1 硬件组成

设备/模块 功能描述 通信接口 关键参数
PC机 监控中心,运行监控软件,处理双串口数据 2×RS232/USB转串口 波特率:9600~115200bps,8N1
车载数据采集模块 集成STM32/Arduino,连接车辆传感器(速度、位置、温度、压力、振动等) 串口(COM1) 自定义协议,帧周期100ms~1s
地面监控终端 地面站PC或工控机,发送控制指令(如紧急制动、参数设置),接收报警信息 串口(COM2) Modbus RTU协议或自定义协议
传感器组 速度传感器(光电/霍尔)、GPS定位模块、温度传感器(PT100)、压力传感器 模拟/数字接口 精度:速度±0.1km/h,温度±0.5℃
报警装置 声光报警器、短信模块(可选) 数字I/O 支持异常状态分级报警(预警/紧急)

2.2 软件架构

graph TD
    A[PC监控软件] --> B[串口1通信模块]
    A --> C[串口2通信模块]
    A --> D[数据处理中心]
    A --> E[监控显示界面]
    A --> F[数据存储模块]
    A --> G[报警处理模块]
    
    B -->|接收| H[车载数据采集模块]
    C -->|通信| I[地面监控终端]
    D -->|解析/校验| B
    D -->|协议转换| C
    E -->|显示| D
    F -->|存储| D
    G -->|触发| E
    G -->|控制| B

三、双串口通信实现

3.1 串口分配与协议设计

串口 连接对象 通信方向 协议类型 数据内容 波特率 周期
COM1 车载数据采集模块 PC←车载(接收) 自定义帧协议 帧头(0xAA55)+设备ID(1B)+数据长度(1B)+数据(速度2B+位置4B+温度2B+压力2B+振动2B)+CRC16(2B)+帧尾(0x0D0A) 19200bps 500ms
COM2 地面监控终端 PC↔地面(双向) Modbus RTU 读保持寄存器(0x03):车辆状态、故障代码;写单个寄存器(0x06):控制指令(如0x01=紧急制动) 9600bps 按需交互

3.2 自定义帧协议(COM1)

帧结构(共16字节)

字段 字节数 说明
帧头 2 固定0xAA55(大端模式)
设备ID 1 车载模块编号(0x01~0xFF)
数据长度 1 数据区字节数(固定0x0A=10B)
速度 2 单位0.1km/h,范围01000(0x00000x03E8)
位置 4 GPS经纬度(经度2B+纬度2B,单位0.0001°,范围-180~180)
温度 2 单位0.1℃,范围-400850(0xFE700x0352)
压力 2 单位kPa,范围01000(0x00000x03E8)
振动 2 单位m/s²,范围0200(0x00000x00C8)
CRC16 2 校验范围:设备ID~振动(多项式0x8005,初始值0xFFFF)
帧尾 2 固定0x0D0A(回车换行)

3.3 Modbus RTU协议(COM2)

关键功能码

功能码 名称 用途 数据格式
0x03 读保持寄存器 地面站读取车辆状态(如速度、故障代码) 请求:从机地址(1B)+0x03+起始地址(2B)+寄存器数(2B);响应:数据(n×2B)
0x06 写单个寄存器 地面站发送控制指令(如紧急制动) 请求:从机地址(1B)+0x06+寄存器地址(2B)+数据(2B)
0x10 写多个寄存器 地面站批量设置参数(如报警阈值) 请求:从机地址(1B)+0x10+起始地址(2B)+寄存器数(2B)+字节数(1B)+数据(n×2B)

四、PC监控软件实现(C#示例)

4.1 开发环境

4.2 关键代码模块

4.2.1 双串口初始化

using System.IO.Ports;

public class SerialPortManager
{
    public SerialPort Com1 { get; set; }  // 连接车载模块
    public SerialPort Com2 { get; set; }  // 连接地面终端

    public void InitPorts()
    {
        // COM1配置(车载数据采集)
        Com1 = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One);
        Com1.DataReceived += Com1_DataReceived;  // 数据接收事件
        Com1.Open();

        // COM2配置(地面通信)
        Com2 = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
        Com2.DataReceived += Com2_DataReceived;
        Com2.Open();
    }

    // COM1数据接收(车载数据)
    private void Com1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        byte[] buffer = new byte[Com1.BytesToRead];
        Com1.Read(buffer, 0, buffer.Length);
        ProcessCarData(buffer);  // 解析车载数据
    }

    // COM2数据接收(地面指令)
    private void Com2_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        byte[] buffer = new byte[Com2.BytesToRead];
        Com2.Read(buffer, 0, buffer.Length);
        ProcessGroundCommand(buffer);  // 解析地面指令
    }
}

4.2.2 车载数据解析(自定义协议)

public class CarDataParser
{
    public struct CarData
    {
        public byte DeviceId;
        public float Speed;    // km/h
        public float Longitude; // °
        public float Latitude;  // °
        public float Temperature; // ℃
        public float Pressure;  // kPa
        public float Vibration; // m/s²
    }

    public static CarData Parse(byte[] frame)
    {
        if (frame.Length != 16 || frame[0] != 0xAA || frame[1] != 0x55)
            throw new Exception("无效帧头");

        // 校验CRC16
        ushort crcCalculated = CalculateCRC(frame, 2, 12);  // 校验设备ID~振动(12字节)
        ushort crcReceived = (ushort)((frame[14] << 8) | frame[15]);
        if (crcCalculated != crcReceived)
            throw new Exception("CRC校验失败");

        CarData data = new CarData();
        data.DeviceId = frame[2];
        data.Speed = BitConverter.ToUInt16(frame, 4) / 10.0f;  // 2字节速度
        data.Longitude = (BitConverter.ToInt16(frame, 6) / 10000.0f);  // 4字节经度(2B+2B)
        data.Latitude = (BitConverter.ToInt16(frame, 8) / 10000.0f);   // 4字节纬度
        data.Temperature = BitConverter.ToInt16(frame, 10) / 10.0f;  // 2字节温度
        data.Pressure = BitConverter.ToUInt16(frame, 12) / 10.0f;   // 2字节压力
        data.Vibration = BitConverter.ToUInt16(frame, 14) / 10.0f;  // 2字节振动(注:原帧结构需调整,此处为示例)

        return data;
    }

    // CRC16计算(多项式0x8005)
    private static ushort CalculateCRC(byte[] data, int offset, int length)
    {
        ushort crc = 0xFFFF;
        for (int i = 0; i < length; i++)
        {
            crc ^= (ushort)(data[offset + i] << 8);
            for (int j = 0; j < 8; j++)
            {
                if ((crc & 0x8000) != 0)
                    crc = (ushort)((crc << 1) ^ 0x8005);
                else
                    crc <<= 1;
            }
        }
        return crc;
    }
}

4.2.3 地面指令处理(Modbus RTU)

public class ModbusProcessor
{
    private SerialPort Com2;  // 地面通信串口

    public ModbusProcessor(SerialPort com2) => Com2 = com2;

    // 发送控制指令(如紧急制动:寄存器0x0001=0x0001)
    public void SendEmergencyStop()
    {
        byte[] command = {
            0x01,       // 从机地址(地面站)
            0x06,       // 功能码(写单个寄存器)
            0x00, 0x01, // 寄存器地址0x0001
            0x00, 0x01, // 数据0x0001(紧急制动)
            0x00, 0x00  // CRC16占位(需计算)
        };
        ushort crc = CalculateModbusCRC(command, 0, 6);
        command[6] = (byte)(crc & 0xFF);
        command[7] = (byte)(crc >> 8);
        Com2.Write(command, 0, 8);
    }

    // 解析地面读指令(0x03)
    public void ProcessReadCommand(byte[] request)
    {
        if (request[1] != 0x03) return;
        byte slaveAddr = request[0];
        ushort startAddr = (ushort)((request[2] << 8) | request[3]);
        ushort regCount = (ushort)((request[4] << 8) | request[5]);

        // 构造响应(示例:返回速度、温度)
        byte[] response = new byte[3 + 2 * regCount];
        response[0] = slaveAddr;
        response[1] = 0x03;
        response[2] = (byte)(2 * regCount);
        // 填充数据(速度0x0001=123.4km/h → 0x04D2,温度0x0002=25.5℃ → 0x00FF)
        response[3] = 0xD2; response[4] = 0x04;  // 速度
        response[5] = 0xFF; response[6] = 0x00;  // 温度
        // 计算CRC
        ushort crc = CalculateModbusCRC(response, 0, 7);
        response[7] = (byte)(crc & 0xFF);
        response[8] = (byte)(crc >> 8);
        Com2.Write(response, 0, 9);
    }

    // Modbus CRC16计算
    private ushort CalculateModbusCRC(byte[] data, int offset, int length)
    {
        ushort crc = 0xFFFF;
        for (int i = 0; i < length; i++)
        {
            crc ^= data[offset + i];
            for (int j = 0; j < 8; j++)
            {
                if ((crc & 0x0001) != 0)
                    crc = (ushort)((crc >> 1) ^ 0xA001);
                else
                    crc >>= 1;
            }
        }
        return crc;
    }
}

参考代码 铁路列车车辆监控系统本系统要求PC机有两个串行通讯串口 www.youwenfan.com/contentcnt/124055.html

五、系统功能实现

5.1 实时监控界面(C# WinForms)

5.2 数据存储与查询

5.3 报警与故障诊断

六、系统测试与优化

6.1 测试方案

测试项 方法 预期结果
串口通信稳定性 连续24小时收发数据,记录丢包率、错包率 丢包率<0.1%,错包率<0.01%
数据解析正确性 用模拟器发送自定义帧,验证解析后数值与发送值一致 解析误差<0.1%
报警响应时间 模拟异常数据(如温度=101℃),记录从数据接收到报警弹出的时间 响应时间<500ms
断线重连 拔插串口线,验证软件自动检测并重新连接 重连时间<3s,无数据丢失

6.2 优化措施

七、系统部署与维护

7.1 硬件部署

7.2 软件维护

八、总结

本系统通过PC机双串口实现了铁路列车车辆的实时监控,具备以下特点:

  1. 双串口独立通信:COM1专注车载数据采集,COM2负责地面交互,分工明确
  2. 可靠数据传输:自定义协议+CRC校验、Modbus RTU标准协议,确保数据正确性
  3. 直观监控界面:实时数据显示、地图定位、历史曲线、分级报警,满足运维需求
  4. 扩展性强:支持传感器扩展(如振动、电压)、协议扩展(如TCP/IP网关)

专注于matlab/simulink,电子电路,编程