3. 数据编码规则:BCD码与HEX码的区别、数据格式标识(DI0-DI3)、数据项与数据单元的映射关系
各位同学,咱们今天聊点实在的。做智能电表协议开发,编码规则是绕不开的第一道坎。我见过不少新手,上来就对着报文发呆——这串数字到底是啥意思?是BCD码还是HEX码?搞不清楚,后面全乱套。
说白了,国网协议里的数据,不是你想怎么存就怎么存的。它有严格的规矩。今天我就把BCD码、HEX码、DI标识、还有数据映射关系,一次性给你讲透。
3.1 BCD码与HEX码:两个世界的数据表达
先问个问题:电表里存的是数字,但数字怎么表示?
嗯,这里有两种主流方式:BCD码和HEX码。它们看着像,但本质完全不同。
3.1.1 BCD码(Binary-Coded Decimal)
BCD码,说白了就是用4个二进制位表示一个十进制数字。0到9,每个数字占半个字节(4位)。
举个例子:十进制数 1234,用BCD码表示就是 0x12 0x34。你看,两个字节,每个字节的高4位和低4位分别代表一个十进制位。
我个人习惯:在调试电表参数时,看到 0x12 0x34 这种数据,第一反应就是BCD码。千万别当成十六进制数去算,否则你会得到 0x1234 = 4660,完全不是一回事。
BCD码特点:
- 每个半字节(4位)表示0-9,不会出现A-F
- 适合显示十进制数值,比如电表读数、电压值
- 存储效率低,但人类可读性好
3.1.2 HEX码(十六进制码)
HEX码就简单了,它就是标准的十六进制数。一个字节表示0x00到0xFF,对应十进制0到255。
比如:0x12 0x34 作为HEX码,它代表的是 0x1234 = 4660(十进制)。
我在项目中遇到过:有一次现场调试,电表上报的电压值是 0x01 0xF4。新来的同事按BCD码解析,得到 01F4,以为电压是1.94V。我一看就知道不对,这明显是HEX码,0x01F4 = 500,实际电压是500V(乘以系数0.1后是50.0V)。
避坑指南:我曾经因为BCD和HEX搞混,导致一个项目的数据解析全盘重来。记住:国网协议中,电能量数据多用BCD码,瞬时量数据多用HEX码。但这不是绝对的,一定要看数据格式标识(DI)。
3.2 数据格式标识(DI0-DI3):数据的身份证
你想想看,电表里那么多数据——电压、电流、功率、电量、费率……每个数据怎么编码?怎么知道它是BCD还是HEX?
答案就是:数据格式标识,也就是DI0到DI3这四个字节。
DI0-DI3,每个字节都有特定含义。我习惯把它们看作数据的「身份证」——看到DI,就知道这个数据是什么类型、什么格式、什么单位。
3.2.1 DI0:数据项类别
DI0决定了数据属于哪一大类。比如:
| DI0值 | 数据类别 | 举例 |
|---|---|---|
| 0x00 | 电能量 | 正向有功总电能 |
| 0x01 | 最大需量 | 当前最大需量 |
| 0x02 | 变量 | 电压、电流、功率 |
| 0x03 | 事件记录 | 掉电事件、编程事件 |
| 0x04 | 参变量 | 费率时段、密码 |
3.2.2 DI1:数据项编号
DI1进一步细分。比如DI0=0x02(变量)时,DI1=0x01表示A相电压,DI1=0x02表示B相电压。
3.2.3 DI2:数据格式与单位
这个字节最关键。它告诉你:
- 数据是BCD还是HEX
- 数据长度是多少字节
- 小数点的位置
- 单位是什么
举个例子:DI2 = 0x12,表示:
- 高4位(0x1):BCD码,2字节长度
- 低4位(0x2):小数点后2位
那么数据 0x12 0x34 解析出来就是 1234,再除以100,得到 12.34。
我的小技巧:DI2的低4位表示小数位数,这个值乘以4就是实际的小数点偏移。比如低4位是0x2,表示小数点后2位。但要注意,有些特殊值(如0xF)表示无小数点。
3.2.4 DI3:费率与通道标识
DI3用于区分费率(尖、峰、平、谷)和通道(主副表、三相)。
比如:DI3=0x01表示费率1(尖),DI3=0x02表示费率2(峰)。
3.3 数据项与数据单元的映射关系
好了,现在你知道数据怎么编码了。但还有一个问题:电表里那么多数据,怎么找到我要的那个?
这就涉及到数据项与数据单元的映射关系。
数据项:就是具体的某个数据,比如「正向有功总电能」。
数据单元:是数据在报文中的实际存储位置。
映射关系,说白了就是:给定一个DI(数据格式标识),就能找到对应的数据单元。
3.3.1 映射规则
国网协议里,映射关系是固定的。我总结了一个口诀:
DI0定大类,DI1定小类
DI2定格式,DI3定费率
组合起来查表,数据单元自然现
具体来说:
- 用DI0和DI1组成一个索引,查数据项定义表
- 找到对应的数据项名称、数据类型、长度
- 用DI2确定编码格式(BCD/HEX)和小数点位置
- 用DI3确定费率或通道
- 最终在报文中找到对应的数据单元
3.3.2 实际例子
假设收到一个数据请求:DI0=0x00, DI1=0x01, DI2=0x12, DI3=0x01
解析过程:
- DI0=0x00:电能量类
- DI1=0x01:正向有功
- DI2=0x12:BCD码,2字节,小数点后2位
- DI3=0x01:费率1(尖)
那么对应的数据单元就是:正向有功尖费率电能,数据格式为BCD,长度2字节,单位kWh,小数点后2位。
如果报文中的数据是 0x01 0x23,那么实际值就是 1.23 kWh。
重要提醒:映射关系不是一成不变的。不同厂家、不同版本的电表,映射表可能有细微差异。我建议你在开发时,一定要拿到电表厂家提供的《数据项定义表》,以那个为准。
3.4 总结与经验
好了,这一章的内容就这些。我最后再唠叨几句:
- BCD和HEX的区别:记住,BCD是「用二进制表示十进制」,HEX是「用二进制表示十六进制」。看到0x12 0x34,先看DI2,再决定怎么解析。
- DI0-DI3:这是数据的身份证,一定要吃透。我建议你把常用的DI组合背下来,调试时能省不少时间。
- 映射关系:别死记硬背,理解规则后,查表就行。我当年做第一个项目时,把映射表打印出来贴在工位上,天天看,慢慢就熟了。
下一章,我会讲报文帧结构——数据在线上到底怎么传的。到时候你会看到,今天学的编码规则,在报文中是怎么体现的。
嗯,今天就到这里。有问题随时问我。