作者:与非网社区工程师
发布日期:2026-10-30
一、前言
在机房监控、智能农业、医药仓储等场景中,以太网温湿度传感器因其布线简单、传输距离远、易于组网等优点,逐渐取代了传统的RS485方案。对于上位机开发人员来说,如何通过C#程序直接读取传感器数据,是项目中常见的需求。
本文以一款工业现场常见的传感器为例,介绍如何使用 C# Socket + Modbus TCP协议 读取温湿度数据,并给出可直接编译运行的完整源码。
二、硬件与环境说明
1. 传感器选型
通信接口:RJ45,支持10/100M自适应以太网
通信协议:Modbus TCP
供电方式:PoE 或 DC 12–24V
温度量程:-20℃ ~ +80℃,精度 ±0.3℃
湿度量程:0% ~ 100% RH,精度 ±2% RH
支持多从站ID,适用于复杂工业网络
192.168.1.100,端口 502,从站地址 1。首次使用建议通过厂家提供的配置工具确认参数。2. 软件环境
操作系统:Windows 10 / 11
开发工具:Visual Studio 2022
.NET 版本:.NET 6.0(也可兼容 .NET Framework 4.7.2+)
网络环境:PC 与传感器在同一局域网
三、Modbus TCP 协议简要说明
|
事务标识
|
协议标识
|
长度
|
从站地址
|
功能码
|
数据
|
|---|---|---|---|---|---|
|
2字节
|
2字节
|
2字节
|
1字节
|
1字节
|
N字节
|
温度:寄存器地址 0x0000(实际发送 0x0000)
湿度:寄存器地址 0x0001
255 表示 25.5℃,具体需参考设备手册。四、C# Socket 通信实现
1. 建立TCP连接
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class ModbusTcpClient
{
private Socket _socket;
private string _ip;
private int _port;
public ModbusTcpClient(string ip, int port = 502)
{
_ip = ip;
_port = port;
}
public bool Connect()
{
try
{
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
_socket.Connect(new IPEndPoint(IPAddress.Parse(_ip), _port));
Console.WriteLine("连接传感器成功!");
return true;
}
catch (Exception ex)
{
Console.WriteLine("连接失败:" + ex.Message);
return false;
}
}
}
2. 构造Modbus TCP读取报文
private byte[] BuildReadCommand(byte slaveId, ushort startAddr, ushort length)
{
byte[] cmd = new byte[12];
// 事务标识(可自增)
cmd[0] = 0x00;
cmd[1] = 0x01;
// 协议标识(0 = Modbus)
cmd[2] = 0x00;
cmd[3] = 0x00;
// 长度(后面字节数)
cmd[4] = 0x00;
cmd[5] = 0x06;
// 从站地址
cmd[6] = slaveId;
// 功能码 0x03
cmd[7] = 0x03;
// 起始地址
cmd[8] = (byte)(startAddr >> 8);
cmd[9] = (byte)(startAddr & 0xFF);
// 寄存器数量
cmd[10] = (byte)(length >> 8);
cmd[11] = (byte)(length & 0xFF);
return cmd;
}
3. 发送并解析温湿度数据
public void ReadTemperatureAndHumidity()
{
if (_socket == null || !_socket.Connected)
{
Console.WriteLine("请先连接传感器!");
return;
}
// 读取温度(假设地址0x0000)
byte[] tempCmd = BuildReadCommand(0x01, 0x0000, 0x0001);
_socket.Send(tempCmd);
byte[] tempResp = new byte[256];
int tempLen = _socket.Receive(tempResp);
// 解析温度(示例:直接取寄存器值/10)
ushort tempRaw = (ushort)((tempResp[9] << 8) | tempResp[10]);
double temperature = tempRaw / 10.0;
// 读取湿度(假设地址0x0001)
byte[] humCmd = BuildReadCommand(0x01, 0x0001, 0x0001);
_socket.Send(humCmd);
byte[] humResp = new byte[256];
int humLen = _socket.Receive(humResp);
ushort humRaw = (ushort)((humResp[9] << 8) | humResp[10]);
double humidity = humRaw / 10.0;
Console.WriteLine($"当前温度:{temperature} ℃");
Console.WriteLine($"当前湿度:{humidity} %RH");
}
4. 完整调用示例
class Program
{
static void Main(string[] args)
{
ModbusTcpClient client = new ModbusTcpClient("192.168.1.100");
if (client.Connect())
{
client.ReadTemperatureAndHumidity();
}
Console.ReadLine();
}
}
五、调试技巧与常见问题
1. 连接超时或拒绝
确认PC与传感器IP是否在同一网段
使用 ping 192.168.1.100 测试网络连通性
检查传感器是否开启了TCP端口(默认502)
2. 数据解析异常
使用 Wireshark 抓包对比Modbus报文
确认寄存器地址是否从0开始还是从1开始(不同厂家定义不同)
注意字节序(大端/小端)
3. 多传感器并发访问
每个传感器建议使用独立Socket连接
避免频繁短连接,可采用长连接 + 心跳机制
六、总结
理解Modbus TCP协议帧结构
使用Socket建立TCP连接并发送十六进制命令
正确解析寄存器数据并转换为工程值
掌握基本排错方法(Ping、Wireshark、配置工具)
22