C# Industrielle Automatisierung开发完全指南:构建Unternehmen级应用

kostenlosKostenloses technisches Material

Dieser Inhalt ist direkt lesbar und eignet sich für das Grundlagenlernen und die Suche.

C# Industrielle Automatisierung开发完全指南:构建Unternehmen级应用缩略图
🌐 Diese Seite ist noch nicht auf Deutsch verfügbar. Die chinesische Version wird angezeigt. Zurück zur chinesischen Seite.
本文目录
  1. 1. 引言:C#/.NET在Industrielle Automatisierung中的优势
  2. 2. 一、C#/.NET工业开发环境配置
  3. 3. 1.1 开发环境要求
  4. 4. 1.2 项目结构和依赖配置
  5. 5. 1.3 项目目录结构
  6. 6. 二、NModbus库深度使用
  7. 7. 2.1 基础Modbus TCP客户端
  8. 8. 2.2 Modbus RTUDie Serie客户端

C#/.NETIndustrielle Automatisierung开发完全指南:构建Unternehmen级工业应用

引言:C#/.NET在Industrielle Automatisierung中的优势

C#/.NET平台凭借其强大的TypusDas System、丰富的类库、卓越的性能和微软的全面支持,在Unternehmen级Industrielle Automatisierung领域占据重要地位。从传统的Windows桌面应用zu现代的云原生微服务,C#/.NET提供了vollständig的解决方案栈,特别适合需要高可靠性、高性能和长期维护的工业应用。

本文将深入探讨C#/.NET在Industrielle Automatisierung中的应用,重点介绍NModbus库的使用、WPF/WinForms界面开发、Unternehmen级架构设计,并结合实际案例展示如何构建专业级的Industrielle AutomatisierungDas System。

一、C#/.NET工业开发环境配置

1.1 开发环境要求

<!-- .NET SDK版本要求 -->
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <OutputType>Exe</OutputType>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

1.2 项目结构和依赖配置

<!-- IndustrialAutomation.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <!-- ModbusKommunikation -->
    <PackageReference Include="NModbus" Version="3.0.73" />
    <PackageReference Include="NModbus.Serial" Version="3.0.73" />

    <!-- Serielle Kommunikation -->
    <PackageReference Include="System.IO.Ports" Version="8.0.0" />

    <!-- 日志记录 -->
    <PackageReference Include="Serilog" Version="3.1.1" />
    <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
    <PackageReference Include="Serilog.Sinks.Console" Version="5.0.0" />

    <!-- 依赖注入 -->
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />

    <!-- 配置管理 -->
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />

    <!-- Daten验证 -->
    <PackageReference Include="FluentValidation" Version="11.8.0" />

    <!-- 单元测试 -->
    <PackageReference Include="xunit" Version="2.6.3" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.5" />
    <PackageReference Include="Moq" Version="4.20.69" />
  </ItemGroup>

</Project>

1.3 项目目录结构

IndustrialAutomation/
├── src/
│   ├── IndustrialAutomation.Core/          # 核心业务逻辑
│   │   ├── Models/                         # Daten模型
│   │   ├── Services/                       # 业务服务
│   │   ├── Interfaces/                     # Schnittstelle定义
│   │   └── Exceptions/                     # Custom definiert异常
│   │
│   ├── IndustrialAutomation.Modbus/        # ModbusKommunikation模块
│   │   ├── Clients/                        # Modbus客户端
│   │   ├── Servers/                        # ModbusDer Server
│   │   └── Converters/                     # DatenKonverter.
│   │
│   ├── IndustrialAutomation.UI/            # 用户界面
│   │   ├── Views/                          # WPF视图
│   │   ├── ViewModels/                     # MVVM视图模型
│   │   ├── Converters/                     # 值Konverter.
│   │   └── Behaviors/                      # 行为
│   │
│   └── IndustrialAutomation.Host/          # 应用程序宿主
│
├── tests/
│   ├── IndustrialAutomation.Core.Tests/
│   ├── IndustrialAutomation.Modbus.Tests/
│   └── IndustrialAutomation.Integration.Tests/
│
├── config/
│   ├── appsettings.json                    # Anwendung Konfiguration
│   ├── appsettings.Development.json        # 开发环境配置
│   └── devices.json                        # Ausrüstung配置
│
└── docs/                                   # 项目Dokumentation

二、NModbus库深度使用

2.1 基础Modbus TCP客户端

using NModbus;
using NModbus.Device;
using System.Net.Sockets;

namespace IndustrialAutomation.Modbus.Clients
{
    /// <summary>
    /// Modbus TCP客户端
    /// </summary>
    public class ModbusTcpClient : IModbusClient, IDisposable
    {
        private readonly ILogger<ModbusTcpClient> _logger;
        private readonly TcpClient _tcpClient;
        private IModbusMaster? _modbusMaster;
        private bool _disposed;

        /// <summary>
        /// AusrüstungVerbindungStatus
        /// </summary>
        public bool IsConnected => _tcpClient?.Connected ?? false;

        /// <summary>
        /// AusrüstungIPAdresse
        /// </summary>
        public string IpAddress { get; }

        /// <summary>
        /// Ausrüstung端口
        /// </summary>
        public int Port { get; }

        /// <summary>
        /// 初始化Modbus TCP客户端
        /// </summary>
        public ModbusTcpClient(
            string ipAddress,
            int port = 502,
            ILogger<ModbusTcpClient>? logger = null)
        {
            IpAddress = ipAddress ?? throw new ArgumentNullException(nameof(ipAddress));
            Port = port;
            _logger = logger ?? NullLogger<ModbusTcpClient>.Instance;
            _tcpClient = new TcpClient();
        }

        /// <summary>
        /// VerbindungzuAusrüstung
        /// </summary>
        public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("正在VerbindungzuAusrüstung {IpAddress}:{Port}", IpAddress, Port);

                await _tcpClient.ConnectAsync(IpAddress, Port, cancellationToken);

                var factory = new ModbusFactory();
                _modbusMaster = factory.CreateMaster(_tcpClient);

                // 设置超时Zeit
                _modbusMaster.Transport.ReadTimeout = 3000;
                _modbusMaster.Transport.WriteTimeout = 3000;

                _logger.LogInformation("成功VerbindungzuAusrüstung {IpAddress}:{Port}", IpAddress, Port);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "VerbindungAusrüstung {IpAddress}:{Port} 失败", IpAddress, Port);
                return false;
            }
        }

        /// <summary>
        /// Lesen und halten Register
        /// </summary>
        public async Task<ushort[]> ReadHoldingRegistersAsync(
            byte slaveAddress,
            ushort startAddress,
            ushort numberOfPoints,
            CancellationToken cancellationToken = default)
        {
            ValidateConnection();

            try
            {
                _logger.LogDebug(
                    "Lesen und halten Register - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, Anzahl: {NumberOfPoints}",
                    slaveAddress, startAddress, numberOfPoints);

                var result = await Task.Run(() =>
                    _modbusMaster!.ReadHoldingRegisters(slaveAddress, startAddress, numberOfPoints),
                    cancellationToken);

                _logger.LogDebug(
                    "Lesen und halten Register成功 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, Daten: {Data}",
                    slaveAddress, startAddress, result);

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                    "Lesen und halten Register失败 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, Anzahl: {NumberOfPoints}",
                    slaveAddress, startAddress, numberOfPoints);
                throw new ModbusCommunicationException(
                    $"Lesen und halten Register失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 写入单个保持Register.
        /// </summary>
        public async Task WriteSingleRegisterAsync(
            byte slaveAddress,
            ushort registerAddress,
            ushort value,
            CancellationToken cancellationToken = default)
        {
            ValidateConnection();

            try
            {
                _logger.LogDebug(
                    "Schreiben in ein einzelnes Register - Von der Station: {SlaveAddress}, Adresse: {RegisterAddress}, 值: {Value}",
                    slaveAddress, registerAddress, value);

                await Task.Run(() =>
                    _modbusMaster!.WriteSingleRegister(slaveAddress, registerAddress, value),
                    cancellationToken);

                _logger.LogDebug(
                    "Schreiben in ein einzelnes Register成功 - Von der Station: {SlaveAddress}, Adresse: {RegisterAddress}",
                    slaveAddress, registerAddress);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                    "Schreiben in ein einzelnes Register失败 - Von der Station: {SlaveAddress}, Adresse: {RegisterAddress}, 值: {Value}",
                    slaveAddress, registerAddress, value);
                throw new ModbusCommunicationException(
                    $"Schreiben in ein einzelnes Register失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 写入多个保持Register.
        /// </summary>
        public async Task WriteMultipleRegistersAsync(
            byte slaveAddress,
            ushort startAddress,
            ushort[] data,
            CancellationToken cancellationToken = default)
        {
            ValidateConnection();

            try
            {
                _logger.LogDebug(
                    "Schreiben in mehrere Register - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, DatenLänge: {Length}",
                    slaveAddress, startAddress, data.Length);

                await Task.Run(() =>
                    _modbusMaster!.WriteMultipleRegisters(slaveAddress, startAddress, data),
                    cancellationToken);

                _logger.LogDebug(
                    "Schreiben in mehrere Register成功 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}",
                    slaveAddress, startAddress);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                    "Schreiben in mehrere Register失败 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, DatenLänge: {Length}",
                    slaveAddress, startAddress, data.Length);
                throw new ModbusCommunicationException(
                    $"Schreiben in mehrere Register失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// Lesen Sie den Zustand der Spule
        /// </summary>
        public async Task<bool[]> ReadCoilsAsync(
            byte slaveAddress,
            ushort startAddress,
            ushort numberOfPoints,
            CancellationToken cancellationToken = default)
        {
            ValidateConnection();

            try
            {
                _logger.LogDebug(
                    "Lesen线圈 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, Anzahl: {NumberOfPoints}",
                    slaveAddress, startAddress, numberOfPoints);

                var result = await Task.Run(() =>
                    _modbusMaster!.ReadCoils(slaveAddress, startAddress, numberOfPoints),
                    cancellationToken);

                _logger.LogDebug(
                    "Lesen线圈成功 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, Daten: {Data}",
                    slaveAddress, startAddress, result);

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                    "Lesen线圈失败 - Von der Station: {SlaveAddress}, Adresse: {StartAddress}, Anzahl: {NumberOfPoints}",
                    slaveAddress, startAddress, numberOfPoints);
                throw new ModbusCommunicationException(
                    $"Lesen线圈失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 批QuantitätLesen优化
        /// </summary>
        public async Task<Dictionary<ushort, ushort[]>> BatchReadRegistersAsync(
            byte slaveAddress,
            IEnumerable<RegisterReadRequest> requests,
            CancellationToken cancellationToken = default)
        {
            ValidateConnection();

            var results = new Dictionary<ushort, ushort[]>();

            foreach (var request in requests)
            {
                try
                {
                    var data = await ReadHoldingRegistersAsync(
                        slaveAddress,
                        request.StartAddress,
                        request.NumberOfPoints,
                        cancellationToken);

                    results[request.StartAddress] = data;
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex,
                        "批QuantitätLesen gescheitert - Adresse: {StartAddress}, Anzahl: {NumberOfPoints}",
                        request.StartAddress, request.NumberOfPoints);
                    results[request.StartAddress] = Array.Empty<ushort>();
                }
            }

            return results;
        }

        /// <summary>
        /// 断开Verbindung
        /// </summary>
        public void Disconnect()
        {
            try
            {
                _modbusMaster?.Dispose();
                _modbusMaster = null;

                if (_tcpClient.Connected)
                {
                    _tcpClient.Close();
                }

                _logger.LogInformation("已断开与Ausrüstung {IpAddress}:{Port} 的Verbindung", IpAddress, Port);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "断开Verbindung时发生Fehler.");
            }
        }

        /// <summary>
        /// 验证VerbindungStatus
        /// </summary>
        private void ValidateConnection()
        {
            if (!IsConnected || _modbusMaster == null)
            {
                throw new InvalidOperationException("Ausrüstungnicht verbunden");
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    Disconnect();
                    _tcpClient.Dispose();
                }

                _disposed = true;
            }
        }
    }

    /// <summary>
    /// Register.LesenBitte
    /// </summary>
    public record RegisterReadRequest(
        ushort StartAddress,
        ushort NumberOfPoints);
}

2.2 Modbus RTUDie Serie客户端

“`csharp
using NModbus;
using NModbus.Serial;
using System.IO.Ports;

namespace IndustrialAutomation.Modbus.Clients
{
///

/// Modbus RTUDie Serie客户端
///

public class ModbusRtuClient : IModbusClient, IDisposable
{
private readonly ILogger _logger;
private readonly SerialPort _serialPort;
private IModbusMaster? _modbusMaster;
private bool _disposed;

    /// <summary>
    /// Die SerieVerbindungStatus
    /// </summary>
    public bool IsConnected => _serialPort?.IsOpen ?? false;

    /// <summary>
    /// Die SerieName
    /// </summary>
    public string PortName { get; }

    /// <summary>
    /// Porter Rate
    /// </summary>
    public int BaudRate { get; }

    /// <summary>
    /// 初始化Modbus RTU客户端
    /// </summary>
    public ModbusRtuClient(
        string portName,
        int baudRate = 9600,
        ILogger<ModbusRtuClient>? logger = null)
    {
        PortName = portName ?? throw new ArgumentNullException(nameof(portName));
        BaudRate = baudRate;
        _logger = logger ?? NullLogger<ModbusRtuClient>.Instance;

        _serialPort = new SerialPort(portName)
        {
            BaudRate = baudRate,
            DataBits = 8,
            Parity = Parity.None,
            StopBits = StopBits.One,
            ReadTimeout = 1000,
            WriteTimeout = 1000
        };
    }

    /// <summary>
    /// VerbindungzuSerielle Ausrüstung
    /// </summary>
    public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            _logger.LogInformation("正在Öffnen Sie die Serie. {PortName} (Porter Rate: {BaudRate})", PortName, BaudRate);

            await Task.Run(() =>
            {
                if (!_serialPort.IsOpen)
                {
                    _serialPort.Open();
                }
            }, cancellationToken);

            var factory = new ModbusFactory();
            var adapter = new SerialPortAdapter(_serialPort);
            _modbusMaster = factory.CreateRtuMaster(adapter);

            // 配置ModbusParameter
            _modbusMaster.Transport.ReadTimeout = 1000;
            _modbusMaster.Transport.WriteTimeout = 1000;
            _modbusMaster.Transport.Retries = 3;
            _modbusMaster.Transport.WaitToRetryMilliseconds = 100;

            _logger.LogInformation("成功Öffnen Sie die Serie. {PortName}", PortName);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Öffnen Sie die Serie. {PortName} 失败", PortName);
            return false;
        }
    }

    /// <summary>
    /// 扫描Serielle Ausrüstung
    /// </summary>
    public async Task<List<byte>> ScanDevicesAsync(
        byte startAddress = 1,
        byte endAddress = 247,
        CancellationToken cancellationToken = default)
    {
        var foundDevices = new List<byte>();

        _logger.LogInformation("开始扫描Ausrüstung (Adresse范围: {StartAddress}-{EndAddress})", startAddress, endAddress);

        for (byte slaveAddress = startAddress; slaveAddress <= endAddress; slaveAddress++)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                break;
            }

            try
            {
                // 尝试LesenAusrüstung标识
                var result = await Task.Run(() =>
                    _modbusMaster!.ReadDeviceIdentification(slaveAddress, 0x01),
                    cancellationToken);

                if (result != null)
                {
                    foundDevices.Add(slaveAddress);
                    _logger.LogInformation("
Techniken术语(共 7 个)—— Klick auf展开
Modbus RTU基于串行链路的ModbusVereinbarung,使用BinärsystemCodierung和CRC-Test
Modbus TCP基于Ethernet的ModbusVereinbarung变体,使用TCP/IP传输
Register.Modbus Register.存储Daten单元,Unterteilung线圈/离散输入/保持/输入Register.四类
Porter Rate串行Kommunikation每秒传输符Nr.数,Modbus RTU常用9600/19200
Die SerieBerechnung机与外部Ausrüstung进行串行Kommunikation的物理Schnittstelle
线圈Modbus位可读Schreiben von Daten,Adresse从00001开始
保持Register.Modbus 16位可读Schreiben von Daten,Adresse从40001开始
来源/Werkzeuge信息 —— Klick auf展开
来源 Modbus Chinesisches Netzwerk(modbus.cn) —— Inländisch führend.ModbusKommunikationsprotokoll Technologie Gemeinschaft Klassifizierung Modbus Programmierung 字数 11169 字 · 阅读约 28 Unterteilung钟 更新 2026-03-01 永久链接 https://www.modbus.cn/40580.html
Empfohlene Werkzeuge: Modbus Debugger-Assistent WeChat-Applet
Modbus Chinesisches Netzwerk官方推出的Modbus Debugging-Tools,支持 Modbus RTU/TCP 实时KommunikationTests、Register.读写、线圈控制、Daten监控和MeldungUnterteilung析。 keine Installation erforderlich,Mikro-Suche「Modbus DebuggingAssistenten.」Benutzt werden kann.。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
Sollte man diese Informationen für ein echtes Projekt verwenden?

Gehen Sie zum Tool Center, um Nachrichten zu analysieren, CRC-Prüfungen und Geräte-Debugging zu erledigen, oder senden Sie Anforderungen für Auswahl - und Zugangsvorschläge.

Ingenieur Mitglied

Verwandeln Sie diesen Artikel in ein umsetzbares Debuggermaterial

Erweiterte Nachrichtenanalyse, Paket-Downloads, Codebeispiele, Engineering-Szenarien und Priority-Technischer Support sind für die Real-Projekt - Bereitstellung möglich.

Unbegrenzte Werkzeuge
Datenpaket und Codepaket
Vollständige Engineering Case-Basis
Vorrangiger Zugang zum technischen Support

Antwort veröffentlichen

Ihre E-Mail - Adresse wird nicht öffentlich gemacht. Erforderliche Elemente wurden verwendet * markiert.