恭喜,你发布的帖子
发布于 2017-01-17 10:51:53
5楼
关于这个问题,我自己的一点理解;
结合RENHQ前辈的指点,目前认为有两种可能:
如前辈所说,for循环不执行完,不会进行下一个周期,所以Cur_DT_Byte.rand在这个循环里面会一直是个常数,导致出现这种结果。这样我把读系统时间READ_CLK放到循环里面便每次循环都会读取。即高亮部分1.
我认为读系统时间READ_CLK然后IF判断Cur_DT_Byte.rand和for循环类似fork,两个独立的线程运行(就算for循环不执行完,也会去READ_CLK),之所以会全0全1,是因为for循环速度远大于if里Cur_DT_Byte.rand变化的速度。为了增加for循环时间,因此在循环里再加一个for循环。即高亮部分2.
下面我将采用控制变量的方法,查看由于是哪种原因,下面是程序
FOR bitNo:=1 TO 700 BY 1 //M0.0-M80.7(多取了一些)
DO
temp:=READ_CLK(CDT := CurDateTime// OUT: DATE_AND_TIME
); // 读取系统时间
i:=bitNo DIV 8; //M区的字节号
j:=bitNo MOD 8; //M区的位号
IF Cur_DT_Byte.rand >15000 THEN //判断其是否大于0对b赋值,这里原来是判断0,但小于0的比例有点小,就改为了15000
b:=false;
ELSE
b:=true;
END_IF;
M[i,j]:=b; //对M区赋值
FOR k:=0 TO 2000 BY 1 DO
k:=k+1; // VOID
END_FOR;
END_FOR;
一共四种情况,首先去掉高亮部分2(for循环),分别把READ_CLK读系统时间放到bitNo这个循环外面和里面,会有两种情况
2.没有延时,READ_CLK在里面
加上延时(高亮部分2),又有两种情况
3.有延时,READ_CLK在外面
4.有延时,READ_CLK在里面
综上,我认为第2种更合理一些,最起码for循环就算不执行完也会去执行下一个周期执行READ_CLK,否则的话,情况3应该是全0全1.
最后,总结一下这个算法并不好,更确切的说并不能实现随机功能。比如我判断Cur_DT_Byte.rand >15000,在bitNO=50的时候Cur_DT_Byte.rand为20000;在bitNo=150的时候Cur_DT_Byte.rand为30000
这样导致bitNo=50-150的时候b全部都为false。因此会造成大片连续的0,1。如果大幅增加bitNo循环时间
又会影响程序运行效率,甚至引发看门狗报警。
我想还有一种方法可以运用复杂一点的运算去判断Cur_DT_Byte.rand ,比如判断奇偶(实际是不行的,因为Cur_DT_Byte.rand最后4个字节是星期,所以在一周内都是奇数或偶数,这里只是举个例子),可以使其更分散些,但我没有再试。
如果有不合理的地方,还望各位包涵,并指正,万分感谢。
请填写推广理由:
分享
只看
楼主