c#定时器顺序控制写法

csharp 复制代码
using System;
using System.Windows.Forms;

namespace c_顺序控制demo
{
    public partial class Form1 : Form
    {
        // =================================================================
        // 核心变量定义:模拟 PLC 内部寄存器
        // =================================================================

        // 定义流程状态枚举,增强可读性(等同于 PLC 的步进状态)
        private enum Step
        {
            Idle = 0,
            StartInfeed = 10,  // 进料步
            Processing = 20,   // 加工步
            Outfeed = 30,      // 出料步
            Complete = 40      // 周期完成
        }

        private Step _currentStep = Step.Idle; // 当前运行步
        private bool _isPaused = false;        // 暂停标志位 (类似中间继电器)
        private int _processCounter = 0;       // 模拟计时器累积值

        public Form1()
        {
            InitializeComponent();
            InitializeCustomSettings();
        }

        private void InitializeCustomSettings()
        {
            // 初始化定时器:模拟 PLC 扫描周期 100ms
            processTimer.Interval = 100;
            processTimer.Enabled = false;

            // 绑定定时器事件(如果在设计器里绑过了,这里可以删掉)
            processTimer.Tick += ProcessTimer_Tick;

            lblStatus.Text = "系统就绪,请点击启动";
        }

        // =================================================================
        // 主扫描逻辑:相当于 PLC 的主程序循环
        // =================================================================
        private void ProcessTimer_Tick(object sender, EventArgs e)
        {
            // 顶尖架构首要规则:优先判断"允许运行"条件
            if (_isPaused) return;

            // 使用 Case 语句实现严格的步进控制
            switch (_currentStep)
            {
                case Step.Idle:
                    UpdateStatus("停止中");
                    break;

                case Step.StartInfeed:
                    UpdateStatus("步骤 10: 正在进料...");
                    if (WaitCycles(20)) // 模拟等待 2 秒 (20 * 100ms)
                    {
                        _currentStep = Step.Processing;
                    }
                    break;

                case Step.Processing:
                    UpdateStatus("步骤 20: 核心加工中...");
                    if (WaitCycles(30)) // 模拟等待 3 秒
                    {
                        _currentStep = Step.Outfeed;
                    }
                    break;

                case Step.Outfeed:
                    UpdateStatus("步骤 30: 正在出料...");
                    if (WaitCycles(15)) // 模拟等待 1.5 秒
                    {
                        _currentStep = Step.Complete;
                    }
                    break;

                case Step.Complete:
                    UpdateStatus("步骤 40: 单次循环完成,准备重启");
                    _currentStep = Step.StartInfeed; // 自动跳转回第一步,实现不停循环
                    break;

                default:
                    _currentStep = Step.Idle;
                    break;
            }
        }

        // =================================================================
        // 功能块封装:模拟 PLC 中的 TON 计时器
        // =================================================================
        private bool WaitCycles(int target)
        {
            _processCounter++;
            if (_processCounter >= target)
            {
                _processCounter = 0; // 计数器清零,准备下一步
                return true;
            }
            return false;
        }

        // =================================================================
        // UI 事件处理:按钮控制
        // =================================================================

        private void btnStart_Click(object sender, EventArgs e)
        {
            _currentStep = Step.StartInfeed;
            _processCounter = 0;
            _isPaused = false;
            processTimer.Start();
            UpdateStatus("流程启动");
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            // 仅置位暂停标志,不停止 Timer,模拟控制系统的"暂停/挂起"
            _isPaused = true;
            UpdateStatus($"已暂停在: {_currentStep}");
        }

        private void btnResume_Click(object sender, EventArgs e)
        {
            // 复位暂停标志,逻辑从断点自动继续
            _isPaused = false;
            UpdateStatus("恢复运行...");
        }

        private void UpdateStatus(string msg)
        {
            // 实时反馈到界面
            lblStatus.Text = $"状态: {msg} | 计数: {_processCounter}";
        }

       
    }
}

//------------------总结如下-------------------------

为什么说这是"顶尖"的写法?

  1. 业务逻辑与定时器控制分离

    很多初学者会在暂停时调用 Timer.Stop()。高手不这么做。 在工业控制思维中,主 CPU(定时器)应该一直运行,通过一个"允许位"(如 _isPaused)来控制业务逻辑是否执行。这样可以方便地在暂停期间监控传感器状态或处理 UI 更新。

  2. 枚举(Enum)优于数字

    使用 Step.Processing 代替数字 20。当你的程序达到几千行时,你不需要去查文档才知道数字代表什么,代码本身就是文档。

  3. 模拟 PLC 计数器

    我写了一个 WaitCycles 方法。这模仿了 PLC 里的 TON(接通延时定时器)。在 switch 结构中,只有当计数达标时才切换状态,这保证了状态切换的严谨性,不会因为 UI 的卡顿导致逻辑跳步。

  4. 易于实现"断点续传"

    因为我们在暂停时没有重置 _currentStep 和 _processCounter,所以按下"继续"按钮时,程序会精准地从刚才那一秒、那个步骤继续往下跑,完美符合产线逻辑。

相关推荐
isyangli_blog12 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081112 小时前
FastAPI APIRouter
开发语言·python
Benszen12 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆12 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木12 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充13 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~13 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball61613 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
春生野草13 小时前
反射、Tomcat执行
java·开发语言
雪的季节14 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt