codesys读取csv文件
最近在项目遇到了需求:要求能够以可编辑文件的方式保存两百个运动和点位到位延迟时间,然后运动控制通过读取文件的方式将点位读出来。一个点位一个点位的执行,文件保存方式最好为Excel表格方式。查询了相关资料以后,发现Codesys是支持csv文件读写的,而恰好Excel也可以打开csv文件。于是,我开始了:本次测试环境基于3.5.12开发环境1、首先,你需要引入一些库,用于读写文件流
2、其次,你需要指定你要读到数据格式,例如我要读X,Y,Z1,Z2,Z3,U1,U2,WaitTime。一行需要有这些数据,每个数据用逗号隔开。同时在首位添加1位占位标志。用来区分数据的开头和结尾。示例:1,101,301,1,2,3,4,5,1001$R$N(这个就是你会读到的数据)
3、特别解释,$R$N是写进去时候的换行符。没有这个无法实现在Excel中的换行
4、读文件源码:
----------------------------变量声明区域------------------
FUNCTION ReadFileToBuffer : BOOL
VAR_INPUT
strIniPath :STRING;
pBuffer :POINTER TO ARRAY OF STRING;
END_VAR
VAR
hFile :DWORD;
dwFileSize :DINT;
strLine :STRING;
iLnCnt :INT:=1;
iFileLine :INT;
dwRead :DWORD;
STR :STRING;(*读到的字符串*)
iEndPos :INT;
dwFileCurPos :DINT;(*当前文件光标位置*)
END_VAR
----------------------------运行代码区域------------------
hFile :=SysFileOpen(FileName:=strIniPath,Mode:='r');
dwFileCurPos:=0;
IF (hFile =0) THEN
ReadFileToBuffer:=FALSE;
SysFileClose(hFile);
RETURN;
END_IFdwFileSize:=SysFileGetSize(FileName:=strIniPath);
IF (dwFileSize=0)THEN
ReadFileToBuffer:=FALSE;
SysFileClose(hFile);
RETURN;
END_IFWHILE(TRUE) DO
IF(*(NOT SysFileEOF(hFile)) OR*) dwFileCurPos<dwFileSize THEN
dwRead:=SysFileRead(File:=hFile,Buffer :=ADR(STR),60);
iEndPos:=FIND(STR1:=STR,STR2:='$N');
dwFileCurPos:=dwFileCurPos+iEndPos;
SysFileSetPos(hFile,dwFileCurPos);
pBuffer^:=LEFT(STR,iEndPos);
iLnCnt:=iLnCnt+1;
ELSE
SysFileClose(hFile);
EXIT;
END_IF
END_WHILE
ReadFileToBuffer:=TRUE;
此部分代码会执行一个过程,将按行数文件内容全部读取到一个指定到的字符串,每一行为一个字符串。
5、因此,我们还需要通过一个方法来分解字符串来取数据
----------------------------变量声明区域------------------
FUNCTION_BLOCK GetPointData
VAR_INPUT
BuffStr:STRING;
END_VAR
VAR_OUTPUT
OutDutData:DUT_XYZ_WaitTime;
END_VAR
VAR
str1:STRING :='1,101,301,1,2,3,4,5,1001$R$N'; ///测试数据
iStartPoint:INT;
iEndPoint:INT;
p,j:INT;
listPoint:ARRAY OF INT; //记录逗号位置
END_VAR
----------------------------运行代码区域------------------
iStartPoint:=FIND(BuffStr,'1');//获取起始位置
iEndPoint:=FIND(BuffStr,'$R');//获取数据结束位置
//从字符位置1开始循环到数据结束位置,通过MID方法获得每一个逗号位置,并记录到数组中。
j:=1;
FOR p:=1 TO iEndPoint DO
IF','=MID(BuffStr,1,p)THEN
listPoint:=p;
j:=j+1;
END_IF
IF j>8 THEN
EXIT;
END_IF
END_FOR
//按照逗号位置取当前逗号到上一个逗号之间的字符串,转换为长实数类型数据
OutDutData.X:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
OutDutData.Y:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
OutDutData.Z1:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
OutDutData.Z2:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
OutDutData.Z3:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
OutDutData.U1:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
OutDutData.U2:=STRING_TO_LREAL( MID(BuffStr,(listPoint-listPoint-1),listPoint+1));
//最后一个没有逗号,但是有换行标志,所以取换行标志到上一个逗号之前的数据,同理转化
OutDutData.WaitTime:=STRING_TO_INT( MID(BuffStr,(iEndPoint-listPoint-1),listPoint+1));
6、通过步骤5的方法。我们可以传一个字符串,从而得到一个我们协议好的数据集合
这样我们在主程序中,这样调用,即可得到想要的值了
Cnst_MaxFileLine :INT:=1000;(*文件的最大行数*)
IF ReadFileToBuffer(strFilePath,ADR(Buffer))THEN
FOR i:=1 TO GVL.Cnst_MaxFileLine DO
fb_GetData(BuffStr:=Buffer,OutDutData=>PointData);
END_FOR
iIndex:=1;
END_IF
对了,别忘了定义你的数据结构体:
TYPE DUT_XYZ_WaitTime :
STRUCT
X:LREAL;
Y:LREAL;
Z1:LREAL;
Z2:LREAL;
Z3:LREAL;
U1:LREAL;
U2:LREAL;
WaitTime:INT;
END_STRUCT
END_TYPE
好了。就是这样,程序中使用就调用OutDutData数组下的相应点位即可,给相应的XY运动点位赋值,即可达成想要的效果。
页:
[1]