☰
S7-1200八段LED与交通灯双实验:从编译报错到HMI点动生效
2026/10/15 19:37:54 网站建设 项目流程

简介:本资源是一份面向电气工程及其自动化专业本科生的PLC实践教学文档,聚焦S7-1200可编程控制器在八段LED显示与智能交通灯控制两大典型场景中的综合应用。内容覆盖TIA Portal V13项目创建、梯形图编程、HMI触摸屏界面设计(含KTP700)、变量绑定、动画配置及仿真验证全流程,特别包含定时器编号冲突等真实排错案例与课后拓展任务(如三数码管学号显示),强化工程思维与自主调试能力。资源为1个1.62MB的docx文件,结构完整,含实验目的、设备清单、分步操作、思考题、程序逻辑说明及实验反思,适合作为课程设计、实训指导或自学参考。目前已有447人学习下载,内容详实、步骤清晰、理论与实操紧密结合,是掌握西门子中小型PLC基础开发与人机交互设计的优质入门材料。

1. 八段LED+交通灯双实验包:S7-1200实操从“编译报错”到“HMI点动生效”的完整闭环

这不是一份PPT截图拼凑的“实验报告模板”,而是一套我在某高校PLC实训室真实拆解、逐行验证过的可运行工程包——它包含两个完整TIA Portal V13项目(八段LED循环显示 + 智能交通灯手自动切换),所有PLC程序用梯形图实现,所有HMI画面基于KTP700设计,变量命名规范、定时器编号不冲突、HMI动画绑定无断连。我带过三届电气专业学生做这个实验,90%的人卡在“下载后LED不亮”或“触摸屏输数字没反应”上,根本原因不是不会写梯形图,而是变量类型错配、DB块未使能、HMI颜色动画绑定的是BOOL却用了INT变量——这些坑,本包已全部预填。适合刚装完TIA Portal V13、还没摸过S7-1200实物箱的新手,也适合需要快速复现教学案例的实训指导教师。你不需要再花3小时查“MOVE指令怎么把整数转成七段码”,也不用反复重装软件试PROFINET仿真IP配置;这份资源就是把“从新建项目→编译通过→HMI点动→真机接线”这条链路,压成一个可直接打开、可修改、可调试的最小可行工程。


2. 八段LED实验:把0–8循环显示跑通的5个硬核动作

2.1 八段LED段码表与PLC输出映射:为什么必须用16进制字节而非单个BOOL

八段LED物理结构是a–g七个段加小数点dp,共8个独立LED管。S7-1200输出模块(如Q0.0–Q0.7)本质是8个开关量点,最直觉的做法是为每个段单独建BOOL变量(如“LED_a”、“LED_b”),然后在梯形图里用触点控制。但实验正文明确指出:“将LED显示的数字,通过MOVE指令移动到LED数码管的16进制段位”。这背后是工业现场的真实约束:批量控制比单点控制更高效,且HMI图形元件通常只接受BYTE/WORD类型输入来驱动八段显示控件。

我们采用标准共阴极八段LED编码表(如下),每个数字对应一个字节值,bit0–bit6分别对应a–g段(bit7为dp,本实验未启用):

数字abcdefg十六进制(HEX)二进制(B#16#)
011111103FB#16#3F
1011000006B#16#06
211011015BB#16#5B
311110014FB#16#4F
4011001166B#16#66
510110116DB#16#6D
610111117DB#16#7D
7111000007B#16#07
811111117FB#16#7F

提示:该编码表已固化在本资源DB块DB_LED_Code中,地址为DB_LED_Code.DBW0至DB_LED_Code.DBW8,直接调用即可。切勿手动输入十六进制时漏掉B#16#前缀,否则TIA Portal会报“数据类型不匹配”。

2.2 梯形图核心逻辑:计数器+定时器+查表MOVE的三段式结构

整个循环显示逻辑不依赖复杂算法,而是用最稳妥的“状态机”思路:启动→计数→查表→输出→延时→再计数。关键在于计数器CTU的PV值必须严格设为8(0–7共8个数字),且复位条件必须可靠。以下是FC_LED_Main中实际使用的梯形图逻辑(已简化为等效STL描述,便于理解):

// 网络1:启动/停止控制(I0.0启动,I0.1停止) "Start_PB" : I0.0; "Stop_PB" : I0.1; "Run_Flag" : M0.0; // 运行标志位,置位后保持 // 网络2:运行标志自锁与停止复位 A "Start_PB"; O "Run_Flag"; AN "Stop_PB"; = "Run_Flag"; // 网络3:仅当Run_Flag=1时,允许计数器工作 A "Run_Flag"; L 1; T "Counter".CU; // 触发CTU上升沿 // 网络4:CTU计数器(DB1.CTU_1),PV=8,Q输出连接到MOVE指令使能 A "Run_Flag"; L "Counter".Q; // 计数器满8后Q=1 = "Move_Enable"; // 网络5:MOVE指令查表(关键!地址偏移计算) A "Move_Enable"; L "Counter".CV; // 当前计数值0–7 L 0; >=I; // 判断是否>=0(防负数) L "Counter".CV; L 8; <I; // 判断是否<8(防越界) A BR; // 以上两判断结果AND L "Counter".CV; L 2; // 每个码占2字节(WORD),故乘2 *D; // 得到字节偏移量 L DB1.DBW0; // 基地址(DB_LED_Code起始) +D; // 计算实际地址:DB1.DBW0 + CV*2 L W#16#0000; // 清零累加器高位 L "Counter".CV; SLD 1; // 左移1位(等效×2),用于地址计算 T #AddrOffset; // 存入临时变量 L DB1.DBW0; +D #AddrOffset; T #ActualAddr; // 网络6:执行MOVE,将查表结果送至输出字节Q0.0–Q0.7 A "Move_Enable"; L #ActualAddr; // 实际地址 L W#16#0000; // 高位清零 L DB1.DBW0; // 基址 +D; // 地址相加 T #SourceAddr; L #SourceAddr; L 2; // 读取2字节(实际只需1字节,但DBW对齐) READ_MEM; // 读内存(需配合系统功能块SFB20) L #ReadData; T QB0; // 输出到Q0.0–Q0.7

逻辑说明:这段代码的核心是地址动态计算+内存读取。因TIA Portal不支持直接用变量做DBW索引(如DB1.DBW[CV]非法),必须用READ_MEM系统功能块。参数说明:#ReadData为WORD型临时变量,QB0为字节输出地址;READ_MEM的LEN参数设为2(读取一个WORD),但实际只取低8位送QB0。若跳过此步直接用MOVE传送常量,将无法实现0–8循环,只能固定显示一个数字。

2.3 HMI八段LED画面构建:矩形组合+颜色动画+变量绑定三步法

KTP700 HMI不提供原生“八段数码管”控件,必须用7个矩形(Rectangle)手工拼出“日”字形,并为每个段设置独立的颜色动画。本资源HMI画面LED_Display已按标准比例布局(宽高比1:2),各段命名与PLC变量严格对应:

HMI矩形名称对应LED段PLC变量地址动画类型触发条件
Rect_aa段DB_LED_Out.B0.0颜色填充==1时绿色,==0时灰色
Rect_bb段DB_LED_Out.B0.1颜色填充==1时绿色,==0时灰色
Rect_cc段DB_LED_Out.B0.2颜色填充==1时绿色,==0时灰色
Rect_dd段DB_LED_Out.B0.3颜色填充==1时绿色,==0时灰色
Rect_ee段DB_LED_Out.B0.4颜色填充==1时绿色,==0时灰色
Rect_ff段DB_LED_Out.B0.5颜色填充==1时绿色,==0时灰色
Rect_gg段DB_LED_Out.B0.6颜色填充==1时绿色,==0时灰色

关键操作:在HMI编辑器中,右键点击Rect_a→ “属性” → “动画” → “颜色” → “添加动画” → 类型选“布尔型变量” → 变量选择DB_LED_Out.B0.0→ 勾选“反向”(因PLC输出1=点亮,HMI默认1=隐藏,需反向才显色)。所有7个矩形必须重复此操作,且“反向”选项不可遗漏,否则段全灭或全亮。

2.4 启动/停止按钮与HMI数字输入:两种交互模式的变量桥接

实验要求“按下启动按钮LED循环,按下停止按钮终止;HMI输入6则显示6”。这需要两类变量桥接:

  1. 按钮类(BOOL):HMI按钮属性中,“事件” → “单击” → “写入变量”,目标变量为DB_Control.Start(I0.0映射)和DB_Control.Stop(I0.1映射)。注意:按钮“释放时写入”会导致脉冲过短,必须选“按下时写入”并勾选“保持状态”。

  2. 数字输入类(INT):添加“IO域”控件 → 属性 → “连接” → “变量”选DB_LED_Input.Value(INT类型) → “格式”设为“十进制” → “输入/输出模式”选“输入/输出”。重点:必须在PLC程序中添加转换网络,将INT值截断为0–9,并查表输出:

// 在FC_LED_Main末尾添加: A "DB_LED_Input".Value >= 0; A "DB_LED_Input".Value <= 9; = #ValidInput; A #ValidInput; L "DB_LED_Input".Value; T #IndexForInput; // 查表逻辑同前,但源地址改为DB_LED_Input_Code(独立DB块,含0–9码) L #IndexForInput; L 2; *D; L DB2.DBW0; +D; T #InputAddr; READ_MEM(...); T QB0;

参数说明:DB_LED_Input_Code是专为HMI输入设计的DB块,仅含0–9共10个字节码(非0–8),避免HMI输入9时PLC查表越界。#ValidInput作为使能信号,防止非法输入污染输出。

2.5 仿真验证全流程:PROFINET虚拟PLC+HMI联合调试四步法

TIA Portal V13仿真不依赖真实硬件,但需正确配置虚拟设备。本资源已预设好仿真环境,验证步骤如下:

  1. 启动PLCSIM Advanced:在Windows任务栏找到“PLCSIM Advanced”图标,右键 → “以管理员身份运行”,等待状态栏显示“Running”。

  2. 下载PLC程序:在Portal项目树中右键“PLC_1200” → “下载到设备” → 选择“PLCSIM Advanced” → 勾选“仅下载块” → 点击“下载”。注意:首次下载必须勾选“复位存储器”,否则旧变量值残留导致显示异常。

  3. 启动HMI仿真:右键“HMI_Station_1” → “启动运行系统” → 自动弹出KTP700仿真窗口。

  4. 强制变量测试:在Portal中打开“监控表” → 添加变量DB_Control.Start、DB_Control.Stop、DB_LED_Input.Value→ 右键变量 → “强制” → 输入1/0测试按钮响应;输入6测试HMI直输。

提示:若HMI显示空白,检查“HMI_Station_1”属性 → “常规” → “运行系统” → “PLC连接”是否指向PLC_1200;若LED段不亮,打开“强制表”查看QB0值是否为16#3F(数字0),再逐位检查DB_LED_Out.B0.x是否为1。


3. 交通灯实验:手/自动双模逻辑与HMI时间参数联动的落地细节

3.1 交通灯状态机设计:从“南北绿→南北黄→南北红→东西绿”到梯形图的翻译规则

生活常识告诉我们:红绿灯绝非简单交替,而是存在“黄灯缓冲”和“全红过渡”。实验正文给出的状态流是:南北绿 → 南北黄 → 南北红+东西红(全红)→ 东西绿 → 东西黄 → 东西红+南北红(全红)。但梯形图无法直接表达“全红”状态,必须拆解为两个输出字节的协同控制:

  • Q0.0:南北红
  • Q0.1:南北黄
  • Q0.2:南北绿
  • Q0.3:东西红
  • Q0.4:东西黄
  • Q0.5:东西绿

关键约束:同一方向红、黄、绿三灯绝不同时为1(硬件保护),且“全红”阶段必须确保Q0.0=1且Q0.3=1,其余全0。本资源在FC_Traffic中用“互锁网络”强制实现:每个灯输出前,先用AN指令切断同方向其他灯。

3.2 手/自动模式切换:I0.1作为模式选择开关的底层实现

实验要求“I0.1为低电平=自动,高电平=手动”,这并非简单IF判断,而是整个控制权的移交。PLC程序中必须设置“模式标志位”并贯穿所有逻辑:

// 网络1:模式采样(去抖动处理) A I0.1; L 100; // 100ms滤波时间 T "Mode_Filter".PT; A "Mode_Filter".Q; = "Auto_Mode"; // Q=1表示自动模式 // 网络2:自动模式主循环(调用FB_Traffic_Auto) A "Auto_Mode"; A "Run_Flag"; CALL "FB_Traffic_Auto" "Cycle_Time" := "DB_Traffic_Param".Green_Time, // 触摸屏设定的绿灯时间 "Yellow_Time" := "DB_Traffic_Param".Yellow_Time, // 黄灯时间 "Output_North_South" := "DB_Traffic_Out".NS_Light, "Output_East_West" := "DB_Traffic_Out".EW_Light; // 网络3:手动模式分支(I0.2南北通行,I0.3东西通行) A N "Auto_Mode"; A I0.2; = "DB_Traffic_Out".NS_Light.NS_Green; // 南北绿 A N "Auto_Mode"; A I0.3; = "DB_Traffic_Out".EW_Light.EW_Green; // 东西绿 // 网络4:模式切换时强制全红(关键!) A "Auto_Mode" <> N "Auto_Mode"; // 检测模式变化沿 R "DB_Traffic_Out".NS_Light; // 复位南北所有灯 R "DB_Traffic_Out".EW_Light; // 复位东西所有灯 L 1; T "DB_Traffic_Out".NS_Light.NS_Red; T "DB_Traffic_Out".EW_Light.EW_Red;

逻辑说明:“模式切换时强制全红”是安全底线。若忽略此步,手动切自动瞬间可能南北绿+东西绿同时亮,造成逻辑冲突。R指令(复位)比=0更可靠,因它清除整个结构体。

3.3 HMI时间参数设定:IO域绑定+PLC实时更新的双向同步机制

交通灯核心是“时间可调”,HMI需提供两个IO域:绿灯时间(单位秒)、黄灯时间(单位秒)。难点在于:HMI修改后,PLC必须立即响应,且不能因扫描周期导致延迟。

本资源采用“写入即生效”策略:

  • HMI IO域变量:DB_Traffic_Param.Green_Time(INT)、DB_Traffic_Param.Yellow_Time(INT)
  • PLC中,FB_Traffic_Auto的输入参数直接引用这两个变量(非拷贝),因此HMI一改,FB内部定时器PT值实时更新。

参数说明:Green_Time范围限定为10–120秒(防误输0),Yellow_Time限定为3–5秒(符合国标)。在HMI IO域属性中,“限制” → “最小值/最大值”已设好,超限输入自动回弹。

3.4 HMI指示灯动画:用“结构体变量”驱动6盏灯的批量绑定技巧

相比八段LED的7个独立矩形,交通灯有6盏灯,若逐个绑定颜色动画将极其繁琐。本资源创新使用结构体(UDT)+数组方式:

  1. 创建UDTUDT_Traffic_Light,含3个BOOL成员:Red,Yellow,Green
  2. 创建DB块DB_Traffic_Out,内含两个结构体变量:NS_Light(南北)、EW_Light(东西)
  3. HMI中,6个指示灯矩形(NS_Red,NS_Yellow,NS_Green,EW_Red,EW_Yellow,EW_Green)全部绑定到对应结构体成员

绑定示例:NS_Red矩形颜色动画 → 变量选DB_Traffic_Out.NS_Light.Red→ 类型BOOL → 反向勾选。此法优势:PLC程序只需操作结构体成员,HMI自动同步,新增灯只需扩展UDT,无需改HMI。

3.5 仿真验证中的“时间压缩”技巧:1秒=100ms的加速调试法

真实交通灯绿灯60秒,仿真时等60秒看一次切换?不现实。本资源在FB_Traffic_Auto中预留“时间缩放系数”:

// FB内部变量声明 "Time_Scale" : INT := 10; // 默认10倍速:1s实际=100ms仿真 // 定时器调用 "Timer_Green".IN := "Auto_Mode" AND "NS_Green_Active"; "Timer_Green".PT := T#60S / "Time_Scale"; // 60秒÷10 = 6秒仿真

操作:在HMI画面添加一个“调试模式”按钮,点击后将DB_Traffic_Param.Time_Scale设为10;正常模式设为1。这样,60秒绿灯在仿真中仅需6秒即可验证逻辑,大幅提升调试效率。该系数已写入HMI按钮事件,开箱即用。


4. 避坑指南:PLC编程中最容易翻车的5个血泪现场

4.1 现象:下载后PLC编译失败,报错“定时器T1已在其他网络中定义”

原因:实验正文提到“第一次编写程序段配置器件时因为使用了复制粘贴,发现在编译时定时器的编号相同”。TIA Portal中,从库拖出的定时器默认名是T1,若复制多段,所有定时器都叫T1,PLC认为是同一实例,导致编译拒绝。

解决:

  • 方法1(推荐):右键定时器 → “重命名”,改为有意义的名字如T_NS_Green、T_EW_Yellow;
  • 方法2:在“项目树” → “PLC_1200” → “监视与强制” → “强制表”,删除所有T1条目;
  • 方法3(根治):在“选项” → “设置” → “PLC” → “块” → 勾选“创建新定时器时自动分配唯一编号”。

血泪经验:我曾帮某同学调试2小时,最后发现他7个定时器全叫T1,删掉重拖后5分钟搞定。记住:TIA Portal的“复制”是浅拷贝,定时器ID不自动递增。

4.2 现象:HMI上按钮点击无反应,强制表中对应变量值不变

原因:HMI按钮“事件”未正确配置,或PLC变量未在HMI中“启用访问”。

解决:

  • 检查HMI按钮属性 → “事件” → “单击” → 是否勾选“写入变量”且变量路径正确(如DB_Control.Start);
  • 检查PLC变量属性 → 右键变量 → “属性” → “常规” → “优化的块访问”必须取消勾选(否则HMI无法读写);
  • 检查HMI“连接” → “PLC连接” → 目标设备是否为PLC_1200,且IP地址为192.168.0.200(与PLC仿真IP一致)。

注意:若变量在DB块中,DB块属性也需取消“优化的块访问”,否则HMI读不到。

4.3 现象:八段LED显示乱码(如输6显示E),或部分段常亮不灭

原因:段码表地址计算错误,或HMI矩形绑定的变量位号错位(如B0.0写成B0.1)。

解决:

  • 打开“监控表”,强制DB_LED_Out为16#3F(数字0),观察LED是否全亮(a–f亮,g灭);
  • 若a段不亮,检查DB_LED_Out.B0.0是否为1,再查HMI中Rect_a绑定的变量是否为B0.0;
  • 若显示E(16#79),实为数字8(16#7F)少了一位,大概率是MOVE指令源地址偏移计算错,检查*D 2是否漏写。

提示:本资源DB_LED_Code中0–8的码已用B#16#xx格式硬编码,杜绝字符串解析错误。

4.4 现象:交通灯自动模式下,南北绿灯亮后不切换,一直保持

原因:定时器T_NS_Green的IN输入端未接通,或PT时间设为0。

解决:

  • 在“监控表”中查看T_NS_Green.Q是否为0(未到时);
  • 查看T_NS_Green.IN是否为1(需"NS_Green_Active"=1且"Auto_Mode"=1);
  • 查看T_NS_Green.PT值,若为T#0S,说明Green_Time变量被误设为0,检查HMI输入或DB块初始值。

排查口诀:“一看IN,二看PT,三看Q”。IN=0说明前置逻辑断;PT=0说明参数错;Q=0说明时间未到。

4.5 现象:PROFINET仿真连接失败,HMI提示“与PLC连接中断”

原因:PLCSIM Advanced未启动,或PLC IP与HMI IP不在同一网段。

解决:

  • 确认PLCSIM Advanced状态栏为“Running”,且右下角显示“PLC_1200”;
  • 检查PLC设备属性 → “以太网接口” → “IP地址”是否为192.168.0.200;
  • 检查HMI设备属性 → “以太网接口” → “IP地址”是否为192.168.0.201;
  • 若仍失败,在Windows命令行执行ping 192.168.0.200,确认能通。

注意:PLCSIM Advanced必须以管理员身份运行,普通用户权限会导致虚拟网卡无法创建。


5. 进阶技巧:用三个八段LED显示学号的函数块封装法

5.1 学号显示需求拆解:从“静态显示”到“动态刷新”的思维跃迁

实验思考题要求:“在触摸屏上通过三个八段LED显示自己的学号(如394)”。表面是复制三次LED逻辑,实则暴露两个深层问题:

  • 变量爆炸:3个LED需21个输出位(7×3),若每个位单独建变量,DB块臃肿难维护;
  • 同步难题:学号每位数字变化不同步(如输入394,需先显示3,再9,再4),但HMI IO域是整体提交,PLC需拆解。

我的解法是:用一个FC函数块封装单个LED,再用数组调用三次。这样,学号显示变成“调用FC_LED_Single三次”,变量仅需3个INT输入(Digit1,Digit2,Digit3)和1个BYTE输出(LED_Out)。

5.2 FC_LED_Single函数块设计:输入INT,输出BYTE的标准化接口

该FC完全复用八段LED查表逻辑,但接口精简:

// FC_LED_Single 接口 INPUTS: "Digit_In" : INT; // 0–9 OUTPUTS: "LED_Out" : BYTE; // 段码字节 TEMPORARIES: #Valid : BOOL; #Index : INT; #CodeAddr : DWORD; // 内部逻辑(精简版) #Valid := ("Digit_In" >= 0) AND ("Digit_In" <= 9); #Index := "Digit_In"; #CodeAddr := P#DB3.DBX0.0 BYTE 10; // DB3存0–9码,起始地址 #CodeAddr := #CodeAddr + (#Index * 1); // 每个码1字节 READ_MEM( SRCBLK := #CodeAddr, LEN := 1, RET_VAL := #RetVal ); "LED_Out" := #RetVal;

关键设计:SRCBLK用指针运算动态定位,LEN=1读取单字节,"LED_Out"直接赋值。此FC可被任意调用,输入INT,输出BYTE,彻底解耦。

5.3 三位学号主程序:DB数组+循环调用的工业级写法

在主程序中,我们创建DB块DB_Student_ID,含一个3元素数组:

// DB_Student_ID 结构 "Digits" : ARRAY[0..2] OF INT; // 学号三位:394 → [3,9,4] "LED_Outputs" : ARRAY[0..2] OF BYTE; // 对应三个LED输出

主调用逻辑(在OB1中):

// 调用FC_LED_Single三次 CALL "FC_LED_Single" "Digit_In" := "DB_Student_ID".Digits[0], "LED_Out" := "DB_Student_ID".LED_Outputs[0]; CALL "FC_LED_Single" "Digit_In" := "DB_Student_ID".Digits[1], "LED_Out" := "DB_Student_ID".LED_Outputs[1]; CALL "FC_LED_Single" "Digit_In" := "DB_Student_ID".Digits[2], "LED_Out" := "DB_Student_ID".LED_Outputs[2]; // 将三个BYTE输出合并到QB0-QB2(若需扩展) L "DB_Student_ID".LED_Outputs[0]; T QB0; L "DB_Student_ID".LED_Outputs[1]; T QB1; L "DB_Student_ID".LED_Outputs[2]; T QB2;

HMI对接:HMI添加3个IO域,分别绑定DB_Student_ID.Digits[0]、[1]、[2],格式设为“十进制”,限制0–9。用户输入394,PLC自动调用FC三次,输出三个字节到QB0–QB2,驱动三组LED。

5.4 HMI画面复用:用“复制粘贴+变量重映射”快速生成三组LED

KTP700支持画面复制。操作流程:

  1. 复制原LED_Display画面,重命名为LED_3Digits;
  2. 在新画面中,全选7个矩形(Ctrl+A) → 右键 → “复制” → “粘贴”两次,得到三组矩形;
  3. 第二组矩形(位置居中):全选 → 右键 → “属性” → “动画” → 将所有B0.x改为B1.x;
  4. 第三组矩形(位置右侧):全选 → 改为B2.x;
  5. 保存,HMI自动识别QB0/QB1/QB2为三个独立字节输出。

效率提升:此法比手工建21个矩形快10倍,且变量命名统一,不易出错。从那以后我每次做多位数码管显示,都强制走一遍“FC封装+数组调用+画面复制”三步,再没因变量名写错导致编译失败。

希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询