又一次成为懒蛋了,标题就这么改了改又是一篇新文章。数据库
网上也有不少S7comm协议的解析,但仍是如同我上一篇同样我只是作报文的解析对于S7comm的原理并进行阐述。编程
有些地方有错误的地方尽请你们指出,共同进步。编程语言
好了,言归正题。咱们开始吧。函数
我仍是按照功能码的顺序进行介绍吧。测试
TPKT层和COTP层我也很少作介绍了,有兴趣的能够本身去了解。今天咱们主要是解析S7comm这一层。编码
功能码附录:spa
0x00 CPU services CPU服务操作系统
0xf0 Setup communication 创建通讯3d
0x04 Read Var 读取值调试
0x05 Write Var 写入值
0x1a Request download 请求下载
0x1b Download block 下载块
0x1c Download ended 下载结束
0x1d Start upload 开始上传
0x1e Upload 上传
0x1f End upload 上传结束
0x28 PI-Service 程序调用服务
0x29 PLC Stop 关闭PLC
发包
咱们来先看Header头部分。
Byte[0] 32 为协议ID 通常指定为0x32
Byte[1] 01 为 PDU类型 通常有0x01 Job 主设备发起请求 0x02 Ack 确认响应 0x03 Ack_data 确认数据响应通常做为确认0x01的请求 0x07 USERDATA 协议的扩展,参数字段包含请求/响应ID
Byte[2]Byte[3] 00 00冗余数据,一般为0×0000
Byte[4]Byte[5] 3e 02协议数据单元的参考、经过请求事件增长
Byte[6]Byte[7] 00 08参数的总长度也就是parameter的长度
Byte[8]Byte[9] 00 00数据的长度、也就是data部分数据的长度若是无即为0
继续看Parmeter部分。
根据上面的length得知,咱们的Parameter部分应该是8个位,数一数看看是否是8位
Byte[0] f0 为PDU的类型也就是功能码
Byte[1] 00 冗余数据,一般为0×0000
Byte[2] Byte[3] 发送链接请求
Byte[4] Byte[5] 发送通讯请求
Byte[6] Byte[7] 协商的PDU长度
回包
红框内跟发包是同样的,就再也不描述了。
从Error Class开始。
Byte[10] 00 为错误类型 、错误类型也有不少种、如下是错误类型附录。
0x00 No error 没有错误
0x81 Application relationship 应用关系
0x82 Object definition 对象定义
0x83 No resources available 没有可用资源
0x84 Error on service processing 服务处理中错误
0x85 Error on supplies 请求错误
0x87 Access error 访问错误
Byte[11] 00 为错误码 文章最后会附录一下所有错误码(很长不贴在这里了,搜索 附录一)
这里能够理解为 错误类型规定错误的大致方向而错误码规定错误的具体事件。
接下来咱们看Parameter这一部分
能够看出跟发包是彻底同样的,仍是那句话百变不离其宗,协议嘛逃脱不了一发一收对吧。
Byte[0] f0 为PDU的类型也就是功能码
Byte[1] 00 冗余数据,一般为0×0000
Byte[2] Byte[3] 确认链接请求
Byte[4] Byte[5] 确认通讯请求
Byte[6] Byte[7] 协商的PDU长度
发包
Header头部与以前都同样的再也不描述了
咱们直接看Parameter部分吧。
Byte[0] 04 功能码
Byte[1] 01 表明了Item的个数 为1 即为 一个
再继续往下扒。
Item部分
Byte[0] 12 结构标识一般都为0x12,表明变量规范
Byte[1] 0a 长度规范、自此日后的长度
Byte[2] 10 IDS的地址规范的格式类型常见值如下表
0x10 S7ANY Address data S7-Any pointer-like DB1.DBX10.2
0x13 PBC-R_ID R_ID for PBC
0x15 ALARM_LOCKFREE Alarm lock/free dataset
0x16 ALARM_IND Alarm indication dataset
0x19 ALARM_ACK Alarm acknowledge message dataset
0x1a ALARM_QUERYREQ Alarm query request dataset
0x1c NOTIFY_IND Notify indication dataset
0xa2 DRIVEESANY seen on Drive ES Starter with routing over S7
0xb2 1200SYM Symbolic address mode of S7-1200
0xb0 DBREAD Kind of DB block read, seen only at an S7-400
0x82 NCK Sinumerik NCK HMI access
Byte[3] 02 为数据传输的大小、常见值如下表
0 NULL
3 BIT bit access, len is in bits
4 BYTE/WORD/DWORD byte/word/dword access, len is in bits
5 INTEGER integer access, len is in bits
6 DINTEGER integer access, len is in bytes
7 REAL real access, len is in bytes
9 OCTET STRING octet string, len is in bytes
Byte[4]Byte[5] 00 01 即数据的长度
Byte[6]byte[7] 00 01 即 DB 编号,若是访问的不是DB区域,此处为0x0000
Byte[8] 84 即数据的区域经常使用的如下表
Byte[9] Byte[10]Byte[11] 要读取数据的地址
图示总体标注一下
回包
Header部分
除了红框内的其余都与发包一致
Error class 即错误类型
Error code 即具体错误码这两个在上面已经介绍了都有哪些错误类型,没有错误即0x00
Parameter部分
Byte[0] 04 功能码 Byte[1] 01 表明一个Item
Data部分
Byte[0] FF 为返回码 返回码经常使用值如下表
0x00 Reserved 未定义,预留
0x01 Hardware error 硬件错误
0x03 Accessing the object not allowed 对象不容许访问
0x05 Invalid address 无效地址,所需的地址超出此PLC的极限
0x06 Data type not supported 数据类型不支持
0x07 Data type inconsistent 日期类型不一致
0x0a Object does not exist 对象不存在
0xff Success 成功
Byte[1] 04 为数据传输大小 data数据传输大小值如下表
0 NULL
3 BIT bit access, len is in bits
4 BYTE/WORD/DWORD byte/word/dword access, len is in bits
5 INTEGER integer access, len is in bits
6 DINTEGER integer access, len is in bytes
7 REAL real access, len is in bytes
9 OCTET STRING octet string, len is in bytes
Byte[2]Byte[3] 为data数据的长度
Byte[4] 即数据
有时候会有填充数据即在byte[4]以后、若是数据长度不知足length的话会填充0x00
列如 byte[2]byte[3] 的长度值为3 就会在byte[4]后填充两个0x00
仍是总体在图示一遍吧
好了,这个功能算是啃完了,其余的功能也大体都同样,因此呢剩下的时候我可能会比较懒了哈哈。
这就很好理解了吧,有读必有写。那写咱们去推断一下,是否是在发包的时候比读数据会多一个Data段做为写入的值呢。答案是确定的!
发包
Header 都与读取值同样的就不在说了
Parameter也同样图示一次吧
叮叮叮,Data段来了
Byte[0] 00 返回码未定义就为00
Byte[1] 04 数据传输的大小
Byte[2]Byte[3] 数据的长度
Byte[4] 数据
是否是感受这些都差很少同样,
计算机跟人类也是同样的。
我对你说“你好帅啊” 你是否是也会回我一句“你也好帅”,假设说你回了一句“我很帅,你很丑”
这是否是不符合常理了,有可能你还要挨骂对吧。
那计算机也是啊,服务端发送数值,客户端不但不接受还骂服务端一句,那是否是服务端这边要报错呢。
可能例子不太恰当,意思到了就阔仪了。
言归正传,别爱我,没结果。
回包
引用上面我举的例子,那彻底能够推断出来回包会会什么对吧。
发包写入了数据,那我回包是否是要回复写入成功或者失败呢。
Header部分和parameter部分都同样仍是懒了些就不在描述了。
来看Data部分吧
Byte[0] FF 即为返回码
上面介绍有返回码的类型 整段的意思就是向0x000000地址写入成功
还有好多个功能码没有写,我会放到下一篇文章里。
缘由:懒了懒了懒了
未完待续....
附录一:错误码具体含义
0x0000 |
没有错误 |
0x0110 |
块号无效 |
0x0111 |
请求长度无效 |
0x0112 |
参数无效 |
0x0113 |
块类型无效 |
0x0114 |
找不到块 |
0x0115 |
块已存在 |
0x0116 |
块被写保护 |
0x0117 |
块/操做系统更新太大 |
0x0118 |
块号无效 |
0x0119 |
输入的密码不正确 |
0x011A |
PG资源错误 |
0x011B |
PLC资源错误 |
0x011C |
协议错误 |
0x011D |
块太多(与模块相关的限制) |
0x011E |
再也不与数据库创建链接,或者S7DOS句柄无效 |
0x011F |
结果缓冲区过小 |
0x0120 |
块结束列表 |
0x0140 |
可用内存不足 |
0x0141 |
因为缺乏资源,没法处理做业 |
0x8001 |
当块处于当前状态时,没法执行请求的服务 |
0x8003 |
S7协议错误:传输块时发生错误 |
0x8100 |
应用程序,通常错误:远程模块未知的服务 |
0x8104 |
未在模块上实现此服务或报告了帧错误 |
0x8204 |
对象的类型规范不一致 |
0x8205 |
复制的块已存在且未连接 |
0x8301 |
模块上的内存空间或工做内存不足,或者指定的存储介质不可访问 |
0x8302 |
可用资源太少或处理器资源不可用 |
0x8304 |
没法进一步并行上传。存在资源瓶颈 |
0x8305 |
功能不可用 |
0x8306 |
工做内存不足(用于复制,连接,加载AWP) |
0x8307 |
保持性工做记忆不够(用于复制,连接,加载AWP) |
0x8401 |
S7协议错误:无效的服务序列(例如,加载或上载块) |
0x8402 |
因为寻址对象的状态,服务没法执行 |
0x8404 |
S7协议:没法执行该功能 |
0x8405 |
远程块处于DISABLE状态(CFB)。该功能没法执行 |
0x8500 |
S7协议错误:帧错误 |
0x8503 |
来自模块的警报:服务过早取消 |
0x8701 |
寻址通讯伙伴上的对象时出错(例如,区域长度错误) |
0x8702 |
模块不支持所请求的服务 |
0x8703 |
拒绝访问对象 |
0x8704 |
访问错误:对象已损坏 |
0xD001 |
协议错误:非法的做业号 |
0xD002 |
参数错误:非法的做业变体 |
0xD003 |
参数错误:模块不支持调试功能 |
0xD004 |
参数错误:做业状态非法 |
0xD005 |
参数错误:做业终止非法 |
0xD006 |
参数错误:非法链路断开ID |
0xD007 |
参数错误:缓冲区元素数量非法 |
0xD008 |
参数错误:扫描速率非法 |
0xD009 |
参数错误:执行次数非法 |
0xD00A |
参数错误:非法触发事件 |
0xD00B |
参数错误:非法触发条件 |
0xD011 |
调用环境路径中的参数错误:块不存在 |
0xD012 |
参数错误:块中的地址错误 |
0xD014 |
参数错误:正在删除/覆盖块 |
0xD015 |
参数错误:标签地址非法 |
0xD016 |
参数错误:因为用户程序错误,没法测试做业 |
0xD017 |
参数错误:非法触发号 |
0xD025 |
参数错误:路径无效 |
0xD026 |
参数错误:非法访问类型 |
0xD027 |
参数错误:不容许此数据块数 |
0xD031 |
内部协议错误 |
0xD032 |
参数错误:结果缓冲区长度错误 |
0xD033 |
协议错误:做业长度错误 |
0xD03F |
编码错误:参数部分出错(例如,保留字节不等于0) |
0xD041 |
数据错误:非法状态列表ID |
0xD042 |
数据错误:标签地址非法 |
0xD043 |
数据错误:找不到引用的做业,检查做业数据 |
0xD044 |
数据错误:标签值非法,检查做业数据 |
0xD045 |
数据错误:HOLD中不容许退出ODIS控制 |
0xD046 |
数据错误:运行时测量期间非法测量阶段 |
0xD047 |
数据错误:“读取做业列表”中的非法层次结构 |
0xD048 |
数据错误:“删除做业”中的非法删除ID |
0xD049 |
“替换做业”中的替换ID无效 |
0xD04A |
执行'程序状态'时出错 |
0xD05F |
编码错误:数据部分出错(例如,保留字节不等于0,...) |
0xD061 |
资源错误:没有做业的内存空间 |
0xD062 |
资源错误:做业列表已满 |
0xD063 |
资源错误:触发事件占用 |
0xD064 |
资源错误:没有足够的内存空间用于一个结果缓冲区元素 |
0xD065 |
资源错误:没有足够的内存空间用于多个结果缓冲区元素 |
0xD066 |
资源错误:可用于运行时测量的计时器被另外一个做业占用 |
0xD067 |
资源错误:“修改标记”做业过多(特别是多处理器操做) |
0xD081 |
当前模式下不容许使用的功能 |
0xD082 |
模式错误:没法退出HOLD模式 |
0xD0A1 |
当前保护级别不容许使用的功能 |
0xD0A2 |
目前没法运行,由于正在运行的函数会修改内存 |
0xD0A3 |
I / O上活动的“修改标记”做业太多(特别是多处理器操做) |
0xD0A4 |
'强制'已经创建 |
0xD0A5 |
找不到引用的做业 |
0xD0A6 |
没法禁用/启用做业 |
0xD0A7 |
没法删除做业,例如由于当前正在读取做业 |
0xD0A8 |
没法替换做业,例如由于当前正在读取或删除做业 |
0xD0A9 |
没法读取做业,例如由于当前正在删除做业 |
0xD0AA |
处理操做超出时间限制 |
0xD0AB |
进程操做中的做业参数无效 |
0xD0AC |
进程操做中的做业数据无效 |
0xD0AD |
已设置操做模式 |
0xD0AE |
做业是经过不一样的链接设置的,只能经过此链接进行处理 |
0xD0C1 |
访问标签时至少检测到一个错误 |
0xD0C2 |
切换到STOP / HOLD模式 |
0xD0C3 |
访问标记时至少检测到一个错误。模式更改成STOP / HOLD |
0xD0C4 |
运行时测量期间超时 |
0xD0C5 |
块堆栈的显示不一致,由于块被删除/从新加载 |
0xD0C6 |
做业已被删除,由于它所引用的做业已被删除 |
0xD0C7 |
因为退出了STOP模式,所以做业被自动删除 |
0xD0C8 |
因为测试做业和正在运行的程序之间不一致,“块状态”停止 |
0xD0C9 |
经过复位OB90退出状态区域 |
0xD0CA |
经过在退出前重置OB90并访问错误读取标签退出状态范围 |
0xD0CB |
外设输出的输出禁用再次激活 |
0xD0CC |
调试功能的数据量受时间限制 |
0xD201 |
块名称中的语法错误 |
0xD202 |
函数参数中的语法错误 |
0xD205 |
RAM中已存在连接块:没法进行条件复制 |
0xD206 |
EPROM中已存在连接块:没法进行条件复制 |
0xD208 |
超出模块的最大复制(未连接)块数 |
0xD209 |
(至少)模块上找不到给定块之一 |
0xD20A |
超出了能够与一个做业连接的最大块数 |
0xD20B |
超出了一个做业能够删除的最大块数 |
0xD20C |
OB没法复制,由于关联的优先级不存在 |
0xD20D |
SDB没法解释(例如,未知数) |
0xD20E |
没有(进一步)阻止可用 |
0xD20F |
超出模块特定的最大块大小 |
0xD210 |
块号无效 |
0xD212 |
标头属性不正确(与运行时相关) |
0xD213 |
SDB太多。请注意对正在使用的模块的限制 |
0xD216 |
无效的用户程序 - 重置模块 |
0xD217 |
不容许在模块属性中指定的保护级别 |
0xD218 |
属性不正确(主动/被动) |
0xD219 |
块长度不正确(例如,第一部分或整个块的长度不正确) |
0xD21A |
本地数据长度不正确或写保护错误 |
0xD21B |
模块没法压缩或压缩早期中断 |
0xD21D |
传输的动态项目数据量是非法的 |
0xD21E |
没法为模块(例如FM,CP)分配参数。系统数据没法连接 |
0xD220 |
编程语言无效。请注意对正在使用的模块的限制 |
0xD221 |
链接或路由的系统数据无效 |
0xD222 |
全局数据定义的系统数据包含无效参数 |
0xD223 |
通讯功能块的实例数据块错误或超出最大背景数据块数 |
0xD224 |
SCAN系统数据块包含无效参数 |
0xD225 |
DP系统数据块包含无效参数 |
0xD226 |
块中发生结构错误 |
0xD230 |
块中发生结构错误 |
0xD231 |
至少有一个已加载的OB没法复制,由于关联的优先级不存在 |
0xD232 |
加载块的至少一个块编号是非法的 |
0xD234 |
块在指定的内存介质或做业中存在两次 |
0xD235 |
该块包含不正确的校验和 |
0xD236 |
该块不包含校验和 |
0xD237 |
您将要加载块两次,即CPU上已存在具备相同时间戳的块 |
0xD238 |
指定的块中至少有一个不是DB |
0xD239 |
至少有一个指定的DB在装载存储器中不可用做连接变量 |
0xD23A |
至少有一个指定的DB与复制和连接的变体有很大不一样 |
0xD240 |
违反了协调规则 |
0xD241 |
当前保护级别不容许该功能 |
0xD242 |
处理F块时的保护冲突 |
0xD250 |
更新和模块ID或版本不匹配 |
0xD251 |
操做系统组件序列不正确 |
0xD252 |
校验和错误 |
0xD253 |
没有可用的可执行加载程序; 只能使用存储卡进行更新 |
0xD254 |
操做系统中的存储错误 |
0xD280 |
在S7-300 CPU中编译块时出错 |
0xD2A1 |
块上的另外一个块功能或触发器处于活动状态 |
0xD2A2 |
块上的触发器处于活动状态。首先完成调试功能 |
0xD2A3 |
块未激活(连接),块被占用或块当前被标记为删除 |
0xD2A4 |
该块已被另外一个块函数处理 |
0xD2A6 |
没法同时保存和更改用户程序 |
0xD2A7 |
块具备“未连接”属性或未处理 |
0xD2A8 |
激活的调试功能阻止将参数分配给CPU |
0xD2A9 |
正在为CPU分配新参数 |
0xD2AA |
当前正在为模块分配新参数 |
0xD2AB |
当前正在更改动态配置限制 |
0xD2AC |
正在运行的激活或取消激活分配(SFC 12)暂时阻止R-KiR过程 |
0xD2B0 |
在RUN(CiR)中配置时发生错误 |
0xD2C0 |
已超出最大工艺对象数 |
0xD2C1 |
模块上已存在相同的技术数据块 |
0xD2C2 |
没法下载用户程序或下载硬件配置 |
0xD401 |
信息功能不可用 |
0xD402 |
信息功能不可用 |
0xD403 |
服务已登陆/注销(诊断/ PMC) |
0xD404 |
达到的最大节点数。再也不须要登陆诊断/ PMC |
0xD405 |
不支持服务或函数参数中的语法错误 |
0xD406 |
当前不可用的必需信息 |
0xD407 |
发生诊断错误 |
0xD408 |
更新已停止 |
0xD409 |
DP总线错误 |
0xD601 |
函数参数中的语法错误 |
0xD602 |
输入的密码不正确 |
0xD603 |
链接已合法化 |
0xD604 |
已启用链接 |
0xD605 |
因为密码不存在,所以没法进行合法化 |
0xD801 |
至少有一个标记地址无效 |
0xD802 |
指定的做业不存在 |
0xD803 |
非法的工做状态 |
0xD804 |
非法循环时间(非法时基或多个) |
0xD805 |
不能再设置循环读取做业 |
0xD806 |
引用的做业处于没法执行请求的功能的状态 |
0xD807 |
功能因过载而停止,这意味着执行读取周期所需的时间比设置的扫描周期时间长 |
0xDC01 |
日期和/或时间无效 |
0xE201 |
CPU已是主设备 |
0xE202 |
因为闪存模块中的用户程序不一样,没法进行链接和更新 |
0xE203 |
因为固件不一样,没法链接和更新 |
0xE204 |
因为内存配置不一样,没法链接和更新 |
0xE205 |
因为同步错误致使链接/更新停止 |
0xE206 |
因为协调违规而拒绝链接/更新 |
0xEF01 |
S7协议错误:ID2错误; 工做中只容许00H |
0xEF02 |
S7协议错误:ID2错误; 资源集不存在 |