
最近给一个单位做了一套知识竞赛用的八人抢答器主控用的是手头现成的西门子S7-200 PLC上位界面用MCGS 7.7组态触摸屏来实现。整套东西从需求梳理、PLC程序设计、MCGS画面组态到现场联调前前后后折腾了将近一周。把这个项目完整记录下来是因为它虽然看起来简单但实际做的时候牵扯到状态机设计、位变量映射、PPI通讯参数匹配这些细节任何一个点不注意都会翻车。如果你手头正好有S7-200和MCGS触摸屏想做个类似的抢答、倒计时、顺序判断类装置这篇文章应该能帮你少走不少弯路。1. 需求拆解抢答器不是谁先按谁亮灯那么简单1.1 从比赛场景反推功能清单做任何设备之前先把使用场景想明白。八人抢答器用在哪里通常就是知识竞赛、技术比武、安全培训答题这类场合一名主持人八名选手或者八个代表队每人面前一个抢答按钮主持人口令一落选手按铃大屏幕或者抢答器面板要立刻显示谁抢到了。听起来很简单但真正到实际比赛里光谁先按谁亮灯是不够的还要考虑几个竞赛场景里的硬性要求。第一是分组抢答状态也就是主持人没有发出抢答口令之前选手提前按下按钮这算犯规系统要能记录并且提示。犯规这东西在实际比赛中比抢答成功还要重要不然大家都抢跑比赛根本没法组织。第二是超时判定比如主持人问完问题限时30秒没人抢答系统要提示超时本轮作废不能一直处于等待抢答的悬挂状态。第三是本轮锁定一旦有人抢答成功其他选手再按就无效了系统要锁死本轮状态不能出现后面的人把前面的人顶掉的情况。第四是轮次复位主持人确认答题正确或者错误之后一键清空本轮所有状态进入下一题。这些功能需求直接决定了PLC程序的写法。如果只是做一个谁先按谁亮灯的演示程序那用几个置位指令就够了根本不需要搞状态机设计。但真实项目里提前犯规、超时锁定、本轮互斥、一键复位这四件事缺一不可。1.2 与纯数字电路抢答器的本质差异学校实验室里如果用74LS148加数码管做过八人抢答器会发现那个方案的逻辑其实很死编码器输出优先编码谁接的引脚号小谁优先顺序固定而且犯规检测、超时判断这些功能全靠外围组合逻辑堆积改一个功能就得改电路板。PLC方案的本质区别在于判断逻辑是顺序扫描的软件逻辑而不是并行的硬件逻辑。你可以在程序里灵活定义犯规超时锁定这些状态可以在运行中随时修改判断条件可以让MCGS触摸屏把内部状态全部可视化。这是PLC加组态方案最大的价值——逻辑和显示分离修改方便排障直观。所以这个项目别看只是八个按钮加八个灯它背后的设计思路其实是一个典型的小型状态机程序的完整落地。做完这个项目你对S7-200的位逻辑、定时器、比较指令、MCGS的变量映射和脚本联动都会有一个比较系统的认识。2. 硬件选型与IO规划S7-200的资源分配2.1 为什么用老款S7-200而不是S7-200 Smart先说一个绕不开的问题S7-200这个系列其实早就停产了现在西门子主推的是S7-200 Smart。为什么这个项目还用老的S7-200原因很实际。MCGS 7.7这个组态软件对老款S7-200的PPI通讯支持非常成熟驱动稳定通道地址直接填V区地址就行不用额外配置GSD文件或者OPC服务器。而且S7-200在实验室、中职院校、培训机构里存量非常大很多单位手里正好有几台闲置的CPU 224用起来零成本。S7-200 Smart当然也能做但要用以太网或者Modbus RTU去连MCGS配置路径不一样反而多一层适配问题。如果你手头是S7-200 Smart这篇文章的PLC程序逻辑依然可以借鉴只是通讯驱动要换成Modbus TCP或者以太网驱动地址映射方式要调整程序主体结构完全通用。但本文以经典的CPU 224为例来展开。2.2 IO点分配与接线方案八人抢答器需要多少IO点算一下输入8个选手抢答按钮1个主持人开始按钮1个主持人复位按钮一共10个输入。输出8个选手状态指示灯1个允许抢答指示灯1个超时指示灯一共10个输出。这个需求用CPU 224刚好14个数字量输入、10个数字量输出点数卡得很准。如果你手里是CPU 221或者CPU 222输入输出点数不够就得想办法复用IO比如犯规状态不单独输出只在触摸屏上显示这样能省下输出点。再往下细化一下输入输出分配地址功能说明I0.0-I0.7选手1-8抢答按钮常开触点按下为1I1.0主持人开始抢答按钮常开触点按下为1I1.1主持人复位按钮常开触点按下为1Q0.0-Q0.7选手1-8抢答指示灯高电平点亮Q1.0允许抢答指示灯激活时点亮提示可以抢答Q1.1超时指示灯超时后点亮接线上有几个细节要提醒你。按钮统一选**瞬动型自复位按钮**而不是自锁型。我见过有人在现场拿自锁按钮做抢答器按下去之后触点一直保持闭合抢答程序判断一次就永远触发复位逻辑极其别扭。抢答按钮必须按下去接通、松手断开这样程序才能根据上升沿或者扫描周期内的状态变化来判断这一次按下。接线时所有按钮的常开触点一端接到PLC对应输入点另一端统一接到PLC的1M或者2M公共端。S7-200 CPU 224默认是漏型输入公共端接24V电源的负极。输出侧驱动指示灯建议直接用24V LED指示灯接到Q输出点输出公共端1L、2L接24V电源正极。每个输出点的驱动能力是有限的虽然24V指示灯电流很小但还是要算一下总电流不要超过公共端允许值。实际做下来CPU 224带10个LED灯完全没压力。这里有个工程上的小建议抢答按钮的接线端子统一用带编号的中间端子排过渡不要直接往PLC端子上压线。现场调试的时候要换按钮、查线路端子排会让你省很多事。3. PLC程序核心设计状态机、互锁与超时处理3.1 存储区布局规划写S7-200程序之前先把V存储区变量规划好。M区只能在PLC内部用MCGS读不到所以要给触摸屏层面保留V区变量。我设计的变量表是这样的地址变量名数据类型说明V100.0-V100.7QiangDa_Bit1-8位选手1-8抢答成功标志V101.0Start_Flag位允许抢答标志置1表示本轮激活V101.1Timeout_Flag位超时标志V102.0-V102.7FanGui_Bit1-8位选手1-8犯规标志VB103Winner_Num字节当前抢答成功选手编号0为无1-8对应选手VB104Time_Left字节剩余秒数供MCGS显示倒计时这个规划是MCGS联调能顺利走下去的前提。MCGS里面看到的变量全部要能在这一张表里找到对应地址。如果你写程序的时候V区地址东一个西一个很随意后面组态时保证出错来回排查非常痛苦。3.2 抢答判断与互锁逻辑的STL描述抢答器的灵魂逻辑是本轮第一个按下的人有效其余人全部无效。从程序角度来说最常见也最可靠的实现方式不是用复杂的比较指令而是用允许抢答标志V101.0作为统一闸门。整个程序的核心逻辑用STL语句写出来大概是这样Network 1 // 主持人按下I1.0且当前没有正在进行的抢答轮次则置位允许抢答标志 LD I1.0 AN V101.0 EU S V101.0, 1 Network 2 // 选手1抢答判断按钮按下 且 允许抢答 则置位抢答成功标志并锁定 LD I0.0 A V101.0 EU S V100.0, 1 // 选手2-8同理每个选手一个网络 Network 3 // 只要任何一个选手抢答成功就清除允许抢答标志其他选手再按无效 LD V100.0 O V100.1 O V100.2 O V100.3 O V100.4 O V100.5 O V100.6 O V100.7 R V101.0, 1 Network 4 // 有抢答成功者写入编号 LD V100.0 MOVB 1, VB103 // 选手2-8类似这组STL的逻辑核心是用V101.0当作一个总闸门一旦闸门关掉后面扫描到的选手即使已经按下按钮也不会触发。PL C是顺序扫描程序从Network 1扫到Network N先扫描先判断的人天然获得优先权。如果两个选手在同一个扫描周期内都按下按钮程序先处理谁谁就抢到了。这在实际比赛中完全符合先按先得的直觉。这里有个容易踩的坑EU指令上升沿。抢答按钮是瞬动按钮但PLC扫描周期极短一个周期内可能检测不到按下到松开的完整过程。如果不加EU用手一直按着按钮程序会反复执行置位指令这在置位位逻辑下问题不大置位1之后还是1但在后面做犯规判断时就会出麻烦——比如你想用手按着按钮2秒然后程序发现状态已经是犯规了。为了避免这类问题我建议所有选手按钮输入都加EU上升沿把一次按下作为一个事件处理。这在梯形图里很好操作对应指令就是右下角的P上升沿触点。3.3 犯规检测的边界条件设计犯规检测是抢答器的隐形需求。实际比赛里最热闹的环节就是主持人还没说开始有人已经按了。犯规逻辑怎么判断核心是区分三种状态本轮未激活主持人还没按开始、本轮激活中可以正常抢答、本轮已结束有人成功抢答或超时。只有在本轮未激活状态下按下按钮才判定为犯规。程序实现上我的判断条件是选手按钮上升沿触发而且V101.0允许抢答标志为0而且当前还没有人抢答成功VB103等于0则置位该选手的犯规标志V102.x。// 以选手1犯规检测为例 LD I0.0 EU AN V101.0 AN V100.0 AN V100.1 AN V100.2 AN V100.3 AN V100.4 AN V100.5 AN V100.6 AN V100.7 S V102.0, 1这个程序段有个关键的坑如果不检查当前还没有人抢答成功这个条件那么超时后、本轮结束后有人随便碰一下按钮也会被判犯规这显然不合理。比如有人抢答成功正在答题旁边观众不小心碰到按钮屏幕上突然显示犯规比赛就乱套了。3.4 超时定时与倒计时刷新超时功能我用S7-200的T37定时器100ms时基实现。设计超时时间为30秒所以PT预设值设为300。逻辑如下Network 10 // 允许抢答期间启动超时定时器 LD V101.0 TON T37, 300 Network 11 // 定时器时间到置位超时标志清除允许抢答 LD T37 S V101.1, 1 R V101.0, 1倒计时剩余秒数VB104要在定时器运行期间不断刷新方便MCGS触摸屏显示。T37的当前值是100ms单位所以剩余秒数 (300 - T37当前值) / 10。S7-200的整数除法没有四舍五入直接用整数除法就行剩几秒显示几秒视觉上稍微有点跳变但现场没人较真这个。Network 12 // 每秒刷新剩余时间 LD V101.0 MOVW T37, VW106 MOVW VW106, VW108 -D 300, VW108 // 这里注意S7-200的减法格式是 SUB_I IN1, IN2结果存IN2 MOVW VW108, VW110 /I 10, VW110 MOVB VW110, VB104 // 这里VB104传的是低字节但实际要把VW110低字节转成VB104写到这里得坦白说一句倒计时刷新这段在S7-200里其实可以用更简单的算术指令组合实现但如果你对S7-200的STL指令不熟在Micro/WIN里直接从梯形图拖算术运算框会更直观。无论用哪种方式关键是理解定时器当前值的单位换算。另外就是S7-200定时器当前值的读取要在T37输出有效的扫描周期内才更新所以放在Network 10、11后面扫描。3.5 复位逻辑复位逻辑相对简单但要覆盖全面。按下I1.1复位按钮必须完成这些事清除所有选手抢答成功标志V100.0-V100.7清除所有选手犯规标志V102.0-V102.7清除允许抢答标志V101.0清除超时标志V101.1清零成功选手编号VB103复位定时器T37用S7-200的字节复位指令可以很干净地实现LD I1.1 R V100.0, 8 // 复位V100.0开始的8个连续位 R V102.0, 8 R V101.0, 2 MOVB 0, VB103 R T37, 1这里有个经验之谈复位后务必把定时器T37也复位掉否则下一轮开始时定时器会从上次残留的当前值继续走导致超时时间变短甚至一进激活状态就立刻超时。这属于典型的定时器残留问题调程序时最容易漏掉。4. MCGS 7.7组态设计画面、变量映射与脚本联动4.1 画面布局与控件选择MCGS 7.7嵌入版组态环境做画面相当于是给触摸屏画界面。我用的是MCGS的TPC系列触摸屏工程在电脑上做好下载到屏幕运行。画面布局我分成四个区域顶部是标题八人抢答器中间一排是8个选手的指示灯和状态文本每个选手一个灯一个名字标签右侧是当前状态区显示等待开始请抢答×号选手抢答成功×号选手犯规本轮超时等状态文字底部是两个大按钮对应开始抢答和本轮复位。指示灯控件我用的是MCGS的位指示灯图元配合不同颜色区分状态选手灯灰色未动作绿色抢答成功红色犯规允许抢答提示灯黄色常亮表示主持人已允许抢答MCGS里这些颜色变化不需要写任何脚本直接在位指示灯控件的属性里配置开关量0状态颜色开关量1状态颜色就行。如果你想让选手抢答成功的时候灯闪烁还得在动画属性里勾选闪烁选项并设置闪烁周期。这个做出来效果很直观现场观众一眼就能看出谁抢到了。4.2 驱动配置与变量连接的关键点MCGS联S7-200用的是PPI驱动。设备窗口里添加西门子S7-200PPI父设备串口参数要特别注意波特率9600与PLC通讯口波特率保持一致。S7-200的PPI默认就是9600但如果之前有人改过系统块设置这里就会对不上。如果现场通讯不上第一件事就是去Micro/WIN的系统块里看通讯口的波特率设置。数据位8、停止位1、偶校验这是PPI协议默认参数。用USB-PPI编程电缆的话电脑设备管理器里要确认虚拟串口号MCGS里选对应的COM口。父设备建好之后接下来就是建立通道连接。这一步是整个MCGS组态里最核心、也最容易出错的地方。通道连接的本质就是把PLC变量地址映射到MCGS的数据库变量。比如选手1的抢答成功标志V100.0你需要在通道连接里新增一个通道类型选位地址填V100.0。每一个要读写的V区变量都要建一个通道。我建的通道变量和实时数据库变量的对应关系大概是这样MCGS实时数据库变量通道地址读写属性Player1_SuccessV100.0只读Player2_SuccessV100.1只读.........Player8_SuccessV100.7只读StartFlagV101.0只读TimeoutFlagV101.1只读Player1_FanGuiV102.0只读.........Player8_FanGuiV102.7只读Winner_NumVB103只读Time_LeftVB104只读看到区别没有按钮用的V105.0、V105.1是读写型的状态显示用的全是只读型。这个区分不做好MCGS可能会把你的只读变量也给写成0导致PLC端状态被意外清掉程序怪一阵子才发现是上位机在捣乱。这里必须单独讲一个MCGS和S7-200配合最容易栽的坑S7-200的V区位地址在MCGS通道里地址格式必须写完整。比如V100.0表示字节地址100的bit0通道类型必须选位不能选字节更不能选字。如果你建通道时为了图省事把V100.0写成V100或者VB100然后类型选位那么MCGS读取的地址会偏掉显示的数据完全不是预期值。我调试时吃过这个亏画面全是乱的排查了很久才发现是通道地址格式写错了。4.3 触摸屏软按钮的脚本实现前面讲PLC输入时主持人按钮接的是I1.0和I1.1。实际做下来发现触摸屏上有操作员值守主持人完全可以不用物理按钮直接在触摸屏上点开始和复位这样还能少接两根线。但前面提过S7-200的输入点I区是只读的触摸屏不能直接写I1.0。解决办法是在V区预留两个软按钮位让PLC程序去读取这两个位效果和物理按钮一样。我在V区额外预留两个地址V105.0软件复位按钮标志MCGS写PLC读V105.1软件开始按钮标志MCGS写PLC读然后把PLC程序里复位和开始的触发条件改成或逻辑// 复位触发I1.1按下 或者 V105.0被MCGS置位 LD I1.1 O V105.0 EU // 复位动作... // 开始触发I1.0按下 或者 V105.1被MCGS置位 LD I1.0 O V105.1 EU // 开始动作...MCGS这端的按钮操作取按1松0方式按钮按下时置位V105.1松开时清零。配合PLC程序里的EU上升沿MCGS按钮按一次PLC端就在上升沿触发一次开始逻辑。这套软按钮方案我用下来很稳定而且不用改动任何硬接线想从物理按钮切换到触摸屏按钮把PLC程序里O V105.0那句去掉就行调试非常方便。MCGS按钮具体配置在按钮控件的按下动作里写!WriteToDevice(设备0, 通道地址, 1)松开动作里写!WriteToDevice(设备0, 通道地址, 0)。注意设备0要替换成你实际建立的设备名称通道地址填V105.1这样的完整地址。5. 联调阶段踩过的坑通讯、抖动的显示异常5.1 通讯不上的排查链路所有组态画面和PLC程序都在电脑上做好之后下载到触摸屏开始联调。第一个遇到的就是通讯问题触摸屏上变量全部显示####或者不刷新PPI通道状态闪烁红色。这个问题的排查要有顺序不要一上来就怀疑电缆坏。我按下面的链路排查每次都很快定位第一步看触摸屏的串口参数是否和PLC一致。MCGS里PPI驱动默认波特率是9600但S7-200如果系统块被改成了187.5K波特率两边就对不上。用Micro/WIN连接PLC在系统块里查看通讯口的波特率设置两边对齐。第二步看通讯电缆。S7-200的PPI口是RS485触摸屏的COM口通常也是RS485但不能直接拿根普通的USB转232线接。必须用带RS485电平转换的PPI电缆或者触摸屏COM口定义和PLC编程口定义一一对应的专用电缆。网上买的USB-PPI电缆有的质量不行通讯偶尔通偶尔断这种情况下别犹豫直接换一根排除嫌疑。第三步看触摸屏工程里面的设备窗口有没有把串口父设备和S7-200子设备都勾选启用。有时候父设备启用了子设备被不小心禁用了也会导致断连。检查方法在MCGS组态环境里双击子设备看状态是否为启用。5.2 按钮抖动与误触发问题联调过程中出现了一个经典的干扰问题选手抢答时触摸屏上显示选手3犯规但实际没人碰选手3的按钮旁边选手1猛拍桌子选手3就犯规了。这个问题的根源是瞬动按钮的机械抖动加现场电磁干扰。选手用力拍按钮的时候触点不是一次稳定闭合而是有几个毫秒的抖动加上现场音箱、灯光、手机信号的干扰PLC输入端可能收到一串毛刺脉冲。S7-200的数字量输入本身有滤波时间设置可以在系统块里配置输入滤波器。CPU 224的输入滤波延时可选的档位里抢答器这种场合建议把滤波器时间提高到6.4ms左右这样可以过滤掉大部分抖动毛刺。注意滤波时间设太长也不行我试过12.8ms快速连续按按钮会出现漏检测的情况。如果你不想改系统块还有一个软件办法在程序里对每个输入加双周期确认逻辑即输入点连续两个扫描周期都是1才认为是有效按下用一个中间继电器变量做延时确认。这个方法不占额外硬件但占程序空间实际效果也很好。5.3 MCGS变量类型不匹配的显示异常还有一个让我排查了很久的恶心问题触摸屏上倒计时数字显示正常但选手1的指示灯有时候会自己变成绿色没有任何人按过那个按钮。后来发现是通道地址重叠。我在通道连接里同时建了V100.0位和VB100字节。S7-200的V区位和字节是重叠的V100.0到V100.7就是VB100的全部8个位。MCGS一旦对VB100做了字节型读取相当于一次读8个位如果某个选手的位发生变化字节值也随之改变而MCGS的实时数据库里多个变量都指向了同一块物理地址刷新时序不一样就出现了指示灯互相串扰的假象。解决方法是统一位访问方式在建通道时严格按位变量建通道把VB100这种字节型通道删掉全部用V100.x这种位通道。如果你确实需要读整个字节比如读选手号VB103那就单独用字节通道不要和位通道混在同一个字节地址上。这个坑让我反思了一个道理MCGS与PLC变量映射是PLC组态联调里最容易出隐蔽问题的地方。你在PLC里觉得V区是一块连续内存怎么用都行但在MCGS里每个通道的访问粒度必须严格一致否则就会出现看起来变量都对实际数据全串的诡异现象。6. 这套方案的扩展方向与工程习惯建议6.1 从八人抢答器到答题计时系统的扩展这个抢答器的架构最大的价值在于它不是一个写死的演示工程而是一个可以快速扩展的框架。如果客户现场要求加答题倒计时比如抢答成功后给选手60秒作答时间只需在PLC程序里再加一个定时器T38抢答成功标志置位时启动同时把剩余时间存到VB107这样的新变量MCGS画面再放一个大的倒计时数字控件就行。整个逻辑结构和已经调通的超时定时、倒计时刷新完全一致可以说是复制粘贴再加两行。如果现场要改成功计分比如抢答正确加10分错误扣5分可以在MCGS端用脚本实现把每轮胜者的得分累加显示在画面上。数据不经过PLC纯组态就能完成开发效率很高。如果要做12人抢答CPU 224的IO点数不够硬件上换CPU 226就能直接支持24入16出程序逻辑只需把选手模块从8个复制到12个V区变量名后缀相应扩展其他几乎不用动。我做了几个抢答器项目的体会是程序状态机一旦搭对扩展只是体力活。6.2 几个值得记住的工程习惯总结这套抢答器项目有几条经验是我觉得放之四海而皆准的写下来分享给你。第一做PLC项目之前在纸上把V区变量表规划好。包括地址、数据类型、读写属性、对应功能全部写清楚再动手写程序。这能避免后期MCGS联调时来回改地址省下的时间远超规划时间。第二MCGS通道连接里位地址和字节地址不要混用在同一区域。S7-200的位和字节在内存上是重叠的MCGS的通道按类型解析混用极易串数据。这是血泪教训切记。第三输入信号尽量用上升沿EU处理。瞬动按钮这类信号用上升沿可以把一次按下定义为一个事件程序逻辑会干净很多。如果不加EU你后面的犯规判断、状态切换都会很难写。第四现场联调时备一个串口监控工具或者至少一个简单的串口助手。S7-200的PPI通讯问题如果能在电脑上用串口助手看数据帧判断是线缆问题还是协议问题比盲猜快非常多。我调通讯那次就是用串口助手确认了电缆的RX/TX信号正常才把怀疑重心转移到PLC通讯参数上。做完这个项目最直观的感受是抢答器这个题目看起来是PLC入门级项目但它把位逻辑、定时器、状态标志、通讯映射、组态联动这些PLC应用的基本功全串起来了。能把这种简单项目做到稳定可靠、界面直观、现场不出幺蛾子比跑通一百个Demo程序都有用。下次再遇到类似的功能需求你可以放心大胆地接。