使用Easy Modbus库读取PT100温度时30℃后出现随机负数问题求助
问题分析与解决方案
核心原因:数据类型解析不匹配
当温度达到30℃时,PLC输出的寄存器值超过了无符号16位整数的半程阈值(32767),但你的代码将寄存器值当作无符号数据处理,而PLC实际存储的是有符号16位整数(Int16),导致数值溢出后显示为随机负数。PLC IDE显示正常是因为它正确识别了数据的有符号类型。
具体修复步骤
1. 修正寄存器值的类型转换
将读取到的寄存器值从默认的无符号16位(ushort)转换为有符号16位整数(Int16),再转为double计算:
// 替换原代码中aux的赋值行 short rawValue = Convert.ToInt16(temp[0]); double aux = Convert.ToDouble(rawValue);
如果PLC使用32位数据存储温度(需要拼接两个寄存器),则需按PLC的字节序(大端/小端)合并寄存器值:
// 大端模式(高位寄存器在前) int raw32Value = (temp[0] << 16) | temp[1]; // 小端模式(低位寄存器在前) // int raw32Value = (temp[1] << 16) | temp[0]; double aux = Convert.ToDouble(raw32Value);
2. 验证PLC寄存器配置
- 确认PT100对应的寄存器数据类型:是16位有符号(Int16)、32位有符号(Int32)还是浮点型(Float)?
- 核对寄存器地址范围:你读取了地址0开始的2个寄存器,但实际温度值可能仅存在于地址0,或需要合并地址0与1的内容。
3. 添加调试输出对比原始值
在代码中输出寄存器的十六进制原始值,和PLC IDE显示的值做对比,确认数据一致性:
Console.WriteLine($"原始寄存器十六进制值: {temp[0]:X4}");
如果PLC IDE中30℃对应的十六进制值以0x8开头,说明是有符号数的负数补码表示,必须用Int16转换才能得到正确的实际数值。
4. 检查线性化函数get_lineariza
验证get_lineariza函数是否支持有符号输入,比如传入PLC显示的30℃对应寄存器值,确认函数输出是否符合预期,避免因输入负数导致计算异常。
修复后的示例代码
if (PLC != null && PLC.Connected) { try { ushort[] temp = PLC.ReadHoldingRegisters(0, 2); // 转换为有符号16位整数 short rawValue = Convert.ToInt16(temp[0]); double aux = Convert.ToDouble(rawValue); double temperaturaLinearizada = get_lineariza(aux, 65535, 60); Console.WriteLine($"Valor lido: {aux}, Temperatura Linearizada: {temperaturaLinearizada}"); Console.WriteLine($"原始寄存器十六进制: {temp[0]:X4}"); // 调试用 lbl_temperatura.Text = $"Temperatura: {temperaturaLinearizada.ToString("0.00")}, PT100: {aux.ToString("0.00")}"; temp = PLC.ReadHoldingRegisters(4, 2); lbl_temperatura.Text += $", L: {temp[0]}"; } catch (Exception ex) { Console.WriteLine($"Erro: {ex.Message}"); } }
内容的提问来源于stack exchange,提问作者guilherme vini
相关产品推荐
相关产品推荐

