多核操作器是 IEC 61131-3 标准的延伸。
该运算符可用于实现原子计数器。如果一个整数变量是通过普通加法运算递增的,例如iTest := iTest + 1;
,那么这个运算就不是原子执行的。在读取和写入变量之间,可以对变量进行另一次访问。
如果计数器在多个任务中递增,则计数结果可能少于计数周期数。因此,如果两个任务同时执行上述代码,而变量之前的值是0
,那么变量之后的值就可以是1
。如果在多个任务中处理数组,并且在每个处理周期中都需要为数组建立唯一索引,那么问题就尤其严重。
当调用__XADD
操作符时,它会获取一个指向DINT
类型变量的指针作为第一个求和值,以及一个DINT
类型的值作为第二个求和值。__XADD
返回第一个求和值的旧值,并在同一步骤中将第二个求和值添加到第一个求和值中。
例如,函数调用可以如下所示: diOld := __XADD(ADR(diVar), deAdd);
示例
下面的示例展示了一种典型的用法。应从两个任务中填充一个数组。在此过程中,应使用数组中的所有位置,不得覆盖任何位置。
使用该函数,多个任务可以填充一个布尔数组。
FUNCTION WriteToNextArrayPosition : BOOL VAR_EXTERNAL g_diIndex : DINT; // Index and array are globally defined and used by multiple tasks g_boolArray : ARRAY [0..1000] OF BOOL; END_VAR VAR_INPUT bToWrite : BOOL; END_VAR VAR diIndex : DWORD; END_VAR diIndex := __XADD(ADR(g_diIndex), 1); // Returns a unique index WriteToNextArrayPosition := FALSE; IF (diIndex >= 0 AND diIndex <= 1000) THEN g_boolArray[diIndex] := bToWrite; //Writes to unique index WriteToNextArrayPosition := TRUE; // TRUE: Array was not full yet END_IF
另见