Siemens S7
按地址通过 S7comm,或按变量名通过 S7CommPlus 连接 Siemens S7 PLC:“访问”字段、机架和槽位、存储区、定型的字节/位寻址、变量名、HMI 设置,以及那些原生数据类型。
Siemens S7 驱动通过 S7comm 和 Siemens S7 PLC 对话,也就是承载在 ISO-on-TCP 上的那个经典 Step 7 协议。它用的是绝对寻址,即存储区、数据块号、字节和位,所以不需要从工程项目里导出任何符号表就能工作。在 Connector 里的 Siemens S7 驱动下面添加一台设备,把下面这些字段填上;面板只显示这个协议用得到的那些字段。
以上是按地址访问。每台设备选择自己的访问方式:上面说的按地址,或者按名称,走 S7CommPlus,也就是 TIA Portal 和 Siemens HMI 使用的协议;按名称时,每个点位按 TIA Portal 的写法写出它的变量,类型由 CPU 告知。
访问
| 方面 | 按地址 | 按名称 |
|---|---|---|
| 协议 | ISO-on-TCP 上的 S7comm,端口 102 | ISO-on-TCP 中 TLS 1.3 上的 S7CommPlus,端口 102 |
| CPU | S7-300、S7-400、S7-1200、S7-1500 | 固件 V2.9 或更新的 S7-1500、固件 V4.5 或更新的 S7-1200,并且在 TIA Portal V17 或更新版本中组态 |
| 设备的字段 | 主机、机架 / 槽位 | 主机、用户名和密码,两者都可不填 |
| 点位写的是什么 | 存储区、DB 号、字节和位,以及它的数据类型 | 变量的名称,例如 GanterOpt.Real_;类型由 CPU 告知 |
| CPU 这边 | 允许 PUT/GET,并且数据块不用优化访问(准备 CPU) | 什么都不用改:优化的数据块也能读,也不需要 PUT/GET |
| 设备发现 | 没有 | CPU 的变量(设备发现) |
现在新建的设备从按名称开始。在有这个选项之前保存的设备,照旧按地址读取。切换访问方式时,点位的定型地址和变量名都会保留,所以切回去时一切都在原处。按名称时,设备标题显示的端点不带机架和槽位,例如 s7://192.168.0.2?access=name。不响应按名称访问的 CPU,会在设备页面上说明这一点(没有按名称访问的 CPU)。
连接
| 字段 | 含义 | 默认值 |
|---|---|---|
| 主机 | CPU(或者挡在它前面的那块 CP 模块)的 IP 地址或主机名。 | 空 |
| 访问 | 按地址或按名称(访问)。 | 按名称 |
| 机架 / 槽位 | 仅按地址时。CPU 的机架号和槽位号,按 Siemens 硬件组态里配置的填。同一行上两个数字框:先机架,后槽位。 | 0 / 0 |
| 用户名 / 密码 | 仅按名称时,两者都可不填:密码是 CPU 保护的密码,在它的访问级别要求时填写;用户名只用于管理用户的 CPU。在这台电脑上受保护地保存。 | 空 |
| 轮询间隔(ms) | 整台设备的读取周期,供没有自己另作规定的点位使用。 | 1000 |
TCP 端口固定为 102(ISO-on-TCP),所以没有端口字段。设备标题栏显示拼好的 endpoint,例如 s7://192.168.0.2:0:1(主机、机架、槽位)。
机架和槽位必须和硬件对上:S7-1200 和 S7-1500 的 CPU 在机架 0、槽位 0 或 1 上应答;典型的 S7-300 CPU 坐在机架 0、槽位 2;S7-400 的机架随组态而变。槽位填错会让连接失败,而不是读到错的数据。
每个点位都可以设自己的轮询间隔(ms);点位填 0 就退回设备的间隔。
按名称读取
按名称读取的设备,其点位在“信号源”卡片的变量名字段里按 TIA Portal 的写法写出变量:数据块和变量,成员前面加点,数组元素放在方括号里。TIA Portal 的双引号可以照样输入("GanterOpt".Real_),会被去掉。
| TIA Portal 中的变量 | 变量名 |
|---|---|
数据块 GanterOpt 中的 Real_ |
GanterOpt.Real_ |
UDT 实例 Udt_ 的 Valor |
GanterOpt.Udt_.Valor |
数组 Vetor 的元素 0 |
GanterOpt.Vetor[0] |
DTL DataHora |
GanterOpt.DataHora:一个点位,一个日期时间 |
不用填存储区、DB 号或字节:变量在哪里、是什么类型,都由 CPU 告知,驱动把它读成点位的数据类型:
| CPU 中的类型 | 数据类型 | 说明 |
|---|---|---|
| Bool | Boolean | |
| Byte、USInt;SInt | Byte;SByte | 无符号;有符号 |
| Word、UInt;Int | UInt16;Int16 | 无符号;有符号 |
| DWord、UDInt;DInt | UInt32;Int32 | 无符号;有符号 |
| LWord、ULInt;LInt | UInt64;Int64 | 全部 64 位,精确 |
| Real;LReal | Float;Double | |
| Char、String | String | Windows-1252,和按地址时一样 |
| WChar、WString | String | UTF-16,任何文字 |
| Time、S5Time | Int32 | 毫秒 |
| LTime | Int64 | 纳秒 |
| Time_Of_Day | UInt32 | 从午夜起的毫秒数,小于 24 h |
| Date、Date_And_Time、DTL、LDT | DateTime | 仅日期;日期和时间 |
设备发现给每个点位带上它的变量的数据类型和单位(ms、ns)。手工建的点位用您选的数据类型,CPU 的值会换算成它。
String 或 WString 按块中声明的长度整体写入,驱动在第一次写入前从变量读出这个长度:更长的文本会连同两个长度一起被拒绝,什么也不发送;String 拒绝 Windows-1252 以外的字符。DTL 作为一个日期时间整体读写;它的八个字段从不单独提供,因为单独写一个字段会接受任何值(包括月份 90)。超出类型范围的值(24 h 或以上的 Time_Of_Day,给 Int 的 40000)会连同范围一起被拒绝,什么也不发送。CPU 里没有的名称就是这个点位的错误,并会这样说明;单独写出 DTL 的某个字段,会得到改写 DTL 本身的建议。
HMI 设置
TIA Portal 为数据块的每个变量保存三项设置,在块的列里。站点像 Siemens 自己的 HMI 和 OPC UA 服务器一样遵守它们,不管 CPU 放行什么:
| TIA Portal 中的设置 | 未勾选时 |
|---|---|
| Accessible from HMI/OPC UA/Web API | 这个变量既不读也不写:点位的错误会写出这项设置的名称,设备发现也不列出它。 |
| Visible in HMI engineering | 设备发现不列出这个变量;手工写出它的点位照常读取。 |
| Writable from HMI/OPC UA/Web API | 这个变量只读:写入会被拒绝并写出这项设置的名称,点位的访问提供只读并说明原因,设备发现把它作为只读提供。 |
没有按名称访问的 CPU
接受连接却不响应按名称访问的 CPU(固件 V2.9 之前的 S7-1500、V4.5 之前的 S7-1200、在 V17 之前的 TIA Portal 中组态的项目,或只会 S7comm 的 CPU)会让设备保持离线。设备页面用一条提示代替错误来说明这一点:CPU 需要什么,TIA Portal 在哪里显示固件(CPU 正在运行的在 Online & diagnostics,项目写的版本在 CPU 属性的 General > Catalog information),以及三条出路:
- 升级 CPU 固件,在 TIA Portal 项目中为 CPU 设置相同的版本,并下载硬件组态。只升级固件是不够的。
- 把访问设为按地址,允许 PUT/GET,并让数据块不用优化访问(准备 CPU)。
- 通过 CPU 自己的 OPC UA 服务器(S7-1500,或固件 V4.4 起的 S7-1200)用 OPC UA 驱动读取。
设备的每个点位在自己的页面上也带着同一条提示,CPU 一按名称响应,提示就自动消失。诊断日志和智能体在设备的错误里读到同样的步骤。
准备 CPU
这一节讲的是按地址访问;按名称读取的设备一项设置都不需要。
S7-1200 或 S7-1500 只有在它自己的两项设置都到位时,才响应 S7comm 的绝对寻址。两项都在 TIA Portal 中设置,并下载到 CPU。S7-300 或 S7-400 两项都不需要。
| 设置 | 在 TIA Portal 中的位置 | 没有它时 |
|---|---|---|
| 勾选 Permit access with PUT/GET communication from remote partner | 打开 CPU 的设备组态,选中该 CPU,然后打开 Properties > General > Protection & Security > Connection mechanisms。下载硬件组态(Download to device > Hardware configuration):只下载程序不会带上它。 | CPU 接受连接,但拒绝每一次读和写。设备保持连接,它的点位读作质量不可用。 |
| 在工作站读取的每一个数据块上,取消勾选 Optimized block access | 在项目树的 Program blocks 下右键单击该数据块,然后打开 Properties > General > Attributes。编译该块并下载。之后该块的 Offset 列会显示每个变量的起始位置,也就是点位的起始字节要填的值。 | CPU 不按地址提供该块的任何字节。它的点位读作质量不可用,设备的其他点位照常读取。 |
更改 Optimized block access 会在下载时重新初始化该数据块:其变量回到起始值。标志位存储区(M)、输入(I)和输出(Q)始终可以寻址,无需更改。必须保持优化的数据块可以换一种方式读取:由 PLC 程序把工作站要读的值复制到一个未优化的数据块或标志位存储区,点位指向那里;或者由工作站通过 PLC 自带的 OPC UA 服务器(S7-1500;固件 4.4 起的 S7-1200),用 OPC UA 驱动来读。
当 CPU 因为其中任何一项设置而拒绝时,设备页面会用一条提示说明是哪一项,并附上这些步骤;CPU 一接受,这条提示就会自行消失。对于数据块,提示会列出该块以及因此读不到值的点位。诊断日志和代理读到的是同样的步骤。CPU 中没有的数据块,以及超出数据块末尾的地址,会在指向它们的点位上照实说明。
寻址
这一节和后面两节(数据类型、写入)讲的是按地址访问;按名称访问见按名称读取。
S7 点位是靠定型字段寻址的,不是靠一串自由文本。面板把它们放在点位的“信号源”卡片里:
| 字段 | 含义 | 接受的取值 | 默认值 |
|---|---|---|---|
| 存储区 | 要读的存储区。 | DataBlock、Merker、ProcessInput、ProcessOutput、Timer、Counter |
DataBlock |
| DB 编号 | 哪一个数据块,只在“区域”是 DataBlock 时显示。 |
0 及以上 | 1 |
| 起始字节 | 值在这个区域里从哪个字节偏移开始。在 Timer 和 Counter 区域里,这个框改标为定时器编号或计数器编号,问的是那个定时器或计数器的编号。 |
0 及以上 | 0 |
| 位号(0–7) | 起始字节里的位位置。只对布尔点位显示。 | 0–7 | 0 |
| 最大长度(留空为 254) | 一个 S7 STRING 或 WSTRING 声明的最大长度,按字符计。只对 Timer 和 Counter 之外的文本点位显示。 |
STRING 为 1–254,WSTRING 为 1–16382,或留空 | 留空 |
| PLC 中的字符串类型 | 文本在块里声明的类型,与长度并列:STRING(每个字符一个字节,Windows-1252)或 WSTRING(每个字符两个字节,UTF-16,任何文字都能容纳)。只在显示最大长度的地方显示。 |
STRING、WSTRING |
STRING |
这些区域对应到 Siemens 常用的记法:Merker 是标志位存储区(M),ProcessInput 是过程映像输入(I/E),ProcessOutput 是过程映像输出(Q/A),Timer/Counter 是 S7-300 和 S7-400 CPU 的定时器和计数器区。定时器和计数器按编号寻址,不按字节:Timer 填编号 5 读的是 T5,Counter 填编号 3 读的是 C3。把经典的绝对地址翻过来是这样:
| 经典地址 | 数据类型 | 要填的字段 |
|---|---|---|
存着 REAL 的 DB5.DBD12 |
Float | 区域 DataBlock,DB 号 5,起始字节 12 |
DB1.DBX3.4 |
Boolean | 区域 DataBlock,DB 号 1,起始字节 3,位 4 |
存着 INT 的 DB2.DBW20 |
Int16 | 区域 DataBlock,DB 号 2,起始字节 20 |
MW10 |
Int16 | 区域 Merker,起始字节 10 |
M10.3 |
Boolean | 区域 Merker,起始字节 10,位 3 |
IB2 |
Byte | 区域 ProcessInput,起始字节 2 |
Q4.1 |
Boolean | 区域 ProcessOutput,起始字节 4,位 1 |
T5 |
Int16 | 区域 Timer,定时器号 5 |
C3 |
Int16 | 区域 Counter,计数器号 3 |
布尔点位在总线上恰好读写一个位;它绝不会把周围那个字节重写一遍。其余每一种类型都从起始字节开始按字节寻址,宽度就是它数据类型的确切宽度。“信号源”卡片里那行只读的源地址(总线)会随着你编辑显示拼好的地址。
数据类型
点位的数据类型决定总线上那个 S7 原生类型。十三种 S7 原生宽度全都可用:
| 数据类型 | S7 类型 | 总线上的大小 |
|---|---|---|
| Boolean | BOOL | 1 位 |
| SByte | SINT | 1 字节 |
| Byte | USINT | 1 字节 |
| Int16 | INT | 2 字节 |
| UInt16 | UINT | 2 字节 |
| Int32 | DINT | 4 字节 |
| UInt32 | UDINT | 4 字节 |
| Int64 | LINT | 8 字节 |
| UInt64 | ULINT | 8 字节 |
| Float | REAL | 4 字节 |
| Double | LREAL | 8 字节 |
| String | STRING 或 WSTRING | 最大长度 + 2 字节(STRING),最大长度 × 2 + 4 字节(WSTRING) |
| DateTime | DTL | 12 字节 |
多字节的值自动采用 S7 原生的大端字节序;没有字节序选项,因为根本用不着。
文本点位读的是标准的 S7 STRING 布局:一个字节的声明最大长度,一个字节的当前长度,然后是字符,每个字符一个字节,采用 Windows-1252,也就是 TIA Portal 和 Siemens HMI 显示 STRING 时用的代码页。所以工作站写入的内容就是 TIA Portal 和 HMI 显示的内容("Peça 12" 仍是 "Peça 12"),工作站读回来的也一样。最大长度按字符数计,必须和块里的 STRING 声明对上(留空表示 S7 的最大值 254);驱动每次读传输的是最大长度 + 2 个字节。日期时间点位映射到 S7-1200/1500 系列的 DTL 结构(从年一直到纳秒);较老的 8 字节 DATE_AND_TIME 不提供。
PLC 中的字符串类型为 WSTRING 的文本点位改读 S7 WSTRING 布局:一个字的声明最大长度,一个字的当前长度,然后是字符,每个字符两个字节,采用 UTF-16,所以任何文字都能容纳("中" 写进去,读回来仍是 "中")。最大长度仍按字符数计,从 1 到 16382,必须和块里的 WString 声明对上(留空表示 254,即 TIA Portal 给不带长度声明的 WString 的长度);驱动每次读传输的是最大长度 × 2 + 4 个字节。S7comm 无法从 CPU 读出类型,所以它必须和变量一致:对着 WString 变量却仍设为 STRING 的点位,会按错误的布局读写。这个字段出现之前保存的点位都是 STRING。
写入
访问为读写或只写的点位可以被写。写入寻的是和读一样的区域、字节和位:布尔写入置它那一个位,其余一切都写它类型确切的那些字节。新点位一开始是只读。
文本写入如果需要的字节数超过最大长度,就会被拒绝,什么也不会发送,绝不会被截短到合适的大小:诊断日志和智能体读到的是,例如 "The DB1 byte 44 write was not sent: the text takes 21 bytes, and the STRING holds 20."。长度正好等于最大长度的文本会被完整写入。
含有 Windows-1252 之外字符(例如汉字)的文本写入也会这样被拒绝,绝不会用问号代替该字符写进去:诊断日志和智能体读到的是,例如 "The DB1 byte 44 write was not sent: the STRING holds Windows-1252 characters only, and '中' (U+4E2D) is not one of them; it fits once the tag's text type in the PLC and the PLC variable are both WSTRING."。点位的面板会用工作站的语言给出同样的原因。
要写这样的文本,请在块里把变量声明为 WString,并把点位的PLC 中的字符串类型设为 WSTRING。WSTRING 每个字符按两个字节计,所以超过其最大长度的文本同样会被拒绝,什么也不会发送:例如 "The DB1 byte 94 write was not sent: the text takes 42 bytes, and the WSTRING holds 40 (20 characters of two bytes)."。
设备发现
按名称读取的 CPU 会列出它的变量;S7comm 什么都不列,广播也找不到 CPU。在驱动页面上,扫描范围卡片里的要扫描的 CPU指定是哪台 CPU:本驱动下按名称读取其 CPU 的一台 Siemens 设备(在这台设备的主机上扫描,并用它的密码登录,受密码保护的 CPU 就是这样列出变量的),或者在此输入的地址,CPU 的地址填在 CPU 地址里。
发现设备把这台 CPU 作为一台设备提供,变量作为点位:提供的是 CPU 标为可从 HMI 访问且可见的变量,全部已勾选,带着 CPU 告知的类型,CPU 标为不可从 HMI 写入的是只读。列表是按每个名称的路径排成的树:数据块,然后是每个结构体或 UDT 实例和每个数组,然后是变量,每个以名称中不与其他变量重复的最短结尾命名(Real_、Valor、Vetor[0])。勾选一个分支会勾选或取消勾选它下面的全部内容,分支上显示它的变量中有几个已勾选;一个 DTL 就是一个变量。添加设备用勾选的点位新建一台按名称读取的设备。
本站点已有 Siemens 设备按名称读取的 CPU,不管扫描是怎么指定的,就是那台设备:扫描用那台设备的密码登录,添加所选点位添加它还没有点位的变量。在按名称读取的设备页面上,点位卡片里的发现点位用同样的树只对这台设备做同样的事(见设备发现)。按地址读取的设备不提供发现点位:它的点位请手工添加。
需要知道的事
- 定时器和计数器区只存在于 S7-300 和 S7-400 的 CPU 上。S7-1200 没有这两个区,S7-1500 即使允许了 PUT/GET,也会以“Address out of range”拒绝通过 S7comm 读写这两个区;这时请在 PLC 程序里把定时器或计数器的值复制到一个数据块或标志位存储区,再从那里读。在有这两个区的 CPU 上,它们按编号寻址,不按字节偏移:那个框问的是定时器或计数器本身(T0、T1、T2 和 C0、C1、C2)。每个值是一个 16 位字,所以要配 Int16;更宽或更窄的数据类型会被拒绝,点位名写进诊断日志,而这台设备其他的点位照读不误。
- 一台够不着的 PLC 在启动时不花什么代价:设备在后台一直重试,在连接接上之前它的点位读作质量不可用。
- 设备上线之后被拔掉的线缆,在下一次读取时被发现:设备转为离线,它的点位转为质量不可用,等网络回来它自己重新连上。CPU 拒绝的一个地址不会造成这种局面,所以一个打错的点位绝不会把这台设备其余部分一起拖垮。读取时发现链路已断的点位,用工作站的语言说明与设备的连接已断开,Sharp7 的原话留在事件页面。