如何反转mBus标准下MAN转HEX的C#函数?
无线M-BUS厂商代码(MAN)与十六进制互转问题
无线M-BUS标准中,3位大写字母的厂商字符串(MAN)与十六进制数字存在固定转换规则。我已实现MAN字符串转十六进制的C#函数:
public static bool TryMANtoHEX(string man_str, out uint man_hex) { man_hex = 0; if (man_str.Length != 3) return false; if (!Regex.IsMatch(man_str, @"^[a-zA-Z]+$")) return false; man_str = man_str.ToUpper(); try { man_hex += ((uint)man_str[2] - 64); man_hex += ((uint)man_str[1] - 64) * 32; man_hex += ((uint)man_str[0] - 64) * 32 * 32; } catch { return false; } return true; }
但在实现反向转换(十六进制转MAN字符串)时,第二个字符计算错误。例如输入0x2674,预期输出"IST",实际得到"IųT"。我的错误实现代码如下:
public static bool TryHEXtoMAN(uint man_hex, out string man_str) { man_str = string.Empty; char c1 = (char)((man_hex / 1024) + 64); char c2 = (char)((man_hex / 32) + 64); char c3 = (char)((man_hex % 32) + 64); char[] cs = { c1, c2, c3 }; man_str = new(cs); return true; }
问题分析与修正
错误根源在于第二个字符的计算逻辑:正向转换中第一位字符的权重是32²=1024,第二位是32,反向计算时需要先剔除第一位的影响,再计算第二位。
修正后的TryHEXtoMAN函数:
public static bool TryHEXtoMAN(uint man_hex, out string man_str) { man_str = string.Empty; // 计算第一位:除以32²(1024)得到偏移量 char c1 = (char)((man_hex / 1024) + 64); // 计算第二位:先取1024的模去除第一位的影响,再除以32 char c2 = (char)(((man_hex % 1024) / 32) + 64); // 计算第三位:直接取32的模 char c3 = (char)((man_hex % 32) + 64); char[] cs = { c1, c2, c3 }; man_str = new string(cs); // 可选:验证结果是否为合法的3位大写字母 if (!Regex.IsMatch(man_str, @"^[A-Z]+$")) { man_str = string.Empty; return false; } return true; }
验证示例
输入0x2674(十进制9844)的计算过程:
- 9844 ÷ 1024 = 9 → 9 + 64 = 73 → 字符
'I' - 9844 % 1024 = 628 → 628 ÷ 32 = 19 → 19 + 64 = 83 → 字符
'S' - 9844 % 32 = 20 → 20 + 64 = 84 → 字符
'T'
最终输出"IST",符合预期。
内容的提问来源于stack exchange,提问作者Pascal
相关产品推荐
相关产品推荐

