前言:本文仅为个人学习记录,非专业讲解,仅为自身巩固记忆以及日后复习所用,如有错误,欢迎指正!
1.定义与语法符号
1.1 定义
1.1.1 C12.18 Client(客户端)
与C12.18 Device(设备端)通过ANSI C12.18Ⅱ类光学口连接的电子通信设备
1.1.2 C12.18 Device(设备端)
一种实现ANSI C12.18Ⅱ类光学口通信协议的电子通信设备
1.1.3 PTP Communication点对点通信
两个设备通过单个光学接口进行通信
1.1.4 Table(表格)
按照ANSI C12.19的定义,Table是将功能相关的一些数据元素组合成的一个用于传输的数据结构体
1.2 语法符号
< > | 用于定义一个由单个或多个元素组成的基本单元,如<read> |
::= | 表示“被定义为”,左值被定义为右值内容,如<read> ::= 30H |
| | 表示“或”,定义的基本单元可以有多个选项,如<read> ::= <full-read>|<pread-default> |
[ ] | 括号里的内容是可选的。产生式无论是否被包含,它都是有效的(没遇到[ ]标注的内容,暂时未理清这句话的含义),原文:A symbol enclosed in square brackets is optional.The production is valid whether or not it is included. |
* | 带星号的单元可以多次出现也可不出现 |
+ | 带加号的单元必须出现,至少一次 |
+n | 标注的内容出现n次 |
{ } | 起注释的作用 |
2.协议详情
2.1 基本数据类型
<byte> ::= {8bits} | |
<msbyte> ::= <byte> | {最高有效字节} |
<lsbyte> ::= <byte> | {最低有效字节} |
<word24> ::= <msbyte> <byte> <lsbyte> | {24bits} |
<word16> ::= <msbyte> <lsbyte> | {16bits} |
2.2 应用层(层7)
提供一组服务(PSEM服务,共9种)和数据结构
2.2.1 数据结构
详情参阅ANSI C12.19中关于Table结构的定义
2.2.2 PSEM(Protocol Specifications for Electric Metering)
PSEM定义了9种服务,每种服务由一个请求和一个响应组成,具体如下:
请求:<requests> ::= | |
<ident> | | {identification} |
<read> | | {读取} |
<write> | | {写入} |
<logon> | | {建立会话} |
<security> | | {访问权限控制} |
<logoff> | | {关闭会话} |
<negotiate> | | {协商,用于配置通信参数} |
<wait> | | {修改等待时长} |
<terminate>| | {终止会话并关闭通信信道} |
响应:<responses> ::= |
<ident-r> | |
<read-r> | |
<write-r> | |
<logon-r> | |
<security-r> | |
<logoff-r> | |
<negotiate-r> | |
<wait-r> | |
<terminate-r> | |
2.2.2.1 编码域划分
1.00H~1FH:作为响应服务的编码号
正确响应:<ok> ::= 00H {接受请求}
报错响应:<nok> ::= <sns> | <isss> | <iar> | <isc> | <onp> | <bsy> | <dlk> |
<dnr> | <rno> |<err>{优先级从左往右递减}
<err> ::= 01H | 为应用层错误码,用于表示拒绝接收到的服务请求。没有提供拒绝的原因 |
<sns> ::= 02H | 为应用层错误码,用于表示请求的服务不被支持。消息是有效的,但请求无法被执行 |
<isc> ::= 03H | 为应用层错误码,用于表示访问权限不够 |
<onp> ::= 04H | 为应用层错误码,用于表示无效操作。消息有效,但无法被处理,如无效字长(length)、无效偏移量(offset) |
<iar> ::= 05H | 为应用层错误码,用于表示非法操作。如对只读表申请写入 |
<bsy> ::= 06H | 为应用层错误码,用于表示请求未被处理,因为设备忙于做其他事情。该操作可能会在稍后重试并成功,因为在此主动通信期间数据可能已准备好进行传输 |
<dnr> ::= 07H | 为应用层错误码,用于请求不成功,因为请求的数据尚未准备好被访问 |
<dlk> ::= 08H | 为应用层错误码,用于表示请求不成功,因为该数据无法访问 |
<rno> ::= 09H | 重新协商请求,为应用层错误码,用于响应设备希望返回 ID 或基本状态并重新协商通信参数 |
<isss> ::= 0AH | 无效的服务序列状态。 为应用层错误码,用于表示在当前服务序列状态下不接受请求。 有关服务序列状态的更多信息,请参阅附录 C服务序列状态控制 |
2.20H~7FH:作为请求服务的编码号
3.80H~FFH:保留,以备协议扩展
2.2.2.2 Identification 服务(必须支持的服务)
用于获取设备正在使用的版本信息,作为发出的第一个服务总是优先于negotiate服务使用(协商通信参数,包括最大字长和波特率等),因此该服务的应答信息包长不应超过默认包长(一般默认为64bytes),总是由C12.18客户端发起。
<ident> ::= 20H
<ident-r> ::= <isss> | <bsy> | <err> |
<ok ><std> <ver> <rev> <feature>* <end-of-list>
<std> ::= <byte> | {表明所使用的协议版本, 00H = C12.18 01H = 保留 02H = C12.21 03H = C12.22 04H~FFH = 保留} |
<ver> ::= <byte> | {版本号} |
<rev> ::= <byte> | {修订号} |
<feature> ::= <device-class> | <device-identity> | {表示设备的特征} |
<end-of-list> ::= 00H | {结束符} |
2.2.2.3 Negotiate 服务(协商服务,可选服务)
用于协商配置通信参数,一般在通信参数与该标准默认值不同时使用,重新协商或信道关闭后参数失效,该服务只能在Identification 服务之后以及Logon服务之前发送,且只能由C12.18客户端发起。
请求:
<negotiate> ::= <baud-rate-selector> <packet-size> <nbr-packets> <baud-rate>*
<baud-rate-selector> ::= 60H~6BH | {0H~BH分别对应请求中有0~11个<baud-rate>,取60H时使用默认波特率} |
<packet-size> ::= <word16> | {数据包最大字长,可设置64~8192byte} |
<nbr-packets> ::= <byte> | {最大可支持数据包数。0值是为以后标准扩展而做的保留} |
<baud-rate> ::= 00H~FFH | {01H~05H:300,600,1200,2400,4800 06H~0AH:9600,14400,19200,28800,57600 0BH~0EH:38400,115200,128000,256000 0FH~FFH:保留 } |
响应:
<negotiate-r> ::= <sns> | <isss> | <bsy> | <err> |
<ok> <packet-size> <nbr-packets> <baud-rate>
<packet-size> ::= <word16> | {数据包最大字长,可设置64~8192byte} |
<nbr-packets> ::= <byte> | {最大可支持数据包数。0值是为以后标准扩展而做的保留} |
<baud-rate> ::= 00H~FFH | {01H~05H:300,600,1200,2400,4800 06H~0AH:9600,14400,19200,28800,57600 0BH~0EH:38400,115200,128000,256000 0FH~FFH:保留 } |
2.2.2.4 Logon 服务(登入,必须支持的服务)
建立一个无需访问权限的会话连接,总是由C12.18客户端发起。
请求:
<logon> ::= 50H <user-id> <user>
<user-id> ::= <word16> | {用户身份代码,对应C12.19 Procedure18中的USER_ID} |
<user> ::= <byte>+10 | {10bytes,包含用户ID} |
响应:
<logon-r> ::= <isss> | <iar> | <bsy> | <err> |
<ok>
2.2.2.5 Logoff 服务(登出,必须支持的服务)
关闭由Logon建立起的会话连接,通信信道维持上次建立通信的参数
请求:
<logoff> ::= 52H
响应:
<logoff-r> ::= <isss> | <bsy> | <err> |
<ok>
2.2.2.6 Security 服务(安全访问权限,可选服务)
用于提供访问权限控制,在Logon成功建立会话后使用,总是由C12.18客户端发起。
请求:
<security> ::= 51H <password>
<password> ::= <byte>+20 | {与C12.19的SECURITY_TBL(Table42)的PASSWORD元素进行比对。长度应为20bytes,也可以是ACT_SECURITY_LIMITING_TBL(Table41)中的PASSWORD_LEN(更小)} |
响应:
<security-r> ::= <sns> | <isss> | <bsy> | <err> |
<ok>
2.2.2.7 Read 服务(全读和部分读,至少需要支持一种方式的读服务)
传输Table数据给请求设备,在Logon成功建立会话后使用。
30H——全读
31H~39H——使用Index/element-count方式部分读(不做详解)
3EH——默认table transfer
3FH——使用offset/octet-count方式部分读
请求:
<read> ::= <full-read> | <pread-index> |
<pread-offset> | <pread-default>
<full-read> ::= 30H <tableid> | |
<tableid> ::= <word16> | {C12.19中表格对应的标号} |
<pread-offset> ::= 3FH <tableid> <offset> <octet-count> | |
<tableid> ::= <word16> | {C12.19中表格对应的标号} |
<offset> ::= <word24> | {地址偏移量,以字节为单位的表格偏移量} |
<octet-count> ::= <word16> | {从Table<offset>开始,请求的数据长度,以字节为单位} |
响应:
<read-r> ::= <nok> |
<ok> <table-data>
<table-data> ::= <count> <data> <cksum> | |
<count> ::= <word16> | {返回的<data>大小,以字节为单位} |
<data> ::= <byte>* | {在接收请求后返回的Table数据以及C12.19中的可选的挂起标头} |
<cksum> ::= <byte> | {<data>的累加和} |
2.2.2.8 Write 服务(全写和部分写,可选服务)
发送Table数据给目标设备,在Logon成功建立会话后才能使用
40H——全写
41H~49H——使用Index/element-count方式部分写(不做详解)
4FH——使用offset/octet-count方式部分写
请求:
<write> ::= <full-write> | <pwrite-index> | <pwrite-offset>
<full-write> ::= 40H<tableid> <table-data>
<pwrite-offset> ::= 4FH<tableid> <offset> <table-data>
响应:
<write-r> ::= <nok> | <ok>
2.2.2.9 Wait 服务(超时等待,可选服务)
用于在空闲期间维持通信信道,扩展channel traffic time-out的等待时长至<time>,防止因time-out而自动终止,在接收到下一个PESM服务后channel traffic time-out恢复默认值。
请求:
<wait> ::= 70H<time>
<time> ::= <byte> {以秒为单位}
响应:
<wait-r> ::= <sns> | <isss> | <bsy> | <err> |
<ok>
2.2.2.10 Terminate 服务(终止,可选服务)
立即关闭通信信道并终止已打开的会话(隐式调用Logoff服务),信道参数恢复默认值
请求:
<terminate> ::= 21H
响应:
<terminate-r> ::= <sns> | <err> |
<ok>
2.2.2.11 Offset/octet-count法访问部分表
a) <offset>表示相对于Table开头的一个新访问起点
b) <offset>为0表示由元素的数据类型和GEN_CONFIG_TBL(表00)的DATA_ORDER值规定的Table中第一个元素的第一个字节的一字节偏移量
c) 在读取请求中,
1) <octet-count>大于0时,程序在发出顺序遍历数据元素请求后应从<offset>位置开始返回不超过<octet-count>个字节,其中每个元素将根据其数据类型和GEN_CONFIG_TBL(表00)的DATA_ORDER值进行传输;
2) <octet-count>大于可用于传输的字节数时,传输字节数则被限制为可用的最大字节数。响应中<count>也应进行相应调整,以反映从请求的表<offset>开始的响应中传输的实际字节数,并包括可选的挂起标头;
3) <octet-count>等于0表示请求读取从表<offset>开始到表结束之间的全部数据;
4) <octet-count>表示读取请求的最大字节数。
d) 在读取响应中,<count>等于0表示未读取到数据
e) 在写入请求中,<count>应正确表示从表<offset>位置开始写入的实际字节数,包括可选的挂起标头
f) <offset>的值按照具体情况设置,有些元素在ANSI C12.19的Table中有定义,但实际情况无该元素即长度为0,则不应对该元素计数和传输
g) 字节计数器计数字节数不计元素个数
h) 如果响应程序不支持传输请求中<offset>位置的字节,则该程序应声明“Inappropriate Action Requested(iar,不当请求)”的错误状况
2.3~2.6 表示层、会话层、传输层、网络层均为空层
略
2.7 数据链路层(层2)
上层服务以一个或多个数据包进行传输。每个数据包的大小均可变,但不超过最大数据包大小(有默认值,也可协商改变)
每收到一个数据包,目标设备都会发出一个Acknowledgment(ack,nak)。该应答是在数据包结构外独立传输的单个字节。若请求方在响应超时前未收到ack或nak,则重新传输该数据包,重复三次后仍无确认信息,请求方则认定发生了终止服务(Terminate)
2.7.1 基本数据(默认配置)
数据格式 | 8bit数据位,1位起始位,1位停止位,无奇偶校验位 |
通信方式 | 异步串行半双工 |
传输速率 | 最大传输速率至少为9600 baud。可以通过选择码选择以下波特率:300,600,1200,2400,5800,9600,14400,19200,28800,38400,57600,115200,128000,256000 |
数据包数 | 至少有一个数据包,更多可以通过协商修改 |
数据包大小 | 默认位64bytes,更大可以通过协商修改 |
Channel Traffic time-out | 6 s |
Inter-Character time-out | 500 ms |
Response time-out | 2 s |
Turn-Around delay | 175 μs |
如果发生冲突(C12.18 客户端和 C12.18 设备同时传输),C12.18 设备应停止传输并等待 C12.18 客户端的传输。
2.7.2 数据包格式(重点)
<packet> ::= <stp> <identity> <ctrl> <seq-nbr> <length> <data> <crc>
<stp> ::= EEH | {起始符} |
<identity> ::= <byte> | {C12.19设备(终端、通信卡等)身份认证,用于标识设备。在00H~FEH之间,可通过ANSI C12.21-1999的全局参数表(表92)中的PSEM表示子段指定。FFH由ANSI C12.21主叫方使用,本协议不应使用。当使用00H以外的身份进行寻址时,C12.19 设备应在响应中使用自己的身份字节或 00H; 否则响应标识字节均为00H} |
<ctrl> ::= <byte> | {控制域 bit7:是否为多包传输的一部分 bit6:是否为多包传输的第一包 bit5:表示拒绝重复包的切换位,每发送1个新数据包则该位翻转,重传的数据包与原始发送保一致。该位初始值不指定,可置0或置1 bit4~2:保留,传输时置0 bit1~0:DATA_FORMAT 0 = C12.18 or C12.21 1 = C12.22 2、3 = 保留} |
<seq-nbr> ::= <byte> | {值为传输总包数减1。每发送1个新数据包,数字减1,若只有一包数据则为0} |
<length> ::= <word16> | {<data>的字节长度} |
<data> ::= <byte>* | {<length>个字节数据,最大长度=(最大包长-8)bytes,永远不超过8183bytes} |
<crc> ::= <lsbyte> <msbyte> | {CCITT CRC 16校验码} |
2.7.3 重复数据包
重复数据包定义为<identity>、重复包切换位以及有效CRC值均与前一个数据包相同。收到重复数据包后,设备会忽略并返回<ack>。在进入基态时,第一个数据包中的切换位可以采取任何状态,此时应抑制重复数据包拒绝机制,直到在基态时收到第一个有效数据包。
2.7.4 CCITT CRC 16
多项式:X16 + X12 + X5 + 1。从起始字符<stp>(EEH)开始计算,CRC值先传地位后传高位。
2.7.5 Acknowledgment(确认)
通信设备通过肯定或否定的Acknowledgment(ack or nak)来确认单个数据包是否有效
<ack> ::= 06H | {收到的数据帧(包)有效} |
<nak> ::= 15H | {收到的数据帧(包)不合法,存在某种错误} |
2.7.6 重传机制
在接收到一个<nak>或一个无效字符或acknowledge超时(确认超时)时,应重传该数据包,连续三次后,自动发出终止服务(Terminate)