首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C# + WPF 打造半导体晶圆与石墨岛搬移上位机:从架构设计到工程落地

C# + WPF 打造半导体晶圆与石墨岛搬移上位机:从架构设计到工程落地

原创
作者头像
用户12608867
发布于 2026-09-23 14:53:09
发布于 2026-09-23 14:53:09
770
举报

引言:当上位机进入半导体制造现场

在半导体制造与化合物半导体(如SiC、GaN)外延生长环节中,晶圆(Wafer)与石墨岛(Graphite Island/Susceptor)的搬移是高频、高精度、高洁净度要求的核心工序。这类设备的控制系统通常由下位机(PLC/运动控制卡)执行实时动作,由上位机(HMI/SCADA)负责调度、监控、参数配置与数据追溯。

C# + WPF 凭借其强大的UI表现力、成熟的异步编程模型、良好的硬件通信生态,成为半导体设备上位机开发的主流技术选型之一。本文从专业工程视角,系统拆解一套晶圆与石墨岛搬移上位机的完整设计与实现路径。


一、需求分析:搬移上位机到底要做什么

1.1 工艺背景

在MOCVD、SiC外延等设备中,晶圆通常放置在石墨载盘(Susceptor)的"岛"(Pocket/Island)上。搬移流程涉及:

  • 取片:从Cassette/FOUP中取出晶圆
  • 定位:视觉或机械定位,确保同心度
  • 放置:将晶圆放入石墨岛指定位置
  • 复位:机械手/传输机构回到安全位

1.2 上位机核心功能

功能模块

具体需求

设备通信

与PLC、运动控制卡、机械手、视觉系统通信

流程调度

编排搬移顺序、互锁逻辑、异常处理

实时监控

位置、速度、真空度、温度、报警状态

参数配置

点位示教、速度曲线、真空阈值

数据追溯

每片晶圆的搬移记录、时间戳、结果

权限管理

操作员/工程师/管理员分级

日志与报警

全事件记录、报警分级、历史查询

1.3 关键指标

  • 定位精度:±0.05mm 级(取决于机构)
  • 节拍时间:单次搬移 < 30s(含定位)
  • 可用性:> 99%(7×24 运行)
  • 安全性:碰撞检测、急停、互锁

二、技术选型:为什么是 C# + WPF

2.1 技术栈对比

方案

优势

局限

C# + WPF

UI灵活、生态成熟、开发效率高

非实时,依赖Windows

C++ + Qt

性能强、跨平台

开发周期长

C# + WinForms

简单

UI表现力弱

Web + Electron

跨平台

硬件通信弱

2.2 WPF 的核心优势

  • XAML数据绑定:MVVM模式天然适合设备状态与UI解耦
  • 样式与模板:可定制工业级深色主题、动画反馈
  • 异步支持:async/await 处理通信与UI不阻塞
  • 依赖注入:配合Prism/Microsoft.Extensions.DependencyInjection
  • 图表与可视化:LiveCharts、OxyPlot 实时曲线

2.3 推荐技术栈

text

代码语言:javascript
复制
UI层:WPF + MVVM(CommunityToolkit.Mvvm / Prism)
通信层:S7.Net(西门子)、HslCommunication、Modbus
运动控制:固高/雷赛/ACS 的 .NET SDK
视觉:Halcon/.NET、OpenCvSharp
数据:SQLite(本地)/ SQL Server(MES对接)
日志:Serilog / NLog
DI容器:Microsoft.Extensions.DependencyInjection

三、架构设计:分层与解耦

3.1 整体架构

text

代码语言:javascript
复制
┌─────────────────────────────────────┐
│         Presentation (WPF)          │
│   Views / ViewModels / Converters   │
├─────────────────────────────────────┤
│         Application Layer           │
│   流程编排 / 任务调度 / 状态机       │
├─────────────────────────────────────┤
│         Domain Layer                │
│   设备模型 / 搬移任务 / 报警规则     │
├─────────────────────────────────────┤
│       Infrastructure Layer          │
│  PLC通信 / 运动控制 / 数据库 / 日志  │
└─────────────────────────────────────┘

3.2 MVVM 实践要点

  • ViewModel 不引用 View:通过绑定与命令交互
  • 设备状态用 ObservableObject:属性变更自动刷新UI
  • 命令用 RelayCommand/AsyncRelayCommand:避免UI线程阻塞
  • 服务通过接口注入:IPlcService、IMotionService、IVisionService

3.3 状态机设计

搬移流程本质是一个状态机,推荐使用 Stateless 库:

csharp

代码语言:javascript
复制
var machine = new StateMachine<State, Trigger>(State.Idle);

machine.Configure(State.Idle)
    .Permit(Trigger.StartTransfer, State.Picking);

machine.Configure(State.Picking)
    .Permit(Trigger.PickDone, State.Placing)
    .Permit(Trigger.Error, State.Fault);

machine.Configure(State.Placing)
    .Permit(Trigger.PlaceDone, State.Idle)
    .Permit(Trigger.Error, State.Fault);

状态机的好处:流程可视化、异常可追溯、逻辑可测试。


四、核心模块实现

4.1 通信层:与PLC打交道

以西门子S7为例:

csharp

代码语言:javascript
复制
public interface IPlcService
{
    Task<bool> ConnectAsync(string ip, int rack, int slot);
    Task<short> ReadIntAsync(string address);
    Task WriteBoolAsync(string address, bool value);
    Task<bool> WaitForSignalAsync(string address, bool expected, int timeoutMs);
}

public class S7PlcService : IPlcService
{
    private Plc _plc;

    public async Task<bool> ConnectAsync(string ip, int rack, int slot)
    {
        _plc = new Plc(CpuType.S71200, ip, rack, slot);
        await _plc.OpenAsync();
        return _plc.IsConnected;
    }

    public async Task<bool> WaitForSignalAsync(string address, bool expected, int timeoutMs)
    {
        var sw = Stopwatch.StartNew();
        while (sw.ElapsedMilliseconds < timeoutMs)
        {
            var val = await _plc.ReadAsync(address);
            if ((bool)val == expected) return true;
            await Task.Delay(10);
        }
        return false;
    }
}

关键点:所有通信必须异步,避免阻塞UI;超时必须有明确处理。

4.2 运动控制:点位示教与轨迹

csharp

代码语言:javascript
复制
public interface IMotionService
{
    Task MoveAbsoluteAsync(int axis, double position, double speed);
    Task MoveRelativeAsync(int axis, double distance, double speed);
    Task HomeAsync(int axis);
    double GetPosition(int axis);
    bool IsInPosition(int axis, double target, double tolerance);
}

示教流程:

  1. 工程师手动Jog到目标位
  2. 点击"记录点位",保存到配置文件(JSON)
  3. 运行时读取点位,自动执行

json

代码语言:javascript
复制
{
  "PickPosition": { "X": 120.5, "Y": 80.2, "Z": 10.0, "R": 0 },
  "PlacePosition": { "X": 300.0, "Y": 150.0, "Z": 5.0, "R": 90 }
}

4.3 视觉定位:同心度校正

若配备视觉系统,流程为:

  1. 相机拍照,识别晶圆圆心
  2. 计算与目标位的偏移量(ΔX, ΔY, Δθ)
  3. 将补偿值下发给运动控制
  4. 执行精定位

csharp

代码语言:javascript
复制
public interface IVisionService
{
    Task<VisionResult> LocateWaferAsync();
}

public record VisionResult(double OffsetX, double OffsetY, double OffsetTheta, bool Success);

4.4 流程编排:搬移主逻辑

csharp

代码语言:javascript
复制
public async Task<bool> TransferWaferAsync(CancellationToken ct)
{
    try
    {
        await _stateMachine.FireAsync(Trigger.StartTransfer);

        // 1. 检查安全条件
        if (!await _safetyService.CheckSafeAsync())
            throw new SafetyException("安全条件不满足");

        // 2. 移动到取片位
        await _motionService.MoveAbsoluteAsync(Axis.Z, _points.SafeZ, 50);
        await _motionService.MoveAbsoluteAsync(Axis.X, _points.PickX, 100);
        await _motionService.MoveAbsoluteAsync(Axis.Y, _points.PickY, 100);

        // 3. 真空吸取
        await _ioService.SetVacuumAsync(true);
        if (!await _ioService.WaitVacuumAsync(true, 2000))
            throw new VacuumException("真空建立失败");

        // 4. 视觉定位
        var vision = await _visionService.LocateWaferAsync();
        if (!vision.Success) throw new VisionException("视觉定位失败");

        // 5. 移动到放片位(含补偿)
        await _motionService.MoveAbsoluteAsync(Axis.X, _points.PlaceX + vision.OffsetX, 100);
        await _motionService.MoveAbsoluteAsync(Axis.Y, _points.PlaceY + vision.OffsetY, 100);
        await _motionService.MoveAbsoluteAsync(Axis.Z, _points.PlaceZ, 20);

        // 6. 释放真空
        await _ioService.SetVacuumAsync(false);
        await _ioService.WaitVacuumAsync(false, 2000);

        // 7. 复位
        await _motionService.MoveAbsoluteAsync(Axis.Z, _points.SafeZ, 50);

        await _stateMachine.FireAsync(Trigger.PlaceDone);
        await _traceService.RecordAsync(new TransferRecord { /* ... */ });

        return true;
    }
    catch (Exception ex)
    {
        await _stateMachine.FireAsync(Trigger.Error);
        _logger.Error(ex, "搬移失败");
        await _alarmService.RaiseAsync(ex);
        return false;
    }
}

4.5 数据追溯:每片晶圆都有"身份证"

csharp

代码语言:javascript
复制
public class TransferRecord
{
    public long Id { get; set; }
    public string WaferId { get; set; }
    public string CassetteId { get; set; }
    public int SlotIndex { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime EndTime { get; set; }
    public bool Success { get; set; }
    public double OffsetX { get; set; }
    public double OffsetY { get; set; }
    public string Operator { get; set; }
}

使用SQLite本地存储,支持导出CSV,并可对接MES系统。


五、工程化要点

5.1 安全性设计

  • 急停链路:硬件急停独立于软件
  • 互锁逻辑:门未关、真空未建立、气压不足时禁止动作
  • 软限位:运动范围软件保护
  • 碰撞检测:力矩监控或视觉预警
  • 权限分级:关键参数修改需工程师权限

5.2 异常处理

  • 通信中断:自动重连 + 状态同步
  • 超时处理:每个动作有超时,超时进入故障态
  • 断电恢复:记录当前状态,重启后可恢复
  • 报警分级:提示/警告/故障/紧急,不同处理策略

5.3 性能优化

  • UI刷新:高频数据用定时器批量更新,避免逐条刷新
  • 通信批量:合并读写请求,减少往返
  • 异步不阻塞:所有IO操作async
  • 内存管理:避免频繁GC,复用对象

5.4 日志与诊断

csharp

代码语言:javascript
复制
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day)
    .WriteTo.SQLite("logs/logs.db")
    .CreateLogger();

关键事件:连接、断开、命令下发、状态变化、报警、参数修改。


六、UI设计:工业级WPF界面

6.1 布局原则

  • 主界面:设备状态总览 + 实时动画 + 报警栏
  • 流程图:可视化的搬移流程与当前步骤高亮
  • 参数页:点位示教、速度配置、真空阈值
  • 追溯页:历史记录查询与导出
  • 诊断页:IO状态、通信状态、日志

6.2 实时动画

用WPF的Canvas + Path绘制设备示意图,用绑定控制机械手位置:

xml

代码语言:javascript
复制
<Canvas>
    <Rectangle Width="40" Height="40" Fill="Gray"
               Canvas.Left="{Binding RobotX}"
               Canvas.Top="{Binding RobotY}"/>
    <Ellipse Width="200" Height="200" Stroke="Blue"
             Canvas.Left="{Binding WaferX}"
             Canvas.Top="{Binding WaferY}"/>
</Canvas>

配合Storyboard实现平滑动画。

6.3 深色工业主题

xml

代码语言:javascript
复制
<ResourceDictionary>
    <SolidColorBrush x:Key="BackgroundBrush" Color="#1E1E1E"/>
    <SolidColorBrush x:Key="PanelBrush" Color="#252526"/>
    <SolidColorBrush x:Key="AccentBrush" Color="#007ACC"/>
    <SolidColorBrush x:Key="AlarmBrush" Color="#F44747"/>
</ResourceDictionary>

七、测试与验证

7.1 分层测试

  • 单元测试:状态机、流程逻辑、补偿计算
  • 集成测试:通信Mock、PLC仿真
  • 现场测试:空跑、带片跑、异常注入

7.2 仿真环境

用PLC仿真软件(如PLCSIM)或自建Mock服务,在上位机开发阶段即可验证逻辑,无需真实设备。

csharp

代码语言:javascript
复制
public class MockPlcService : IPlcService
{
    private readonly Dictionary<string, object> _memory = new();

    public Task<short> ReadIntAsync(string address)
        => Task.FromResult((short)(_memory.GetValueOrDefault(address) ?? (short)0));

    public Task WriteBoolAsync(string address, bool value)
    {
        _memory[address] = value;
        return Task.CompletedTask;
    }
}

7.3 验收标准

  • 连续运行72小时无故障
  • 搬移成功率 > 99.5%
  • 定位精度符合工艺要求
  • 异常处理覆盖所有已知故障模式

八、结语:上位机是设备的大脑,也是工艺的守门人

半导体晶圆与石墨岛搬移上位机,表面上是"控制机械手搬东西",实质上是工艺稳定性、数据可追溯性、操作安全性的综合载体。C# + WPF 提供了高效的开发范式,但真正决定系统质量的,是:

  • 对工艺的理解:知道每一步为什么这么做
  • 对异常的敬畏:预判所有可能的失败
  • 对数据的尊重:每一片晶圆都可追溯
  • 对安全的坚守:任何时候人机安全优先

从架构设计到工程落地,从通信协议到UI交互,从状态机到数据追溯——一套专业的上位机,是软件工程与半导体工艺的深度结合。这才是"专业"二字的真正含义。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 引言:当上位机进入半导体制造现场
  • 一、需求分析:搬移上位机到底要做什么
    • 1.1 工艺背景
    • 1.2 上位机核心功能
    • 1.3 关键指标
  • 二、技术选型:为什么是 C# + WPF
    • 2.1 技术栈对比
    • 2.2 WPF 的核心优势
    • 2.3 推荐技术栈
  • 三、架构设计:分层与解耦
    • 3.1 整体架构
    • 3.2 MVVM 实践要点
    • 3.3 状态机设计
  • 四、核心模块实现
    • 4.1 通信层:与PLC打交道
    • 4.2 运动控制:点位示教与轨迹
    • 4.3 视觉定位:同心度校正
    • 4.4 流程编排:搬移主逻辑
    • 4.5 数据追溯:每片晶圆都有"身份证"
  • 五、工程化要点
    • 5.1 安全性设计
    • 5.2 异常处理
    • 5.3 性能优化
    • 5.4 日志与诊断
  • 六、UI设计:工业级WPF界面
    • 6.1 布局原则
    • 6.2 实时动画
    • 6.3 深色工业主题
  • 七、测试与验证
    • 7.1 分层测试
    • 7.2 仿真环境
    • 7.3 验收标准
  • 八、结语:上位机是设备的大脑,也是工艺的守门人
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档