简介:TP301系列DTU使用说明面向工业物联网现场调试与数据采集实施人员,聚焦无线数据传输终端的入网配置与平台对接。手册从产品介绍切入,说明RS232、RS485、TTL三类通讯接口及供电、USB配置口、SIM卡座、状态指示灯等硬件细节,再依次讲解配置工具操作、MODBUS RTU协议连接TLINK示例、TCP协议连接TLINK平台示例、连接服务器示例,并附常见故障分析,便于读者按设备启动、平台连接、传输稳定性逐项排查。压缩包共1个PDF文件,约2.15MB,篇幅集中、目录层级清晰,可对照章节快速定位配置环节与排错依据。已有263人学习,适合初次接触TP301系列或需要完成现场调试的工程师作为案头参考。
1. 一台 TP301 系列 DTU 能替掉多少现场改造
车间里一排配电柜,要在不改动原有 PLC 程序的前提下,把 8 路温度送上云端,现场只剩两根 RS485 线可用。这种活我现在一般不塞工控机,直接在柜里装一台 TP301 系列 DTU:8~28V 直流取电,插卡、接 GPRS 天线,485 上的 Modbus 报文原样进、原样出,云平台那边就能看到实时曲线。DTU 在这个场景里干的事很朴素——把串口字节流封进 TCP 推出去,再把服务器下来的字节流还原到串口,报文怎么解析交给两侧的设备去管。它适合手里已有 Modbus RTU 从站、又不愿为联网重写上位机的现场工程师,也适合小批量远程采集、预算卡得紧的项目。不适合毫秒级闭环或按 MB 计数据量的场景,透传模块本来就不是干这个的。
2. 打通 USB 配置口:CH340 驱动、COM 口与 26 项参数怎么填
DTU 上电不亮灯、插上电脑又不认口,是新手最先撞的墙。这一章把从物理接口到参数落盘的全过程拆开,每一步都落到能复现的动作上。配置这件事看着是填表,真正决定上线成败的其实只有四五项,其余是留给现场调试和售后定位用的。
2.1 先看清四个物理口和三条串口线
TP301 系列的外壳上接口不多,但每个口的能力边界必须先分清,否则后面所有排错都是在猜。供电口吃 8~28VDC 直流,别拿 5V USB 供电去带,模块在发射瞬间的电流尖峰会让它反复重启。USB 配置口接电脑装 CH340 驱动后用来读写参数,这个口没有数据收发能力,别指望拿它当调试串口看业务报文。SIM 卡座按型号分两种,V2 只认移动和联通的 2G 网络,V4 是全网通版本,但电信 2G、3G 除外;如果用卡地区和型号不匹配,表现为网络启动失败,跟信号强弱没关系。SMA 天线口接 GPRS 天线,天线没接或接触不良会直接落到信号弱那一档。
数据侧提供 RS232、RS485、TTL 三种接口,一次只用一路,配置完成后三个口共享同一套串口参数——这点很关键,意味着你改了波特率,三个口一起变,不存在「485 是 9600、232 还是 115200」这种拆分配置。
| 接口 | 规格 | 能不能传业务数据 |
|---|---|---|
| 直流供电 | 8~28VDC | 否 |
| USB 配置口 | CH340 芯片,固定 115200-8-N-1 | 否,仅配置与日志 |
| SIM 卡座 | V2:移动/联通 2G;V4:全网通(除电信 2G/3G) | 否 |
| SMA 天线 | GPRS 天线 | 否 |
| RS232 / RS485 / TTL | 三选一,参数共用 | 是 |
2.2 CH340 驱动与 115200-8-N-1 的死约定
驱动装好之后,设备管理器的端口列表里会多出一个 COM 口,这就是配置通道。Linux 下对应的是 /dev/ttyUSB*,插拔前后对比一下就能定位。配置口的三项串口参数是固定的:115200 波特率、无校验、8 位数据位、1 位停止位,不需要也不允许改动,改了就刷不出设备信息。
# 插入 USB 配置线后,确认内核认到了 CH340 并拿到设备节点 ls -l /dev/serial/by-id/ dmesg | tail -n 20 | grep -i ch34 # 按固定参数配置该端口:115200、8 数据位、无校验、1 停止位、raw 模式 stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb -echo raw # 回读确认参数确实生效 stty -F /dev/ttyUSB0 -a | head -n 5这几条命令做三件事:ls /dev/serial/by-id/用稳定路径代替会漂移的 ttyUSB 编号,多设备同时插时尤其有用;dmesg | grep -i ch34确认是 CH340 而不是别的串口芯片抢了节点;stty那一行把端口参数对齐到配置工具的约定值,cs8是 8 位数据位、-cstopb是 1 位停止位、-parenb是去掉校验位、raw关掉行缓冲和回显,避免工具读到被终端加工过的字节。最后一行只是回读,方便确认没写错。
Windows 下没有这些命令,等价动作是打开设备管理器看端口号,回到配置工具的「通讯设置」,串口设置里选这个 COM 口,波特率填 115200,然后点刷新。刷不出设备信息,九成是 COM 口选错或者被别的软件占着。
2.3 配置项逐条拆:哪些必填,哪些别碰
配置工具刷新成功后会把二十多项参数一次性列出来。新手常见做法是从上往下挨个填,填到一半就乱了。我一般按「必填 → 按需 → 只读」三档过一遍,先把链路上线,再回头调细节。
| 配置项 | 档位 | 取值与建议 | 说明 |
|---|---|---|---|
| 登录包(序列号) | 必填 | 平台侧设备序列号 | 连云平台时必须与平台一致,连自建服务器按服务器要求填 |
| 服务器地址 | 必填 | 域名或 IP | 目标服务器地址 |
| 服务器端口号 | 必填 | 与服务器监听端口一致 | 填错表现为连接服务器失败 |
| 心跳包内容 | 按需 | 默认 Q | 按上报间隔周期发送 |
| 心跳包上报时间 | 按需 | 建议 45 秒 | 该时间内无数据上传则发心跳 |
| 十六进制登录包/心跳包 | 按需 | 是/否 | 决定登录包与心跳包的编码格式 |
| 掉线自检测 | 按需 | 开启/关闭 | 开启时心跳包必须为 Q |
| 掉线自检测时间 | 按需 | 0~1800 秒 | 该时间内没收到 A 即判定掉线 |
| 串口波特率/校验/数据位/停止位 | 必填 | 与所接从站设备一致 | 四项必须整体对齐 |
| APN 相关(3 项) | 按需 | 专网用户填写 | 公网卡不填 |
| IMEI | 按需 | 一般不动 | 需要绑定 IMEI 的平台才填 |
| 设备名称/型号/温度/信号强度/运营商/无线网络 | 只读 | 不改 | 用于判断现场状态 |
掉线自检测这一项值得单独说。它的工作方式是:DTU 每到一个心跳周期就向服务器发字符串 Q,服务器必须在设定的检测时间内回一个字符串 A,收不到 A 就判定为假连接,主动重连,重连若干次仍不成功则自动重启模块。所以开启它的前提是心跳包内容确实被设成了 Q,并且服务器侧真的会回 A。这两个条件缺一个,结果就是 DTU 反复重连、平台侧看着设备一直在线却收不到数据——这种「假在线」比直接掉线更难查。
2.4 保存与重启的先后顺序
配置工具右上角有两个按钮,保存配置和重启设备。血泪经验是:改完参数必须先点保存,再点重启,顺序反了或者只点重启,前面填的东西全丢,而界面上参数还显示着你刚填的值,看上去像是「配置生效了但没连上」,很容易把排查方向带到服务器和 SIM 卡上去。
固化成动作序列就是四步:改参数 → 点保存配置 → 点重启设备 → 点设备监听看启动日志。设备监听窗口打印的是 USB 口出来的运行日志,包括模块开机、网络启动、SIM 卡获取、信号强度、连接服务器这几段状态,配合外壳上的状态灯颜色,基本能在一分钟内判断卡在哪一环。这一步做完再去平台侧看数据,比在平台里瞎点效率高得多。
还有一处容易忽略:读取「检测 SIM 卡」这一项时必须用手动刷新。用自动刷新时经常出现有卡却检测不到的情况,第一次遇到会以为卡座坏了或者卡没插到位,实际只是刷新时机的问题。
3. MODBUS RTU 上云:偏置 +1、缩放 ÷100 与 120 秒轮询
Modbus RTU 这条路是现场最常见的:DTU 只管透传,Modbus 的主从关系发生在云平台和采集模块之间。理清这条链路上的三个数字——从站地址、寄存器地址、缩放倍数——比记住配置工具长什么样重要得多。
3.1 谁做主站:透传不等于协议转换
很多人第一次配会下意识认为 DTU 在做 Modbus 采集,其实不是。DTU 在透传模式下不解析任何 Modbus 报文,它把串口收到的字节原样塞进 TCP 发出去,把 TCP 收到的字节原样丢回串口。真正的 Modbus 主站是云平台:平台按周期下发读保持寄存器指令(功能码 03),报文经 DTU 透传到 485 总线,采集模块作为从站应答,应答报文再原路返回平台解析。
示例拓扑是一台 8 通道模拟量采集模块,485 接口,能直接接模拟量、热电偶、PT100 和 Cu50 热电阻,本次接的是 PT100。它做从站,从站地址为 1,支持功能码 03,数据区是 16 位无符号数,寄存器地址 0 到 7 分别对应第 1 到第 8 通道。这条「地址 0 对应通道 1」的映射关系是后面所有偏置计算的基准,记错一位整条数据链就整体错位。
一个必须提前知道的坑:平台侧的偏置字段不允许填 0。所以寄存器地址 0 要用偏置 1 来表达,寄存器地址 1 用偏置 2,依此类推。也就是说偏置 = 寄存器地址 + 1。这个 +1 没有任何协议含义,纯粹是平台字段的取值限制,但不理解它的人会在平台里填偏置 0,然后发现读回来的是第二个通道的数据。
3.2 平台侧建建设备:8 个传感器与 ÷100 映射
平台侧的动作顺序是:登录账号 → 左侧设备栏添加设备 → 填设备名(自定义,示例用的是协议名)、选 MODBUSRTU 协议、采集周期建议 120 秒 → 在地图上标注设备位置 → 点创建设备 → 跳转到设备列表。
建完设备还要配传感器。因为模块能采 8 组数据,传感器数量填 8;每个传感器的名称自定义,类型按被采集量选数值型,再设小数位和单位。这里最关键的一步是映射:模块在做 Modbus 通讯时把 PT100 的温度值放大了 100 倍,平台侧必须给每个传感器加一条映射把数据缩回 1/100,否则你会看到 1480 这种数字堂而皇之地挂在温度曲线上。
采集周期为什么建议 120 秒而不是 10 秒?GPRS 链路一次往返的延迟本身就在几百毫秒到一两秒量级,把周期压得太短,报文会在链路上排队,平台侧看到的是数据抖动而不是更实时。工业温度这种缓变量,120 秒完全够用,还能省流量。这是我一般的取值习惯,现场如果确实需要更快,先测一轮往返延迟再定。
3.3 报文级验证:手算一帧请求和应答
平台配完,别急着相信界面上的曲线。先用报文验证一遍链路,出问题时才知道是 DTU 没通还是寄存器错位。读 8 个保持寄存器的请求帧是01 03 00 00 00 08加 CRC16,标准应答是01 03 10加 16 字节数据加 CRC16。
def crc16_modbus(data: bytes) -> bytes: """标准 Modbus RTU 的 CRC16:初值 0xFFFF,多项式 0xA001(反向),低字节在前""" crc = 0xFFFF for b in data: crc ^= b for _ in range(8): if crc & 0x0001: crc = (crc >> 1) ^ 0xA001 else: crc >>= 1 return bytes([crc & 0xFF, (crc >> 8) & 0xFF]) # 从站地址 0x01,功能码 0x03,起始寄存器 0x0000,读取数量 0x0008 req = bytes.fromhex("010300000008") frame = req + crc16_modbus(req) print(frame.hex().upper()) # 输出 010300000008440C # 解析一帧实际应答 resp = bytes.fromhex("01031005C805C805D805CB05D8060B05C105D367F2") assert resp[2] == 0x10 # 字节数应为通道数 × 2 = 16 assert resp[-2:] == crc16_modbus(resp[:-2]) # CRC 自校验 payload = resp[3:-2] raw = [int.from_bytes(payload[i:i + 2], "big") for i in range(0, len(payload), 2)] print(raw) # [1480, 1480, 1496, 1483, 1496, 1547, 1473, 1491] print([round(v / 100, 2) for v in raw]) # [14.8, 14.8, 14.96, ...]这段代码干了三件事。crc16_modbus是标准实现,初值 0xFFFF、多项式 0xA001、结果低字节在前,这三个参数错一个 CRC 就对不上;构造请求时注意起始寄存器写的是 0x0000,读 8 个,正好覆盖 0~7 这 8 个通道;解析应答时先断言第 3 个字节是 0x10(16 字节有效数据),再断言尾部 CRC 正确,两个断言都过了才继续切数据,否则宁可报错也别往下算——带着错误报文算出来的温度看着也像那么回事,最难查。
拿到的原始值除以 100 就是实际温度:14.80℃、14.80℃、14.96℃、14.83℃、14.96℃、15.47℃、14.73℃、14.91℃。如果平台侧忘了加 ÷100 映射,你就会在界面看到 1480 这样的数字;如果偏置整体错了 1 位,你会看到通道号整体前移或后移,第 1 通道读到的是第 2 通道的温度。这两种现象对号入座,能省掉一大半排查时间。
3.4 批量设置读写指令与错位自查
8 个传感器的读写指令逐个点开配太慢,平台在传感器信息栏下方提供了批量设置入口,把起始偏置、功能码、数据类型、上报时间一次性铺开,8 条指令一起下发。批量设置省事,但也是最容易把错位埋进去的地方:如果起始偏置填成 0 而不是 1,批量出来的一整排指令全部左移一位,现象是第 8 通道没数据、前 7 个通道数据整体串位。
自查方法很土但有效:随便挑一个已知温度点(比如手握住 PT100 探头),看平台上哪个通道在动。动的那个通道编号和实际接线通道对不上,就是偏置整体偏移,回批量设置里把起始值改回 1 重新下发即可。
4. TCP 透传接云平台:自定义协议标签怎么切数据
不是所有现场都愿意走 Modbus。有些老设备只吐 ASCII 字符串,有些客户坚持自己定义报文格式,这时候就切到 TCP 透传模式。透传的灵活度高了,代价是数据格式得自己约定,并且两边必须严格一致。
4.1 透传模式的能力边界:只吃 TCP
先把边界摆清楚:透传模式只支持 TCP,不支持 UDP。所以服务器侧务必用 TCP Server 监听,用 UDP 收是永远收不到的。第二个边界是登录包——连云平台时登录包必须配成平台下发的设备序列号,因为平台靠这个字符串把 TCP 连接和设备档案绑起来;连自建服务器时登录包的内容由服务器自己约定,服务器不校验甚至可以留空。
串口参数照旧跟所接设备对齐。示例里是用 485 转 USB 把 DTU 的 485 口接到电脑上,用串口工具往平台发数据,此时 DTU 的串口参数必须和这个串口工具完全一致,波特率、校验位、数据位、停止位四项任何一个不同,平台收到的就是乱码或者干脆收不到。
4.2 协议标签语法速查
平台侧解析透传数据靠的是「协议标签」,也就是用一组带方括号的标记描述「数据头是什么、分隔符是什么、每个字段多长、结束符是什么」。这套语法不难,但括号里的大小写和长度写法必须一字不差。
| 标签 | 含义 | 示例写法 |
|---|---|---|
[H:数据]/[HE:数据] | 字符串数据头 / 16 进制数据头 | [H:#DTU] |
[S:数据]/[SE:数据] | 字符串分隔符 / 16 进制分隔符 | [S:,] |
[SN[长度]] | 已知长度分隔符 | [SN[2]] |
[D?] | 未知长度字符串数值 | [D?] |
[D[长度]] | 已知长度字符串数值 | [D[4]] |
[DE[长度]|ABCD] | 已知长度 16 进制数值 | [DE[2]|ABCD] |
[DEC[长度]|ABCD] | 已知长度 16 进制字符串数值 | [DEC[4]|ABCD] |
[DF[长度]|数据] | 已知长度 16 进制,返回浮点型 | [DF[4]|ABCD] |
[T:数据]/[TE:数据] | 字符串结束符 / 16 进制结束符 | [TE:0D0A] |
[CRC16]/[CRC8] | 校验码结束符 | [CRC16] |
结束符里没列出的校验类型(比如求和校验),可以退化成用[SN[长度]]当结束符,按固定长度截断,长度由自己定。这条兜底规则在对接一些私有协议时挺管用。
4.3 从#DTU,30.2,30.2,30.2到一帧可解析的数据
示例定义的协议是#DTU,30.2,30.2,30.2(0D0A):数据头#DTU,三组数值用英文逗号分隔,结束符是回车换行 0D0A。平台侧按这个格式配好标签,串口工具发一模一样的字符串,监控中心就能出数据。注意这里的三组数值只是样例,协议内容完全可以自定义,只要平台标签和实际报文严格对应。
import socket # 模拟 DTU 侧上来的数据流,实际是 TCP 长连接里的字节 stream = b"#DTU,30.2,30.2,30.2\r\n#DTU,30.3,30.1,30.2\r\n" HEAD, SEP, TAIL = b"#DTU,", b",", b"\r\n" def parse(buf: bytes): out = [] for line in buf.split(TAIL): # 先按结束符切帧,处理粘包 if not line.startswith(HEAD): continue # 数据头不对直接丢弃 body = line[len(HEAD):] parts = body.split(SEP) # 再按分隔符切字段 if len(parts) != 3: continue # 字段数不符视为残缺帧 out.append([float(p) for p in parts]) return out print(parse(stream)) # [[30.2, 30.2, 30.2], [30.3, 30.1, 30.2]]这段解析逻辑对应了标签配置里的三个要素:先用结束符\r\n切帧,解决 TCP 粘包;再校验数据头#DTU,,防止把心跳包或者别的杂数据当成业务帧;最后按逗号切出三个字段并转浮点。字段数不等于 3 就整帧丢弃,不做「尽力解析」——半截数据算出来的值看着合理,实际是错的,这类错误在黑匣子日志里几乎查不出来。参数上唯一要调的是字段数和结束符,换成十六进制结束符时把TAIL改成对应字节即可。
4.4 自建服务器联调:端口映射、公网 IP 与那帧 010300000008440C
没有平台账号也能把链路跑通。做法是用一台通用串口调试工具在本机起一个 TCP Server,端口示例用 9116,然后在路由器上给这台电脑做端口映射,把 9116 映射出去;DTU 的服务器地址填本机的公网 IP,端口填 9116,串口参数与所接采集模块对齐。
连接建立后,从服务器侧发010300000008440C(就是 3.3 节算出来的那帧 Modbus 请求),采集模块的应答会经 DTU 回到服务器侧:01031005C805C805D805CB05D8060B05C105D367F2。用 3.3 节的解析代码一跑,就是那 8 个温度值。
# 本机临时起一个 TCP 服务端,端口 9116,用来接 DTU 的连接 # -l 监听 -p 端口 -v 打印收发内容 -b 二进制安全 socat -v TCP-LISTEN:9116,reuseaddr,fork - # 另一个终端发一帧 Modbus 请求的十六进制(注意 CRC 低字节在前) printf '\x01\x03\x00\x00\x00\x08\x44\x0C' | socat - TCP:127.0.0.1:9116socat -v会把双向字节以十六进制打印出来,是替代商用串口服务器最省事的做法。TCP-LISTEN:9116,reuseaddr,fork里的reuseaddr让端口在进程退出后能立刻复用,fork让每个连接单独一个子进程,避免 DTU 重连时把上一个连接卡死。第二条命令里的\x44\x0C就是 CRC16 的两个字节,顺序是低字节在前,写反了从站不会应答——这个错误我在现场见过不止一次。
服务器侧如果收得到登录包但收不到业务数据,先确认服务器是不是在监听 TCP、端口映射是不是真的通了;再看 DTU 的串口参数是否和采集模块一致。这两条之外,剩下的基本就是 DTU 侧没点保存。
5. 常见故障排查:六种灯色和设备监听日志怎么对上
DTU 的排查成本低,前提是你知道去哪里看。它把绝大部分运行状态都摊在两处:外壳上的状态指示灯和配置工具里的设备监听日志。正常时绿灯常亮,异常时灯色会切到六种颜色之一,配合监听窗口打印的文字,基本能一次定位。
5.1 状态灯与监听日志的对照
| 现象(灯色) | 监听日志关键字 | 原因方向 |
|---|---|---|
| 绿灯常亮 | 正常运行 | — |
| 红灯常亮 | 模块开机失败 | 模块本身故障,联系售后 |
| 紫色闪烁 | 网络启动失败 | SIM 卡欠费,或使用地无信号 |
| 浅绿闪烁 | SIM 卡获取失败 | 卡没插到位或未识别 |
| 天蓝闪烁 | 信号弱 | 未接天线或位置遮挡 |
| 红灯闪烁 | 连接服务器失败 | 服务器地址或端口错误,服务器未开 |
这张表的价值在于把「设备不工作」这种笼统描述拆成六个可执行动作。红灯常亮是硬件问题,别浪费时间查网络;红灯闪烁是配置问题,先看服务器地址和端口号,再看服务器那边的监听是否真的起来了。
5.2 五条踩坑记录
现象:平台显示设备在线,但监控中心一直没有数据。原因:开启了掉线自检测,但心跳包内容不是 Q,或者服务器不回应答 A。解决:把心跳包改成 Q,同时确认服务器侧对每个 Q 回一个 A,两个条件必须同时满足,否则 DTU 会持续判定假连接、反复重连,重连失败还会触发重启。
现象:设备管理器里有 COM 口,配置工具刷新却一直不出设备信息。原因:COM 口选成了别的串口设备,或者端口被其他软件占用。解决:拔掉 USB 配置线看哪个口消失,锁定之后重新选;关闭可能占用该口的调试助手和上位机软件。
现象:检测 SIM 卡显示无卡,卡实际插着。原因:用了自动刷新,读取时机不对。解决:改用手动刷新再读一次。这一项必须手动刷,自动刷出现有卡检不到是已知现象,别急着拆卡座。
现象:485 上的数据一切正常,DTU 也连上了服务器,但平台解析出来的温度是 1480 而不是 14.80。原因:PT100 数据在模块内部放大了 100 倍,平台侧漏配了 ÷100 的映射。解决:给每个传感器补一条缩小 100 倍的映射,改完重下发。
现象:串口调试助手收到的全是乱码或者一堆 0x00。原因:DTU 的串口参数和所接从站不一致,四项里任意一项不同都会这样。解决:把波特率、校验位、数据位、停止位按从站设备的实际参数逐项对齐,别只看波特率。
5.3 容易误判的三处
第一处是拿 USB 配置口当调试口用。这个口只负责参数读写和设备监听日志,不转发任何业务数据,往这里发 Modbus 帧是收不到回应的,会让人误以为 485 没通。
第二处是忽略工作温度。配置工具里能读到单片机的工作温度,这一项不用配,但需要看:超过 50℃ 时 CPU 会出问题,表现可能是随机掉线或者参数读出来不对。柜内散热差的现场,这一条值得在调试阶段就确认一次。
第三处是用卡地区与型号不匹配。V2 只支持移动和联通的 2G,V4 虽说是全网通,电信 2G、3G 仍然不在支持范围内;港澳台和国外还需要特订通讯模块。这类问题在日志里表现为网络启动失败,跟信号无关,查信号强度是查不出结果的。
6. 上线前的串口自检:一份能照着跑的验证清单
我现在的习惯是:DTU 上电之前,先在串口侧把采集链路单独跑通,再接 DTU 上云。理由是这条链路上有三个独立环节——从站设备、串口参数、DTU 配置——任何一个出问题,最终表现都是「平台没数据」,从平台那头往回查等于同时排查三个变量。拆开之后,每个环节只动一个变量,出错概率和排查成本都低一个量级。
import serial from binascii import unhexlify def crc16(data: bytes) -> bytes: crc = 0xFFFF for b in data: crc ^= b for _ in range(8): crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1 return bytes([crc & 0xFF, crc >> 8]) # 直连从站设备的串口(不是 DTU 的 USB 配置口) ser = serial.Serial("/dev/ttyUSB1", 9600, bytesize=8, parity=serial.PARITY_NONE, stopbits=1, timeout=2) req = unhexlify("010300000008") ser.write(req + crc16(req)) resp = ser.read(64) # 三重断言:从站地址、功能码、字节数、CRC,缺一不可 assert len(resp) == 21, f"帧长异常:{len(resp)}" assert resp[0] == 0x01 and resp[1] == 0x03, "从站地址或功能码不符" assert resp[2] == 0x10, "有效字节数不是 16" assert resp[-2:] == crc16(resp[:-2]), "CRC 校验失败" raw = [int.from_bytes(resp[3 + i:5 + i], "big") for i in range(0, 16, 2)] print("通道原始值:", raw) print("换算温度:", [round(v / 100, 2) for v in raw])四个断言对应四个最常见的失败模式:帧长不对通常是波特率或数据位错;从站地址或功能码不符说明总线上还有别的设备在应答,或者地址填错;字节数不是 16 说明从站寄存器映射和预期不一致;CRC 失败基本就是校验位或停止位没对上。逐条看输出,比在平台上反复刷新快得多。
上云之前把下面这张清单过一遍,每项都打勾再动手接 DTU:
| 检查项 | 合格标准 |
|---|---|
| 串口直连从站 | 上述脚本四个断言全过 |
| 数值缩放 | 除以 100 后的温度落在合理区间 |
| 从站地址与寄存器映射 | 地址 0 对应第 1 通道,无整体偏移 |
| DTU 串口参数 | 与从站四项完全一致 |
| 服务器地址与端口 | 端口通,TCP 可达(不是 UDP) |
| 登录包 | 与平台设备序列号或服务器约定一致 |
| 心跳包与掉线自检测 | 内容为 Q,服务器会回 A |
| 保存与重启 | 先保存配置,再重启设备 |
这张表里最容易漏的是最后一项。我吃过一次亏:参数全对,平台一直没数据,从 SIM 卡查到服务器端口查了两小时,最后发现是改完之后直接点了重启没点保存。从那以后我每次改完参数都强制走一遍「保存 → 重启 → 看设备监听日志」这三步,日志里打印出连接服务器成功才去平台看曲线。希望帮到你。
本文还有配套的精品资源,点击获取