AI小西
热门搜索
1847工业学习平台与计算机连接选型选型选型PLC编程

签到有奖

  • 移动端入口

  • 工业服务小程序
  • 支持中心移动端首页
  • AI小西-AI智能问答助手
  • SIEMENS工业找答案小程序
  • 工业培训与认证
  • 西门子工业1847俱乐部
  • SIEMENS工业技术支持与服务
@CurrentUser.EmailCount@

消息提醒

登录 | 注册
@CurrentUser.NickName@
1847会员:未开通
VIP等级 @CurrentUser.vipLevel@
西币
@CurrentUser.coin@
  • 我的支持中心
  • 我的1847会员
  • 我的技术论坛
  • 我的找答案
  • 我的下载中心
  • 我的售后服务
  • 我的培训认证
  • 我发的帖子
  • 我跟的帖子
  • 我的论坛设置
  • 论坛用户指南
  • 我的下载中心
  • 我的培训认证
  • 我的提问
  • 我的回答
  • 已经帮助了@CurrentUser.allAnswercount@人我要回答
  • 已连续活跃@CurrentUser.allLoginDayCount@天我要提问
  • 首次回答问题获得双倍西币积分
  • 个人设置
  • 退出
  • 首页
  • 技术支持
    • 技术支持
    • AI小西
    • 风驰卡
    • 产品入门
    • 在线产品选型
  • 售后服务
    • 售后登记和质保查询
    • 备件商城
    • ASP工程师验证
    • ASP公司证书验证
    • 售后服务常见问题
  • 下载中心
    • 首页
    • 售前文档(样本、宣传册等)
    • 售后文档(FAQ、手册等)
  • 工业学习平台
    • 首页
    • 了解会员权益
    • 立即开通1847会员
    • 标准机型应用中心
  • 培训认证
    • 首页
    • 教室培训课
    • 取证训练营
    • 在线自学课
    • 认证证书查询
    • 培训伙伴验证
  • 技术论坛
    • 首页
    • 最新发帖
    • 精华帖
    • 发新帖
  • 找答案
    • 首页
    • 已解决问题
    • 精华常见问题
    • 发布新问题

官方商城

  • 西门子中国
  • 技术支持与服务首页
    我的支持中心
    下载中心首页
    全球技术资源
    1847工业学习平台
    产品入门新手必读
    找答案
    技术论坛
    售后服务
    网络资源新手必读
    高级搜索
  • 技术论坛
    论坛公告
    论坛使用指南
    最新发帖
    精华帖
    分享帖
    高赞帖
    热门帖
    高端推荐帖
    最高收藏帖
  • 咱工程师的故事 / 网友专栏
  • 【大展身手】8工位抢答器的系列程序设计

技术论坛

 • 产品分类
自动化系统
  • SIMATIC S7-1500系列 
  • SIMATIC S7-1200系列 
  • SIMATIC S7-200
  • SIMATIC S7-200 SMART 
  • SIMATIC S7-300/400 
  • 通信与网络组件
  • Profinet技术开发专区
  • 工业边缘计算
  • SIMATIC WinCC / Panel 
  • SIMATIC WinCC OA (原PVSS)
  • DCS/SIMATIC PCS7
  • IPC/PG
  • LOGO!
  • 物联网(IOT)
  • 工业电源
驱动技术
  • SINAMICS 
  • SINAMICS S200 
  • 直流调速器
  • 电机
  • SIMOTION
  • MicroMaster
  • 驱动技术综合产品
  • MasterDrives 
  • DCMA 变频器健康管家 维护智库
数控系统
  • SINUMERIK 
  • SIMODRIVE
低压电气
  • 低压电气
  • 低压数字化
传感器与通讯
  • 过程仪表
  • 分析仪器
  • 工厂传感器
谈天说地
  • 谈天说地
 • 咱工程师的故事
咱工程师的故事
  • 网友专栏 
  • 工程师随笔
1847大咖专栏
  • 崔工谈博途与PLC
  • PROFINET工业通信详解
  • 冯工聊工业网络
  • 电磁兼容问题及处理
  • 大咖专栏合集
特别专题
  • 专家大讲堂课后探讨
  • 西门子工业1847俱乐部
  • 特别专题合集
 • 培训与认证答疑专区
培训与认证答疑专区
  • PLC编程精英训练营
  • MA 小型自动化系统
  • WinCC系统开发工程师精英训练营
  • V90精英训练营
  • WinCC精英训练营
  • S7-1200精英训练营
  • G120变频器精英训练营
  • S7-200SMART精英训练营
 • 服务合作伙伴专区
服务合作伙伴专区
  • FA合作伙伴共创社区
  • Networks and Communication
  • GMC蓝黄带考试-G120
  • GMC蓝黄带考试-V90
  • GMC 合作伙伴专区

故事作者:'Razor论坛推荐作者

最近创作

看看TA的故事

【大展身手】8工位抢答器的系列程序设计

'Razor

西门子1847工业学习平台

  • 帖子

    3477
  • 精华

    43
  • 被关注

    228

论坛等级:至圣

注册时间:2008-03-31

钻石 钻石 如何晋级?

【大展身手】8工位抢答器的系列程序设计

17

6

2026-03-20 19:13:41

由于经常在论坛混,近几天个人的收件箱收到了多条官方的邀请,本着却之不恭的初心,抽时间弄了一下,仓促之间做出的东西就比较潦草了。


至于其它硬件选型,I/O表,电气图纸,为节省篇幅,在此就省略不搞了,有关注需求的朋友可以参照其它朋友的帖子,大同小异,区别就是8工位抢答按钮的I区分配最好分配为一个完整连续的独立字节,如IB0此类操作,如此则可以方便仲裁检测,否则的话,还要使用中间层字节再做额外的位映射工作。


这里先说使用常规扫描编程实现抢答仲裁FB_ArbiterNew的方法,先上效果图,









从上面的几张图可以看出,当被检测的8位字节被赋予同一值时,图中为16#34,即2#0011 0100,也就是第2,4,5索引位同时出现上升沿变化时,连续三次检测,每次仲裁得到的首个上升沿工位ID都不一样,这也在一定程度上实现了“公平”的要求,没有出现连续三次都是同一工位被检测到首次触发上升沿的独占情况。


审题得知,如何实现最大程度上的公平,是本题的重心,仲裁FB的代码如下:

FUNCTION_BLOCK "FB_DetectFirstTrigger"




{ S7_Optimized_Access := 'TRUE' }

VERSION : 0.1

VAR_INPUT

  Reset : Bool;

  ArbiterType : Bool;//仲裁类型

  Interlock : Byte;//互锁

  LampsNoTrue : Byte;//对应状态指示灯无激活

  DetectedByte : Byte; // 当前待检测的HMI按钮字节值

  CfgByte : Byte;          // 使能位掩码(1表示该位参与检测)

END_VAR


VAR_OUTPUT


END_VAR


VAR_IN_OUT

  FirstTriggerID : USInt;         // 检测到的首个上升沿位索引(0~7),若无上升沿则返回255

  LastFirstTriggerID : USInt;    //上一次检测到的首个上升沿位索引

END_VAR


VAR

  LastByte : Byte;        // 上一周期的字节值,用于上升沿检测

  NextStart : USInt := 0;   // 下一次扫描的起始位索引(0~7),实现循环优先级

  LastCfg : Byte := 0;    // 上一次的使能掩码,用于检测配置变化并复位起始位

  TempRisingRaw : Byte;       // 原始上升沿掩码(所有由0变1的位)

  TempRising : Byte;          // 经过使能掩码过滤后的有效上升沿掩码

  TempLoopIndex : USInt;        // 循环扫描时的索引变量

  TempFound : Bool;           // 是否找到首个上升沿的标志

  TempNextIndex : USInt;        // 寻找下一次起始位时的循环索引

  TempNextFound : Bool;       // 是否找到下一个使能位的标志

 

END_VAR


VAR_TEMP

 

END_VAR


VAR CONSTANT

 

END_VAR



BEGIN

    // FUNCTION_BLOCK FB_FirstRisingEdgeMasked

    // TITLE = '公平检测字节中使能位的首个上升沿(支持配置变化复位)'

    // VERSION : '1.0'

    // AUTHOR : '...'

   

   

   

    IF #Reset THEN

        #LastFirstTriggerID := 0;

    END_IF;

   

    IF #ArbiterType AND #Interlock = 0 AND #LampsNoTrue = 0 THEN //满足仲裁条件,3个允许灯全亮

        // 检测配置是否变化,若变化则重置起始位为0,以保证新配置下的公平起始点

        IF #CfgByte <> #LastCfg THEN

            #NextStart := 0;

            #LastCfg := #CfgByte;

        END_IF;

       

        // 1. 计算原始上升沿(当前为1且上一次为0的位)

        #TempRisingRaw := #DetectedByte AND (NOT #LastByte);

        #LastByte := #DetectedByte;     // 更新历史值

       

        // 2. 仅保留使能位

        #TempRising := #TempRisingRaw AND #CfgByte;

       

        // 3. 若无上升沿,直接返回255

        IF #TempRising = 0 THEN

            #FirstTriggerID := 255;

            // NextStart 保持不变

            RETURN;

        END_IF;

       

        // 4. 从 NextStart 开始循环扫描,找到第一个上升沿的使能位

        #TempFound := FALSE;

       

        // 先扫描高位部分(NextStart 到 7)

        FOR #TempLoopIndex := #NextStart TO 7 DO

            IF (#TempRising AND SHL(IN := BYTE#16#01, N := #TempLoopIndex)) <> 0 THEN

                #LastFirstTriggerID := #FirstTriggerID := #TempLoopIndex + 1;

                #TempFound := TRUE;

                EXIT;

            END_IF;

        END_FOR;

       

        // 若未找到,再扫描低位部分(0 到 NextStart-1)

        IF NOT #TempFound THEN

            FOR #TempLoopIndex := 0 TO #NextStart - 1 DO

                IF (#TempRising AND SHL(IN := BYTE#16#01, N := #TempLoopIndex)) <> 0 THEN

                    #LastFirstTriggerID := #FirstTriggerID := #TempLoopIndex + 1;

                    #TempFound := TRUE;

                    EXIT;

                END_IF;

            END_FOR;

        END_IF;

       

        // 理论上Found必为TRUE,因为Rising非0

        IF #TempFound THEN

            // 5. 计算下一次起始位:当前选中位之后的下一个使能位(基于Cfg,循环)

            #TempNextFound := FALSE;

           

            // 先找更高位

            FOR #TempNextIndex := (#FirstTriggerID ) TO 7 DO

                IF (#CfgByte AND SHL(IN := BYTE#16#01, N := #TempNextIndex)) <> 0 THEN

                    #NextStart := #TempNextIndex;

                    #TempNextFound := TRUE;

                    EXIT;

                END_IF;

            END_FOR;

           

            // 若未找到,再从0开始找比当前位低的使能位

            IF NOT #TempNextFound THEN

                FOR #TempNextIndex := 0 TO #FirstTriggerID - 1 DO

                    IF (#CfgByte AND SHL(IN := BYTE#16#01, N := #TempNextIndex)) <> 0 THEN

                        #NextStart := #TempNextIndex;

                        #TempNextFound := TRUE;

                        EXIT;

                    END_IF;

                END_FOR;

            END_IF;

           

            // 若仍未找到,说明只有当前位一个使能位,则下一次起始位仍为当前位

            IF NOT #TempNextFound THEN

                #NextStart := #FirstTriggerID;

            END_IF;

        ELSE

            // 异常情况,置255

            #FirstTriggerID := 255;

        END_IF;

    END_IF;

   

   

   

END_FUNCTION_BLOCK


FUNCTION "FC_TransferResult" : Void


 

  { S7_Optimized_Access := 'TRUE' }

VERSION : 0.1

VAR_INPUT

    TriggerID : Int;

    Reset : Bool;

  END_VAR

 

  VAR_OUTPUT

   

  END_VAR

 

  VAR_IN_OUT

    Statments : Array[1..8] OF Bool;

    LastTriggerID : Int;

  END_VAR

 

  VAR_TEMP

   

  END_VAR

 

  VAR CONSTANT

   

  END_VAR



BEGIN

    IF #Reset THEN

        #Statments[#LastTriggerID] := FALSE;

        #LastTriggerID := 0;

    ELSIF #TriggerID >= 1 AND #TriggerID <= 8 THEN

        #Statments[#TriggerID] := true;

        #LastTriggerID := #TriggerID;

    END_IF;

   

   

END_FUNCTION


FUNCTION_BLOCK "FB_ArbiterNew"


 

  { S7_Optimized_Access := 'TRUE' }

VERSION : 0.1

VAR_INPUT

    Mode : Int;    // 模式

    ResetBtn : Bool;    // 复位按钮

    ArbiterAllow : Bool;   // 抢答启动按钮

    QuizCmds : Byte;      // 8个工位抢答按钮

    EnableIDs : Byte;      // 启用抢答的工位

    InterlockNoSuccess : Byte;//无抢答成功

    InterlockNoFoul : Byte;//无抢答犯规

  END_VAR

 

  VAR_OUTPUT

   

  END_VAR

  VAR_IN_OUT

    Success : Array[1..8] OF Bool;  // 成功标志

    Fault : Array[1..8] OF Bool;  // 犯规标志

    Enable : Array[1..8] OF Bool;//抢答启用标志

  END_VAR

 

  VAR

    StatFirstSuccessID : USInt;

    StatLastFirstSuccessID : USInt;

    StatDoubleLastFirstSuccessID : Int;

    StatFirstFoulID : USInt;

    StatLastFirstFoulID : USInt;

    StatDoubleLastFirstFoulID : Int;

  FB_DetectFirstQuiz_Instance {S7_SETPOINT := 'True'} : "FB_DetectFirstTrigger";

  FB_DetectFirstFoul_Instance {S7_SETPOINT := 'True'} : "FB_DetectFirstTrigger";

  END_VAR

 

  VAR_TEMP

   

  END_VAR

 

  VAR CONSTANT

   

  END_VAR



BEGIN

    #FB_DetectFirstQuiz_Instance(Reset:=#ResetBtn,

                                 ArbiterType:=#ArbiterAllow,

                                 Interlock:=#InterlockNoFoul,

                                 LampsNoTrue:=#InterlockNoSuccess,

                                 DetectedByte:=#QuizCmds,

                                 CfgByte:=#EnableIDs,

                                 FirstTriggerID:=#StatFirstSuccessID,

                                 LastFirstTriggerID:=#StatLastFirstSuccessID);

    "FC_TransferResult"(TriggerID:=#StatLastFirstSuccessID,

                        Reset:=#ResetBtn,

                        Statments:=#Success,

                        LastTriggerID:=#StatDoubleLastFirstSuccessID);

   

    #FB_DetectFirstFoul_Instance(Reset:=#ResetBtn,

                                 ArbiterType:=NOT #ArbiterAllow,

                                 Interlock:=#InterlockNoSuccess,

                                 LampsNoTrue:=#InterlockNoFoul,

                                 DetectedByte:=#QuizCmds,

                                 CfgByte:=#EnableIDs,

                                 FirstTriggerID:=#StatFirstFoulID,

                                 LastFirstTriggerID:=#StatLastFirstFoulID);

    "FC_TransferResult"(TriggerID:=#StatLastFirstFoulID,

                        Reset:=#ResetBtn,

                        Statments:=#Fault,

                        LastTriggerID:=#StatDoubleLastFirstFoulID);

   

END_FUNCTION_BLOCK



乍一看,上面的图挺唬人的,可是,抢答成功的检测还可以说得过去,只有一个抢答成功绿灯亮;可是,抢答犯规的红灯为什么也只有一个亮,如果是“法不责众”的想法作怪,那么执行起来就是谁先被检测到犯规扣谁的分,可是,同样是犯规,为什么只检测出来一个,不应该是都被检测出来吗?


国际田径大赛的规则,自2010年以来,就是“零抢跑”,“一枪就下”,谁抢跑就取消谁的比赛资格,不管你是第几个抢跑的,只管你做没做,而不管你是第几个做。

照此看,所有抢答犯规的人,都应该有被扣分的待遇。


所以,我的副标题是“系列程序设计”,也计划多盖几楼。

剩余80%未阅读, 请登录阅读

回帖加入探讨技术论坛守则

上传附件要求

1. 文件大小:上传文件的大小请限制在2M以内。

2. 文件格式:请不要上传.exe文件,系统支持的格式有:
.avi,.wmv,.mp3,.rar,.zip,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.wma,.asf,.txt,.7z

 
发分享帖
爱工控,乐分享,
分享您的经验与案例
发故事
发表您的精彩故事,
参与征文活动
技术探讨帖
阐述您的观点,
表达我的看法
西家杂谈
海侃天南地北,
闲聊工控世界
发求助帖
求道解惑,“刨根问底”
解决问题
发投票帖
邀投票,做调查,
网友帮您来作主
取消原因:
【大展身手】8工位抢答器的系列程序设计
编辑推荐: 关闭

请填写推广理由:

活动公告 查看全部公告>

2026论坛首届竞赛正式开启!发帖100%有奖,等你来!

1,862,739 条
海量精彩技术内容

100,000+ 网友与你交流

助你技有所长,论有所获

热门视频,猜你喜欢

本版热门话题

网友专栏

共有3405条技术帖

更多

评选标准

相关推荐

换一换

热门标签

换一换

相关帖子推荐

换一换
正在加载...
guzhang

恭喜,你发布的帖子

被评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

  • 分享

  • 只看
    楼主

top
X 图片

下载中心

  • 首页
  • 查找文档
  • 常见问题大全
  • 精选主题
  • 全球技术资源

  • 首页
  • 知识库
  • 订阅文档

1847工业学习平台

  • 首页
  • 了解会员权益
  • 立即开通1847会员
  • 课程中心
  • 学习路线
  • 初级工程师认证
  • 高级工程师认证

培训与认证

  • 首页
  • 教室培训课
  • 取证训练营
  • 在线自学课
  • 认证证书查询
  • 培训伙伴验证

技术论坛

  • 首页
  • 发帖
  • 最新发帖
  • 精华帖
  • 高赞贴
  • 当前热门帖
  • 高端推荐帖
  • 用户荣誉榜

找答案

  • 首页
  • 提问
  • 精华问答
  • 高赞问答
  • 新解决问题
  • 待解决问题
  • 总积分排行榜

售后服务

  • 我要报修
  • 服务进度查询
  • 质保及权益查询
  • 备件商城
  • ASP工程师验证
  • ASP公司证书验证
  • 支持中心网站重要声明

西门子中国   © 西门子(中国)有限公司 1996 – 2026   企业信息    隐私政策   使用条款   京ICP备06054295号   京公网安备 11010502040638号
 
支持中心新发布“关注”功能了!实时查看彼此动态,更方便地进行技术交流。
不管是“关注”与“被关注”,相信都是一个美好的开始!
还有多重奖励派送,快快行动起来吧!

20秒帮我们优化支持中心!

欢迎您访问支持中心!

丰富的视频,全方位的文档,大量的网友交流精华……

为了更好的完善这些内容,我们诚邀您在浏览结束后,花20秒左右的时间,完成一个用户在线调查!

感谢您的支持!

您收到0封站内信:
×
×
图片
立即
签到
已签到
已签到0天
累计可抽西币次数:0次抽奖机会
累计可抽惊喜实物奖次数:0次抽奖机会
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。