PLC可以是认为跑在while 死循环里的程序(Ob100除外),每一个OB块都是一个单独的线程。了解了这点,就可以更好的进行C# 上位机编程和 PLC的SCL(ST)编程。
在SCL中,如果If 语句的条件使用了长信号,If语句会反复执行,一些交换值,传递值,更新值的操作就无法完成,这时候If语句的条件必须要使用瞬态信号,If 的条件使用上升沿是一个好选择。
上升沿:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FPTest
{
public class R_TRIG
{
///
/// 这个属性存储上一次的bool状态,get;private set;这个写法相当于PLC的 Output接口
///
public bool Last { get; private set; }
///
/// 这个属性填被检测的bool量,set;相当于PLC的Input接口
///
public bool CLK
{
set
{
Q = value && !Last;//我们知道上升沿是从0变1的一瞬间,所以本次扫描为真上次为假时就产生了上升沿
Last = value;//每个扫描周期刷新参考位
}
}
///
/// 这个就是检测的状态,外部获取这个变量就知道上升沿有没有产生
/// 相当于PLC的 Output接口
public bool Q { get; private set; }
}
}
下降沿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FPTest
{
public class F_TRIG
{
public bool Last { get; private set; }
public bool CLK
{
set
{
Q = !value && Last;//1变0 上次为真本次为假
Last = value;
}
}
public bool Q { get; private set; }
}
}
主程序
namespace FPTest
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
rTrig = new R_TRIG();
fTrig = new F_TRIG();
this.label1.Text = a.ToString();
this.label2.Text = b.ToString();
}
private R_TRIG rTrig;
private F_TRIG fTrig;
private int a = 0;
private int b = 0;
CancellationTokenSource cts = new CancellationTokenSource();
private void btnUp_Click(object sender, EventArgs e)
{
Task.Run(async () =>
{
while (!cts.IsCancellationRequested)
{
await Task.Delay(200);
rTrig.CLK = true;
if (rTrig.Q)
{
a = b;
b = int.Parse(this.textBox1.Text.Trim()) ;
}
this.label1.Invoke(new Action(() => { this.label1.Text = a.ToString(); }));
this.label2.Invoke(new Action(() => { this.label2.Text = b.ToString(); }));
}
}, cts.Token);
}
private void NoRTrig_Click(object sender, EventArgs e)
{
Task.Run(async () =>
{
while (!cts.IsCancellationRequested)
{
await Task.Delay(200);
if (true)
{
a = b;
b = int.Parse(this.textBox1.Text.Trim());
}
this.label1.Invoke(new Action(() => { this.label1.Text = a.ToString(); }));
this.label2.Invoke(new Action(() => { this.label2.Text = b.ToString(); }));
}
}, cts.Token);
}
}
}
初始状态
使用上升沿,If中执行了一次
不使用上升沿,a,b无法传递值
bool q;
bool last;
bool trigIn;
bool trigQ;
trigQ = trigIn AND NOT last;
last = trigIn;