七天学会PLC 从零打通 TIA Portal Openness:环境配置、连接博图到自动生成 工程代码
七天学会 PLC 上位机到机器视觉:利用 Openness 与人工智能生成工程代码
从零打通 TIA Portal Openness:环境配置、连接博图到自动生成 SCL / 梯形图程序(V18 实战)
标签:#TIA Openness #西门子 PLC #S7-1200 #C# 二次开发 #PLC 自动编程 #博图自动化
前言
如果觉得看文档不直观,可以bibi查看配套视频,操作演示
当下工业自动化、机器视觉、AI 融合开发已成主流趋势,很多开发者希望打通上位机、PLC、人工智能全链路。西门子 TIA Portal 作为工业领域主流编程软件,手动编写 PLC 程序效率低、重复性工作多。
本文基于 TIA Portal V18 + S7-1200 + PLCSIM 仿真 实战,手把手教你使用 C# 结合 TIA Portal Openness 官方.NET API,实现自动连接博图、离线切换、批量生成 SCL / 梯形图代码。全文代码全部实测可用,汇总海量踩坑问题,不管是 PLC 上位机开发、自动化工程批量部署,还是结合 AI 自动生成 PLC 工程代码,都能直接拿来落地,也是从 PLC 开发进阶到机器视觉 + AI 融合项目的必备技能。
一、什么是 Openness?纠正 90% 新手的认知误区
TIA Portal Openness 是西门子官方推出的 .NET 接口套件,核心作用是用代码自动化操控博图(TIA Portal)软件,支持新建项目、添加硬件设备、生成程序块、编译、导入导出、程序下载等全流程操作,是实现 PLC 工程自动化、AI 生成代码的核心工具。
很多初学者极易混淆 Openness 与 PLC 通信协议,这里用表格清晰区分:
表格
| 业务场景 | 对应技术方案 |
|---|---|
| 自动化操作博图、新建项目、编写程序、编译下载 | ✅ TIA Portal Openness |
| 博图程序下载、在线连接 PLCSIM / 物理 PLC | ✅ Openness 内置 DownloadProvider / OnlineProvider |
| 读写 PLC 实时变量、DB 块数据、在线监控 | ❌ 非 Openness,推荐 Sharp7、S7netPlus、OPC UA |
核心总结:Openness 操作的是博图软件与离线工程文件,而非直接操控运行状态下的 PLC 硬件;它读取的设备信息,是工程内组态数据,不是仿真 / 真机的实时运行数据。
二、环境与前置条件(缺一不可,配置错一步直接报错)
本次实战固定版本组合,兼容性最佳,所有组件必须严格匹配:
表格
| 软件 / 组件 | 版本 & 要求 | 补充说明 |
|---|---|---|
| TIA Portal | V18(自带 Openness 组件) | 安装博图时默认勾选 Openness,无需额外单独安装 |
| 开发工具 | Visual Studio 2022 | 新建控制台项目即可,无需复杂窗体 |
| .NET 运行库 | .NET Framework 4.8 | V18 专属适配版本,4.7.2 及以下大概率加载 DLL 失败 |
| 核心 DLL | Siemens.Engineering.dll | 路径:C:\Program Files\Siemens\Automation\Portal V18\PublicAPI\V18\ |
| Windows 权限 | 当前用户加入 Siemens TIA Openness 用户组 |
头号报错根源,未添加会直接提示拒绝访问 |
2.1 关键配置:将用户加入 Openness 用户组
这是入门第一道关卡,提供两种配置方式,任选其一即可,配置完成必须注销并重新登录系统,否则不生效。
方式 1:图形界面操作(适合新手)
- 按下
Win + R,输入lusrmgr.msc打开本地用户和组; - 左侧选择组,双击
Siemens TIA Openness; - 点击添加,选中当前 Windows 登录账号,确认保存;
- 注销电脑,重新登录。
方式 2:PowerShell 命令行(管理员模式,高效快捷)
以管理员身份打开 PowerShell,执行以下命令:
powershell
# 将当前用户加入Openness用户组
net localgroup "Siemens TIA Openness" "$env:USERNAME" /add
# 查看组成员,验证是否添加成功
net localgroup "Siemens TIA Openness"
执行完毕后,同样需要注销重登。
三、创建项目并引用 Openness 依赖
- 打开 Visual Studio 2022,新建 .NET Framework 4.8 控制台应用;
- 手动引用
Siemens.Engineering.dll,重点配置属性:Private=False(禁止复制 DLL 到运行目录,程序自动从系统注册表解析路径)。
3.1 项目配置文件 .csproj 核心代码
xml
<Reference Include="Siemens.Engineering">
<HintPath>C:\Program Files\Siemens\Automation\Portal V18\PublicAPI\V18\Siemens.Engineering.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
3.2 App.config 指定运行时版本
xml
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
四、核心难点:程序集解析 AssemblyResolve
Siemens.Engineering.dll 不会复制到程序运行目录,.NET 运行时会找不到程序集导致崩溃。解决方案:注册 AssemblyResolve 事件,从系统注册表精准匹配对应版本 DLL。
踩坑提醒:电脑可能存在多个博图版本(V15.1/V16/V17/V18),必须按请求版本精确匹配,强行加载低版本 DLL 会触发
TypeLoadException类型加载异常。
4.1 完整程序集解析代码
csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Linq;
using Microsoft.Win32;
namespace TIAOpennessDemo
{
class Program
{
static void Main(string[] args)
{
// 优先注册解析事件(必须在调用Openness类型之前)
AppDomain.CurrentDomain.AssemblyResolve += OpennessAssemblyResolver;
// 执行核心业务逻辑
RunOpennessTest();
}
/// <summary>
/// 从注册表精准加载对应版本的Openness程序集
/// </summary>
private static Assembly OpennessAssemblyResolver(object sender, ResolveEventArgs args)
{
var requested = new AssemblyName(args.Name);
string assemblyName = requested.Name;
Version requestedVersion = requested.Version;
if (!assemblyName.StartsWith("Siemens.Engineering", StringComparison.OrdinalIgnoreCase))
return null;
// 读取64位注册表
using (RegistryKey baseKey = RegistryKey
.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey(@"SOFTWARE\Siemens\Automation\Openness"))
{
if (baseKey == null) return null;
var candidates = new List<KeyValuePair<Version, string>>();
// 遍历所有Openness版本
foreach (string versionName in baseKey.GetSubKeyNames())
{
using (RegistryKey publicApiKey = baseKey.OpenSubKey(versionName + @"\PublicAPI"))
{
if (publicApiKey == null) continue;
foreach (string apiVersion in publicApiKey.GetSubKeyNames())
{
using (RegistryKey asmKey = publicApiKey.OpenSubKey(apiVersion))
{
string path = asmKey?.GetValue(assemblyName) as string;
if (string.IsNullOrEmpty(path) || !File.Exists(path)) continue;
Version.TryParse(apiVersion, out Version v);
candidates.Add(new KeyValuePair<Version, string>(v ?? new Version(0, 0), path));
}
}
}
}
if (candidates.Count == 0) return null;
// 优先精确匹配版本,无匹配则选用最高版本
string chosenPath =
candidates.FirstOrDefault(c => requestedVersion != null && c.Key == requestedVersion).Value
?? candidates.OrderByDescending(c => c.Key).First().Value;
return Assembly.LoadFrom(chosenPath);
}
}
}
}
关键规则:AssemblyResolve 事件必须最先注册,所有使用 Openness 类型的代码单独封装方法,避免 JIT 提前加载 DLL 报错。
五、连接博图:附加到正在运行的 TIA Portal 实例
实战最常用方式:直接附加到已打开的博图进程,无需后台静默启动软件。通过 TiaPortal.GetProcesses() 扫描本地博图实例,再执行附加连接。
5.1 连接博图 + 读取项目设备代码
在上述代码中补充 RunOpennessTest 方法、递归遍历设备工具方法:
csharp
using Siemens.Engineering;
using Siemens.Engineering.Device;
/// <summary>
/// 核心入口:附加博图、读取项目与设备
/// </summary>
private static void RunOpennessTest()
{
var processes = TiaPortal.GetProcesses();
Console.WriteLine($"检测到 {processes.Count} 个博图运行实例");
if (processes.Count == 0)
{
Console.WriteLine("请先手动打开 TIA Portal V18!");
return;
}
foreach (var process in processes)
{
using (TiaPortal tia = process.Attach())
{
Console.WriteLine("✅ 成功附加到博图实例,Openness连接正常");
var project = tia.Projects.FirstOrDefault();
if (project == null)
{
Console.WriteLine("当前博图无打开项目");
continue;
}
Console.WriteLine($"当前项目名称:{project.Name}");
Console.WriteLine($"项目设备总数:{project.Devices.Count}");
// 遍历所有设备
foreach (Device device in project.Devices)
{
Console.WriteLine($"\n设备名称:{device.Name} 设备类型:{device.TypeIdentifier}");
foreach (var item in EnumerateDeviceItems(device))
{
Console.WriteLine($" - {item.Name} 【{item.Classification}】 {item.TypeIdentifier}");
}
// 查找PLC程序容器、切换离线、生成代码
var plcSoftware = FindPlcSoftware(project);
if (plcSoftware != null)
{
GoOfflineIfNeeded(project);
GenerateMotorControlScl(plcSoftware);
project.Save();
Console.WriteLine("✅ 项目已保存,程序块生成完成");
}
}
}
}
}
/// <summary>
/// 递归遍历设备下所有硬件模块
/// </summary>
private static IEnumerable<DeviceItem> EnumerateDeviceItems(Device device)
{
foreach (DeviceItem item in device.DeviceItems)
{
yield return item;
foreach (var child in EnumerateDeviceItems(item))
yield return child;
}
}
private static IEnumerable<DeviceItem> EnumerateDeviceItems(DeviceItem parent)
{
foreach (DeviceItem item in parent.DeviceItems)
{
yield return item;
foreach (var child in EnumerateDeviceItems(item))
yield return child;
}
}
5.2 运行说明
- 手动打开 TIA Portal V18 并新建 / 打开一个 S7-1200 项目;
- 启动 C# 控制台程序,首次附加会弹出博图安全确认框,点击「允许」即可;
- 控制台正常输出设备、CPU 型号、接口等信息,代表连接成功。
六、定位 PLC 程序容器 PlcSoftware
所有 PLC 程序块、变量表、外部源都挂载在 PlcSoftware 下,通过 SoftwareContainer 服务遍历获取:
csharp
using Siemens.Engineering.Services;
using Siemens.Engineering.SW;
/// <summary>
/// 从项目中查找PLC程序容器
/// </summary>
private static PlcSoftware FindPlcSoftware(Project project)
{
foreach (Device device in project.Devices)
{
foreach (DeviceItem item in EnumerateDeviceItems(device))
{
var container = item.GetService<SoftwareContainer>();
if (container != null && container.Software is PlcSoftware plc)
return plc;
}
}
return null;
}
七、必做操作:在线转离线(修改程序硬性要求)
高频报错点:博图处于在线(连接 PLCSIM / 真机)状态时,禁止修改程序、生成代码,会抛出 This function is not supported in online mode。
解决方案:代码自动检测在线状态,并切换至离线模式:
csharp
using Siemens.Engineering.Online;
/// <summary>
/// 自动将在线设备切换为离线
/// </summary>
private static void GoOfflineIfNeeded(Project project)
{
foreach (Device device in project.Devices)
{
foreach (DeviceItem item in EnumerateDeviceItems(device))
{
OnlineProvider op = item.GetService<OnlineProvider>();
if (op != null && op.State != OnlineState.Offline)
{
Console.WriteLine($"设备 {item.Name} 处于在线状态,正在切换离线...");
op.GoOffline();
}
}
}
}
八、自动生成 PLC 程序:SCL 与 梯形图 (LAD) 实战
Openness 生成代码分为两种方案,SCL 语法简单、稳定性高,优先推荐入门与 AI 代码生成场景;梯形图基于 XML 格式,结构复杂,适合需要可视化梯形图的场景。
8.1 推荐方案:SCL 语言(外部源生成,最简方案)
利用外部源文件 (External Source),直接编写标准 SCL 文本,由博图自动编译为程序块。案例:电机正反转互锁控制逻辑(工业经典案例)。
csharp
using Siemens.Engineering.SW.ExternalSources;
/// <summary>
/// 自动生成电机正反转SCL程序块
/// </summary>
private static void GenerateMotorControlScl(PlcSoftware plc)
{
const string blockName = "MotorControl_FwdRev";
string srcDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "src");
Directory.CreateDirectory(srcDir);
string sclFile = Path.Combine(srcDir, blockName + ".scl");
// 标准SCL代码:电机正反转+自锁+互锁
string sclCode =
$"FUNCTION \"{blockName}\" : Void\r\n" +
"{ S7_Optimized_Access := 'TRUE' }\r\n" +
"VERSION : 0.1\r\n" +
"\r\n" +
"BEGIN\r\n" +
" // I0.0正转启动、I0.1反转启动、I0.2停止\r\n" +
" // Q0.0正转输出、Q0.1反转输出,双向互锁\r\n" +
" %Q0.0 := (%I0.0 OR %Q0.0) AND NOT %I0.2 AND NOT %Q0.1;\r\n" +
" %Q0.1 := (%I0.1 OR %Q0.1) AND NOT %I0.2 AND NOT %Q0.0;\r\n" +
"END_FUNCTION\r\n";
// 写入SCL文件(UTF-8编码)
File.WriteAllText(sclFile, sclCode, new UTF8Encoding(true));
// 删除旧文件,避免重复报错
var oldSource = plc.ExternalSourceGroup.ExternalSources.Find(blockName);
oldSource?.Delete();
// 创建外部源并编译生成程序块
PlcExternalSource source = plc.ExternalSourceGroup.ExternalSources.CreateFromFile(blockName, sclFile);
var result = source.GenerateBlocksFromSource(GenerateBlockOption.KeepOnError);
Console.WriteLine($"\n共生成 {result.Count} 个程序对象:");
foreach (var obj in result)
{
if (obj is PlcBlock blk)
Console.WriteLine($"✅ 程序块:{blk.Name} 编程语言:{blk.ProgrammingLanguage}");
}
}
运行后,博图项目的程序块目录下会自动出现 MotorControl_FwdRev 功能块,编译、调用即可运行。该方案非常适合对接 AI 大模型:AI 生成 SCL 文本 → 代码写入文件 → Openness 自动编译为 PLC 程序。
8.2 进阶方案:梯形图 LAD(FlgNet XML)
梯形图依赖 FlgNet 格式 XML 描述触点、线圈、连线,格式复杂,不建议手写。最佳流程:
- 在博图中手动绘制一段梯形图;
- 使用
Export接口导出 XML 模板; - 基于模板动态拼接 XML,再通过
Import导入生成梯形图。
基础 XML 模板(常开触点 + 线圈)
xml
<FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v1">
<Parts>
<Access Scope="GlobalVariable" UId="21"><Symbol><Component Name="Start"/></Symbol></Access>
<Access Scope="GlobalVariable" UId="22"><Symbol><Component Name="Lamp"/></Symbol></Access>
<Part Name="Contact" UId="23"/>
<Part Name="Coil" UId="24"/>
</Parts>
<Wires>
<Wire UId="25"><Powerrail/><NameCon UId="23" Name="in"/></Wire>
<Wire UId="26"><IdentCon UId="21"/><NameCon UId="23" Name="operand"/></Wire>
<Wire UId="27"><NameCon UId="23" Name="out"/><NameCon UId="24" Name="in"/></Wire>
<Wire UId="28"><IdentCon UId="22"/><NameCon UId="24" Name="operand"/></Wire>
</Wires>
</FlgNet>
导出 / 导入核心代码
csharp
// 导出现有梯形图为XML模板
block.Export(new FileInfo("lad_temp.xml"), ExportOptions.WithDefaults);
// 导入XML生成梯形图程序块
plcSoftware.BlockGroup.Blocks.Import(new FileInfo("lad_temp.xml"), ImportOptions.Override);
注意:XML 命名空间、版本随博图版本变化,务必以本机导出的模板为准。
九、常见报错速查表(排错必备)
表格
| 报错信息 | 根因 | 解决方案 |
|---|---|---|
| UnauthorizedAccessException 拒绝访问 | 用户未加入 Siemens TIA Openness 组 |
添加用户组,注销重登 |
| TypeLoadException 加载类型失败 | 加载了低版本 DLL(V15.1 等) | 优化 AssemblyResolve,按版本精准匹配 |
| This function is not supported in online mode | 设备处于在线状态 | 执行 GoOffline () 切换离线 |
| 梯形图触点显示??? | XML 中操作数 / 地址配置错误 | 导出原生梯形图模板,仿写格式 |
| 找不到 Siemens.Engineering 程序集 | 未注册 AssemblyResolve 事件 | 程序入口优先注册解析事件 |
| 程序附加后卡死不动 | 博图弹出权限确认框 | 切换到博图,点击「允许」 |
十、完整业务工作流(PLC+AI + 机器视觉通用流程)
结合 Openness、AI 生成代码、机器视觉项目,整理全链路标准流程:
- 环境准备:安装 TIA Portal V18、VS2022、.NET4.8,配置用户组权限;
- 项目搭建:创建.NET4.8 控制台项目,引用 DLL 并配置
Private=False; - 程序集解析:注册
AssemblyResolve事件,从注册表加载 DLL; - 连接博图:扫描并附加本地博图进程,读取项目与硬件设备;
- 状态切换:检测 PLC 设备状态,自动切换为离线模式;
- 代码生成:对接 AI 生成 SCL 文本 / 拼接 LAD-XML,自动生成程序块;
- 项目保存:调用 Save () 保存工程文件;
- 调试运行:切换在线模式,下载程序到 PLCSIM / 物理 PLC,联动机器视觉设备调试。
十一、拓展:对接人工智能与机器视觉落地思路
本文实现了Openness 自动生成 PLC 代码的基础能力,在此之上可快速拓展为 AI+PLC + 机器视觉一体化方案:
- AI 生成 PLC 代码:通过大模型接收业务需求(如视觉分拣、定位逻辑),自动输出标准 SCL 代码;
- 代码自动落地:C# 程序接收 AI 返回的 SCL 文本,调用 Openness 写入博图生成程序块;
- 全链路联动:机器视觉相机采集图像 → 上位机算法处理 → 下发指令至 PLC → PLC 驱动执行机构动作。
该方案大幅减少人工编程工作量,也是工业智能化项目的主流开发方向。
结语
本文基于 TIA Portal V18 完成了 Openness 从环境配置、进程连接、离线切换到自动生成 SCL / 梯形图的全流程实战,所有代码经过真机 + 仿真验证。掌握这套技术,不仅能实现 PLC 工程自动化,更是打通PLC 上位机、人工智能、机器视觉三大技术栈的关键一步。
后续大家可基于本文代码拓展:批量创建工程、自动组态硬件、一键编译下载、AI 智能生成复杂控制逻辑等功能。如果在配置、代码调试、AI 对接过程中遇到问题,欢迎留言交流。
原创不易,欢迎点赞 + 收藏 + 关注,持续分享工业自动化、PLC 二次开发、机器视觉实战教程!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)