简介:这份资源围绕MCGS组态软件中的串口数据收发技术展开,面向工业自动化领域的组态开发人员、设备调试工程师以及需要实现设备间串行通信的初学者与进阶者。内容聚焦串口参数配置、通信对象建立、自由口协议下的数据收发与解析,以及超时重试、异常处理等排错思路,可帮助读者理解MCGS与PLC、仪表、传感器等硬件交互的完整流程。压缩包共5个文件,以drv驱动文件、chm帮助文档、htm说明页和dll动态库为主,分别承担串口驱动支持、协议说明与功能调用等用途,整体约142KB,体积轻便便于随工程携带查阅。目前已有920人学习下载,适合希望快速掌握MCGS串口通信配置与自由口协议应用、并对照实例排查通信问题的读者参考。
1. 拆开这个 MCGS 串口收发包:工控屏和单片机到底怎么对上话
现场调试最让人头大的场景之一,就是触摸屏和 PLC 或单片机之间数据对不上。屏上显示 25.6,实际仪表读数是 25.4;按下启动按钮,设备没反应,查了半天发现是串口参数配错了。这类问题十有八九出在串口通信的配置环节,而不是程序逻辑本身。Mcgs_串口数据收发.zip这个资源包,解决的就是 MCGS 触摸屏与下位机之间通过串口收发数据的问题。它适合两类人:一是刚接触工控组态、需要快速跑通串口通信的现场调试人员;二是已经会用 MCGS 画界面,但一碰到自由协议或 Modbus 就卡住的电气工程师。包里通常包含组态工程文件、设备配置说明和调试记录,拿到手可以直接对照自己的硬件改参数。
2. MCGS 串口通信的底层逻辑:从设备窗口到数据对象
2.1 串口收发的三个核心环节
MCGS 的串口通信不是“配好就能通”的黑匣子,它内部走的是三层结构:设备窗口负责硬件驱动和协议解析,实时数据库负责数据缓存,用户窗口负责画面呈现。串口数据从下位机上来,先经过设备窗口的“设备构件”完成帧解析,再写入实时数据库的对应变量,最后画面上的控件通过变量名绑定刷新。反过来,画面上按钮触发的变量变化,也是先写数据库,再由设备构件按周期下发。
这个链路里最容易断的是设备构件配置。很多人只填了串口参数,没配“设备地址”和“采集周期”,结果数据要么不刷新,要么刷新频率和实际需求差十倍。常见做法是:采集周期设 200ms 到 500ms,设备地址和下位机程序里写的从站地址严格一致。如果下位机是自定义协议,设备构件要选“通用串口父设备”加“自由协议”子设备,而不是直接选 Modbus RTU。
2.2 父设备与子设备的挂载关系
MCGS 的设备窗口里,串口通信必须有一个“通用串口父设备”作为根节点,下面挂具体协议的子设备。父设备管的是物理层参数:波特率、数据位、停止位、校验位、串口号。子设备管的是协议层参数:设备地址、帧格式、寄存器映射。
一个父设备下可以挂多个子设备,但前提是这些子设备共用同一组串口参数。如果现场有两台不同波特率的仪表,就得建两个父设备,分别对应不同的 COM 口或不同的波特率配置。我见过有人把 9600 和 19200 的设备挂在同一个父设备下,结果只有一台能通,另一台始终超时。这不是玄学,是物理层参数冲突。
2.3 实时数据库变量的类型匹配
串口读上来的数据写入实时数据库时,变量类型必须和下位机的数据格式对齐。下位机发的是 16 位无符号整数,数据库变量就设成“数值型”并指定“无符号整数”;下位机发的是浮点数,数据库变量要设成“数值型”并选“浮点数”,同时注意字节序。
字节序这个问题坑了很多人。下位机用 C 语言发的 float,内存里是小端模式,但 MCGS 默认按大端解析,结果读上来是乱码。解决办法是在设备构件的“数据处理”里勾选“交换高低字节”或“交换高低字”,具体勾哪个取决于下位机的字节序和 MCGS 版本的默认行为。常见做法是:先发一个已知值比如 1.0,看读上来是不是 1.0,不是就调字节序,调对了再继续。
3. 从零跑通一次串口收发:配置步骤与代码对照
3.1 下位机发送帧的构造
假设下位机是单片机,通过串口向上位机发送一帧数据:帧头 0xAA、数据 2 字节(整数)、校验和 1 字节、帧尾 0x55。用 C 语言构造这帧数据的常见写法如下:
// 下位机发送帧:帧头0xAA + 数据高字节 + 数据低字节 + 校验和 + 帧尾0x55 void send_frame(uint16_t value) { uint8_t buf[5]; buf[0] = 0xAA; // 帧头 buf[1] = (value >> 8) & 0xFF; // 数据高字节 buf[2] = value & 0xFF; // 数据低字节 buf[3] = buf[1] ^ buf[2]; // 校验和:高字节异或低字节 buf[4] = 0x55; // 帧尾 uart_send_bytes(buf, 5); // 串口发送5字节 }这段代码的关键在于帧结构要固定。帧头帧尾用来做帧同步,校验和用来判断数据是否在传输中出错。异或校验是最简单的,现场也够用。如果下位机发的数据量更大,可以改成 CRC16,但 MCGS 的自由协议构件对 CRC 的支持需要手动写脚本,不如异或来得直接。
3.2 MCGS 自由协议构件的脚本编写
在 MCGS 的设备窗口里,父设备选“通用串口父设备”,子设备选“自由协议”。自由协议构件里有一个“脚本程序”入口,用来写帧解析逻辑。下面是一个典型的解析脚本:
' MCGS 自由协议脚本:解析 0xAA 开头、0x55 结尾的 5 字节帧 ' 假设接收缓冲区为 RecvBuf,长度为 RecvLen If RecvLen >= 5 Then If RecvBuf(0) = &HAA And RecvBuf(4) = &H55 Then ' 校验和验证 If RecvBuf(3) = (RecvBuf(1) Xor RecvBuf(2)) Then ' 合成 16 位整数并写入数据库变量 DataValue = RecvBuf(1) * 256 + RecvBuf(2) ' 清空缓冲区,准备下一帧 RecvLen = 0 End If End If End If这段脚本的逻辑是:先判断帧头和帧尾是否匹配,再验证校验和,最后把两个字节合成一个整数写入数据库变量DataValue。参数说明:RecvBuf是接收缓冲区数组,RecvLen是当前缓冲区里的字节数,DataValue是实时数据库里绑定的数值变量。注意 MCGS 的脚本里异或运算符是Xor,不是^,写错了编译不报错但逻辑不对。
3.3 上位机下发命令的帧构造
上位机往下位机发命令时,帧结构可以更简单:帧头 0xBB、命令字 1 字节、数据 1 字节、帧尾 0xEE。在 MCGS 里,下发帧通常通过“设备构件”的“发送数据”功能触发,或者在脚本里调用!SendData函数。常见做法是:在用户窗口放一个按钮,按钮的“按下”事件里写脚本,把要发的数据填入发送缓冲区,然后调用发送函数。
' 按钮脚本:向下位机发送启动命令 SendBuf(0) = &HBB ' 帧头 SendBuf(1) = &H01 ' 命令字:启动 SendBuf(2) = &H00 ' 数据:保留 SendBuf(3) = &HEE ' 帧尾 SendLen = 4 ' 发送长度 !SendData(设备名, SendBuf, SendLen) ' 调用发送函数这里设备名要替换成实际设备构件的名称,SendBuf是发送缓冲区数组。注意发送长度必须和实际字节数一致,多发了下位机会把后面的字节当成新帧的帧头,少发了下位机等不到帧尾,两种情况都会导致通信异常。
3.4 联调时的最小验证方法
配置完成后不要直接上完整工程,先用最小系统验证。下位机写一个死循环,每 500ms 发一次固定值 0x1234。MCGS 这边只建一个数值变量,绑到画面上的标签。下载工程后看标签是否显示 4660(0x1234 的十进制)。如果显示不对,先查字节序;如果不刷新,查采集周期和串口参数;如果显示 0,查设备地址和帧解析脚本。
这个最小验证能跑通,再逐步加变量、加命令、加逻辑。我一般会在这个阶段用串口助手同时监听,确认下位机确实在发,MCGS 确实在收。串口助手和 MCGS 不能同时占用同一个 COM 口,所以要么用两个串口,要么先抓包再单独跑 MCGS。
4. 避坑排查:串口通信里那些让人翻车的细节
4.1 现象:数据偶尔跳变,大部分时间正常
原因:串口线没有屏蔽层,或者走线经过变频器、伺服驱动器附近,电磁干扰导致个别字节出错。校验和能挡住一部分,但如果干扰发生在帧头或帧尾,整帧会被丢弃,表现为数据偶尔不刷新。
解决:换屏蔽双绞线,屏蔽层单端接地;走线远离动力线,间距至少 20cm;如果干扰无法避免,把校验和从异或改成 CRC16,并在脚本里加超时重发机制。
4.2 现象:MCGS 显示“设备无响应”,但串口助手能收到数据
原因:MCGS 的设备地址和下位机程序里的从站地址不一致,或者采集周期设得太短,下位机还没处理完上一帧,MCGS 又发了下一帧。
解决:先核对设备地址,Modbus RTU 里从站地址是 1 到 247,自由协议里地址可以是任意值但必须双方约定一致。采集周期不要低于 100ms,下位机处理慢的话设 500ms 以上。如果下位机是轮询式处理,MCGS 的采集周期要大于下位机的轮询周期。
4.3 现象:浮点数读上来是乱码或极大值
原因:字节序不匹配。下位机用的小端模式,MCGS 默认按大端解析,或者反过来。
解决:在设备构件的“数据处理”里调整字节序。常见做法是先用整数测试,整数对了再换浮点数。如果整数也不对,先查波特率和数据位,波特率错了连帧头都收不到。
4.4 现象:按钮按下去没反应,下位机收不到命令
原因:发送脚本里的设备名写错了,或者发送缓冲区长度和实际字节数不一致,或者按钮事件绑错了(绑到了“弹起”而不是“按下”)。
解决:检查脚本里的设备名是否和设备窗口里的构件名完全一致,包括大小写。发送长度用Len函数动态计算,不要写死。按钮事件确认绑在“按下”或“执行”上,不要绑到“弹起”。
4.5 现象:工程下载后串口打不开,提示“串口被占用”
原因:MCGS 运行版和组态版同时打开了同一个工程,或者串口助手没关,或者上一次运行异常退出导致串口句柄没释放。
解决:关掉所有可能占用串口的程序,包括串口助手、其他组态软件、调试工具。如果还不行,重启电脑。MCGS 运行版和组态版不要同时开同一个工程,调试时只开一个。
5. 进阶技巧:用脚本做超时重发和通信状态指示
5.1 超时重发的实现思路
自由协议构件本身不带重发机制,但可以在脚本里加一个计数器。每次发送命令后启动一个定时器,如果在设定时间内没收到正确响应,就重发一次,重发三次仍失败则报警。
' 超时重发脚本片段 If SendFlag = 1 Then TimeoutCount = TimeoutCount + 1 If TimeoutCount > 30 Then ' 30个周期约3秒 RetryCount = RetryCount + 1 If RetryCount <= 3 Then !SendData(设备名, SendBuf, SendLen) ' 重发 TimeoutCount = 0 Else CommAlarm = 1 ' 报警标志置位 RetryCount = 0 SendFlag = 0 End If End If End If这段脚本放在“循环脚本”里,执行周期设为 100ms。SendFlag在发送命令时置 1,收到正确响应后清 0。TimeoutCount累计超时周期数,RetryCount记录重发次数。参数说明:30 个周期对应 3 秒超时,这个值根据下位机响应速度调整,响应慢的设备可以设 50 到 100。
5.2 通信状态指示灯的绑定
在画面上放一个指示灯控件,绑定到CommAlarm变量。正常通信时CommAlarm为 0,指示灯绿色;超时重发失败后CommAlarm置 1,指示灯红色。这样操作工一眼就能看出通信是否正常,不用打开调试工具。
5.3 数据记录与趋势曲线
MCGS 的实时数据库变量可以绑定到“数据对象”里的“存盘数据”,设置存盘周期后,历史数据会自动写入数据库。趋势曲线控件绑定这个变量,就能看到数据变化趋势。常见做法是:存盘周期设 1 秒,曲线显示最近 10 分钟的数据。如果数据量太大,存盘周期改 5 秒或 10 秒。
5.4 一个容易被忽略的细节:脚本执行周期
MCGS 的循环脚本执行周期默认是 200ms,但串口通信的采集周期可能设的是 100ms。如果脚本执行周期大于采集周期,会出现数据积压,表现为画面刷新滞后。我一般会把循环脚本的执行周期设成和采集周期一致,或者更短。但也不能太短,太短会占用 CPU,导致画面卡顿。200ms 到 500ms 之间是比较稳妥的范围。
从那以后我每次配完串口通信,都会先用最小系统跑一遍,确认数据能通、字节序对、按钮能发命令,再往上加逻辑。这个习惯帮我省了很多返工的时间。希望帮到你。
本文还有配套的精品资源,点击获取