在使用TwinCAT3过程中,假如有些参数需要频繁的修改,或者是根据不同的制程要求设置不同的参数,这时候可以把这些参数放到一个CSV文件中,参数修改后,直接让TwinCAT plc重新读取参数就可以了,很方便。
FB_FileOpen, 用来打开CSV文件。
FB_FileGets, 用来取得CSV文件中的一整行数据。
FB_CSVMemBufferReader,更加数据分割符,把一整行数据解析成更小的数据单元。
FB_FileClose,用来关闭上文中打开的CSV文件。
文件存放路径:C:\Temp\Demo.csv
CSV文件内容:
假定有四个参数Parameter1~Parameter4 需要经常调整,现场技术员不需要到plc程序里边,而只需要修改此CSV参数,然后重新读取数据就可以了。
在此,我把第一行Parameter1~Parameter4称为title行。
把100,110,120,132,成为参数行(Parameters)
PROGRAM MAIN
VAR
(*Huang HanSheng 2017-03-21*) (* Read CSV file from computer*)
fbFileClose: FB_FileClose;
fbFileGets: FB_FileGets;
fbFileOpen: FB_FileOpen;
fbCSVMemBufferReader: FB_CSVMemBufferReader;
sCSVField,sCSVLine,tmpString: T_maxstring;
fileName:STRING := 'C:\Temp\Demo.csv'; //file directory
lineIdx:INT; //lineIdx=0-->Title, lineIdx=1-->Parameters
Steps:eSteps; // 自己定义的一个枚举变量
bStart: BOOL;
strPara: ARRAY[1..4] OF STRING; //输出参数数组
strTitle: ARRAY[1..4] OF STRING; //输出参数Title数组
END_VAR
主程序代码段
DEFAULT_CSV_FIELD_SEP:= 16#2C; //配置CSV文件的分割符,16#2C表明各个参数之间是用逗号分隔的。
IF bStart THEN //bStart是总的开始变量,把bStart置位true,则程序开始读取数据
CASE Steps OF
Step_Init: //读取CSV文件初始步骤
fbFileOpen(bExecute:=FALSE);
fbFileClose(bExecute:=FALSE);
fbFileGets(bExecute:=FALSE);
lineIdx:= 0;
Steps:= Step_OpenFile;
Step_OpenFile: //FB_FileOpen 用打开csv文件
fbFileOpen(sNetId:='',sPathName:=fileName,nMode:=FOPEN_MODEREAD OR FOPEN_MODETEXT,
ePath:=PATH_GENERIC,bExecute:=TRUE,tTimeout:=T#3S,bBusy=> ,bError=>,nErrId=>,hFile=> );
IF NOT fbFileOpen.bBusy AND NOT fbFileOpen.bError THEN //确保打开Demo.csv文件正确无错误的情况下执行下一步
Steps:= Step_Getfile;
END_IF
Step_Getfile: //用FB_FileGets取得文件中的一行数据,并把数据存放到sCSVLine变量中
fbFileGets(sNetId:='',hFile:=fbFileOpen.hFile,bExecute:=TRUE,tTimeout:=T#3S,bBusy=> ,
bError=>,nErrId=> ,sLine=>sCSVLine,bEOF=> );
IF NOT fbFileGets.bBusy AND NOT fbFileGets.bError THEN
(* FB_FileGets中sCSVLine读取到的数据是以一个换行符'$N'结尾的,但是在
FB_CSVMemBufferReader功能块中,需要使用回车换行符'$R$N'来作为一行数据结束的分割符,所以此处为读取的
数据添加'$R' 符号*)
IF RIGHT(STR:= sCSVLine,SIZE:= 1) = '$N' THEN
sCSVLine:= REPLACE(STR1:=sCSVLine, STR2:='$r$n',L:=2,P:= LEN(STR:=sCSVLine) );
END_IF
fbFileGets(bExecute:=FALSE);//读取一行完成后,就停止执行FB_FileGets功能块
IF lineIdx = 0 THEN //此处如果lineIdx=0,则读取Title行
Steps:=Step_Title;
ELSIF lineIdx=1 THEN 此处如果lineIdx=1,则读取参数行
Steps:=Step_Para;
END_IF
lineIdx:= lineIdx+1;
END_IF
Step_Title: //读取参数的Title,并用FB_CSVMemBufferReader分解为单个的数据,存入strTitle数组中
//--------------------read 1st title
fbCSVMemBufferReader(eCmd:=eEnumCmd_First,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strTitle[1]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
//--------------------read 2nd title
fbCSVMemBufferReader(eCmd:=eEnumCmd_Next,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strTitle[2]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
//--------------------read 3rd title
fbCSVMemBufferReader(eCmd:=eEnumCmd_Next,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strTitle[3]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
//--------------------read 4th title
fbCSVMemBufferReader(eCmd:=eEnumCmd_Next,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strTitle[4]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
// 让Step 重回到Step_Getfile,准备读取参数行
Steps:= Step_Getfile;
Step_Para: //读取参数行,并用FB_CSVMemBufferReader分解为单个的数据,存入strPara中
fbCSVMemBufferReader(eCmd:=eEnumCmd_First,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strPara[1]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
//--------------------read 2nd parameter
fbCSVMemBufferReader(eCmd:=eEnumCmd_Next,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strPara[2]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
//--------------------read 3rd parameter
fbCSVMemBufferReader(eCmd:=eEnumCmd_Next,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strPara[3]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
//--------------------read 4th parameter
fbCSVMemBufferReader(eCmd:=eEnumCmd_Next,pBuffer:=ADR(sCSVLine),cbBuffer:=SIZEOF(sCSVLine)-1,
bOk=> ,getValue=>sCSVField, pValue=> ,cbValue=> ,bCRLF=> ,cbRead=> );
strPara[4]:= CSVFIELD_TO_STRING(in:= sCSVField,bQM:= FALSE);
// the steps go to Step_Close
Steps:= Step_Close;
Step_Close: //关闭打开的Demo.csv文件
fbFileClose(sNetId:='',hFile:=fbFileOpen.hFile,bExecute:=TRUE,tTimeout:=T#3S,bBusy=> ,
bError=> , nErrId=> );
(*Huang HanSheng 2017-03-21*) (* Read CSV file from computer*)
END_CASE
END_IF
Step的定义方法和具体代码:
TYPE eSteps :
(
Step_Init := 0,
Step_OpenFile:=10,
Step_Getfile:=20,
Step_Title:= 30,
Step_Para:= 35,
Step_Close:= 40,
Step_Last:= 100
);
END_TYPE