倍福BECKHOFF PLC:File Function Blocks文件操作功能块

本文详细探讨了在倍福PLC中进行文件读写的最佳实践,包括使用字符串模式避免二进制数据读写错误,介绍了文件操作功能块如FileOpen、FileClose、FileWrite和FileRead的正确使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

测试总结

  • 1、 如果使用二进制,进行文件读写,写入浮点数618,在从文件读出,读出的结果会出错。浮点数据 = 1.000 、610、620,测试都没问题;浮点数:616 出错,读出来是608,619也出错了,从文件读出是623。暂不知是什么问题,是因为编码问题? 用其他语言读写文件会不会也会遇到这种问题?
  • 2、 所以在倍福plc中,读写文件,为了避免上面的问题,读写模式选用字符串模式(也即,读写功能块的sMode = ‘wt’ / ‘rt’) ,给文件写入的数据也用字符串型变量。

官方范例

在这里插入图片描述

实际测试

程序框架借鉴 轴控模块的思路,使用功能块与接口结构体的方式(这个坑以后在填),当然这样的思路并不是最简洁的,比如做到类似高级语言 fopen(…)这样的FUNCTION函数,编程体验自然是更好。
在这里插入图片描述

  • 结构体与功能块之间的数据传输
    在这里插入图片描述

打开文件:FileOpen

  • 关于文件打开模式,参考C语言相关解释
(*******************************************************************************************************)
(*
文件使用方式        意 义
“rt”      只读打开一个文本文件,只允许读数据
“wt”      只写打开或建立一个文本文件,只允许写数据
“at”      追加打开一个文本文件,并在文件末尾写数据
“rb”      只读打开一个二进制文件,只允许读数据
“wb”       只写打开或建立一个二进制文件,只允许写数据
“ab”                追加打开一个二进制文件,并在文件末尾写数据
“rt+”      读写打开一个文本文件,允许读和写
“wt+”      读写打开或建立一个文本文件,允许读写
“at+”      读写打开一个文本文件,允许读,或在文件末追加数 据
“rb+”      读写打开一个二进制文件,允许读和写
“wb+”      读写打开或建立一个二进制文件,允许读和写
“ab+” 		    读写打开一个二进制文件,允许读,或在文件末追加数据
*)
(*

对于文件使用方式有以下几点说明:

1. 文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是:
r(read):w(write):a(append): 追加
t(text): 文本文件,可省略不写
b(banary): 二进制文件
+: 读和写

2. 凡用“r”打开一个文件时,该文件必须已经存在, 且只能从该文件读出。

3. 用“w”打开的文件只能向该文件写入。 若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件。

4. 若要向一个已存在的文件追加新的信息,只能用“a ”方式打开文件。但此时该文件必须是存在的,否则将会出错。

5. 在打开一个文件时,如果出错,fopen将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作,并作相应的处理。因此常用以下程序段打开文件:
if((fp=fopen("c:\hzk16","rb")==NULL)
{
      printf("error on open c:\hzk16 file!");
      getch();
      exit(1);
}
  这段程序的意义是,如果返回的指针为空,表示不能打开C盘根目录下的hzk16文件,则给出提示信息“error on open c: hzk16file!”,
下一行getch()的功能是从键盘输入一个字符,但不在屏幕上显示。在这里,该行的作用是等待,只有当用户从键盘敲任一键时,
程序才继续执行, 因此用户可利用这个等待时间阅读出错提示。敲键后执行exit(1)退出程序。

6. 把一个文本文件读入内存时,要将ASCII码转换成二进制码, 而把文件以文本方式写入磁盘时,也要把二进制码转换成ASCII码,
因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换。

7. 标准输入文件(键盘),标准输出文件(显示器 ),标准出错输出(出错信息)是由系统打开的,可直接使用。文件关闭函数fclose()文件一旦使用完毕,
应用关闭文件函数把文件关闭, 以避免文件的数据丢失等错误。
*)
(*******************************************************************************************************)


(*打开文件模式,nmode:d 代表着流形态*)
IF  File_ITF.sMode = 'r'THEN 	(* r: 打开只读文件,该文件必须存在*)
	File_ITF.nMode := FOPEN_MODEREAD;

ELSIF  File_ITF.sMode = 'r+'THEN (* r+: 打开可读写文件,该文件必须存在*)
	File_ITF.nMode := FOPEN_MODEREAD OR FOPEN_MODEPLUS;

(*rb+:读写打开1个二进制文件,只允许读写数据*)
(*rt+:读写打开1个文本文件,只允许读写数据*)

ELSIF  File_ITF.sMode = 'w'THEN	(* w: 打开只写文件,若文件存在,则该文件内容会消失。若文件不存在则建立该文件*)
	File_ITF.nMode := FOPEN_MODEWRITE;

ELSIF  File_ITF.sMode = 'w+'THEN (* w+: 打开可读写文件,若文件存在,则该文件内容会消失。若文件不存在则建立该文件*)
	File_ITF.nMode := FOPEN_MODEWRITE OR FOPEN_MODEPLUS;

ELSIF  File_ITF.sMode = 'a'THEN (* a: 以追加的方式打开只写文件,若文件不存在,则新建该文件,如果文件存在,写入的数据会被追加到文件尾,即文件原先的内容会被保留。(EOF符保留)*)
	File_ITF.nMode := FOPEN_MODEAPPEND;

ELSIF  File_ITF.sMode = 'a+'THEN (* a+: 以追加的方式打开可读写文件,若文件不存在,则新建该文件,如果文件存在,写入的数据会被追加到文件尾,即文件原先的内容会被保留。(原来的EOF符不保留)*)
	File_ITF.nMode := FOPEN_MODEAPPEND OR FOPEN_MODEPLUS;
(*wb*)
(*wb+*)
(*wt*)
(*wt+*)
(*at+*)
ELSIF  File_ITF.sMode = 'at+'THEN
	File_ITF.nMode := FOPEN_MODEAPPEND OR FOPEN_MODEPLUS OR FOPEN_MODETEXT;

(*ab+*)

ELSIF  File_ITF.sMode = 'b'THEN
	File_ITF.nMode := FOPEN_MODEBINARY;

ELSIF  File_ITF.sMode = 't'THEN
	File_ITF.nMode := FOPEN_MODETEXT;
ELSE
	File_ITF.nMode :=File_ITF.nMode;
END_IF
(*EOF: 文件结束标识符,一般值为-1*)

10:
	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileOpen:=TRUE;
	IF NOT g_st_TestGroup.stFlieTxt1.st_FileInterface.bBusyOpen THEN
		stFlow_Auto.st_FlowInterface.nState	:= 20;
	END_IF
  • 查看C盘成功新建了该文件。
    在这里插入图片描述
  • FileOpen功能块在成功打开文件后,会产生一个hFile,暂时理解成文件索引,这个值很重要,是因为其他文件功能块都是基于这个值对文件进行操作的;反过来,如果直接使用其他文件操作功能块,没有FileOpen的hFile值做输入,那么操作的是哪个文件就无从得知。
    在这里插入图片描述

关闭文件:FileClose

  • 如果在我们打开文件之后,不使用关闭文件功能块关闭文件,那么我们直接在系统中删除修改保存文件,都会报文件被占用警告。
    在这里插入图片描述
    在这里插入图片描述
  • 所以我们可以用是否可以用记事本修改或者删除文件,来验证 我们的文件关闭功能块执行是否成功。
g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileClose:=TRUE;
IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileClose.Q  THEN
	stFlow_Auto.st_FlowInterface.nState	:= 20;
	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileClose:=FALSE;
END_IF

在这里插入图片描述
可改写,可删除
在这里插入图片描述
在这里插入图片描述

  • 在这里,需要注意的是,启动关闭文件,立即就检测功能块Busy信号,会有很大概率导致关闭失败;所以,在这里用下降沿功能块检测busy的下降沿,这样,就可以正确等待功能块执行成功。
    在这里插入图片描述
    当然,也可以使用延时检测Busy信号的方式,达到稳定关闭文件的效果。对于上面打开文件OpenFile操作,也是一样,不推荐立即检测busy信号。
    在这里插入图片描述

文件读写FileWirte/Puts,FileRead/Gets

  • FileRead,按照 open -> close -> close 流程
  • FileRead,按照 open -> read -> close 流程

10:
	g_st_TestGroup.stFlieTxt1.st_FileInterface.sMode:='wt';
	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileOpen:=TRUE;
	IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileOpen.Q  THEN
		stFlow_Auto.st_FlowInterface.nState	:= 20;
		g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileOpen:=FALSE;
	END_IF

20:(* open -> write -> close*)
	(*g_st_TestGroup.stFlieTxt1.st_FileInterface.pWriteBuff:=ADR(sVar);
	g_st_TestGroup.stFlieTxt1.st_FileInterface.cbWriteLen:=SIZEOF(sVar);*)

	(*g_st_TestGroup.stFlieTxt1.st_FileInterface.pWriteBuff:=ADR(nVar);
	g_st_TestGroup.stFlieTxt1.st_FileInterface.cbWriteLen:=SIZEOF(nVar);*)

	g_st_TestGroup.stFlieTxt1.st_FileInterface.pWriteBuff:=ADR(fVar);
	g_st_TestGroup.stFlieTxt1.st_FileInterface.cbWriteLen:=SIZEOF(fVar);

	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileWrite:=TRUE;
	IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileWrite.Q  THEN
		stFlow_Auto.st_FlowInterface.nState	:= 30;
		g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileWrite:=FALSE;
	END_IF
30:
	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileClose:=TRUE;
	IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileClose.Q  THEN
		stFlow_Auto.st_FlowInterface.nState	:= 40;
		g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileClose:=FALSE;
	END_IF


40:
	g_st_TestGroup.stFlieTxt1.st_FileInterface.sMode:='rt';
	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileOpen:=TRUE;
	IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileOpen.Q  THEN
		stFlow_Auto.st_FlowInterface.nState	:= 50;
		g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileOpen:=FALSE;
	END_IF

50:(* open -> read -> close*)
	(*g_st_TestGroup.stFlieTxt1.st_FileInterface.pReadBuff :=ADR(sVarRead);
	g_st_TestGroup.stFlieTxt1.st_FileInterface.cbReadLen :=SIZEOF(sVarRead);*)

	(*g_st_TestGroup.stFlieTxt1.st_FileInterface.pReadBuff:=ADR(nVarRead);
	g_st_TestGroup.stFlieTxt1.st_FileInterface.cbReadLen:=SIZEOF(nVarRead);*)

	g_st_TestGroup.stFlieTxt1.st_FileInterface.pReadBuff:=ADR(fVarRead);
	g_st_TestGroup.stFlieTxt1.st_FileInterface.cbReadLen:=SIZEOF(fVarRead);

	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileRead:=TRUE;
	IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileRead.Q  THEN
		stFlow_Auto.st_FlowInterface.nState	:= 60;
		g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileRead:=FALSE;
	END_IF

60:
	g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileClose:=TRUE;
	IF g_st_TestGroup.stFlieTxt1.fb_File.ft_FileClose.Q  THEN
		stFlow_Auto.st_FlowInterface.nState	:= 998;
		g_st_TestGroup.stFlieTxt1.st_FileInterface.bExecuteFileClose:=FALSE;
	END_IF

998:(* 流程正常结束 *)
;
  • 测试 整型618,字符型’618’,浮点型618;结果是浮点型数据会出错
    在这里插入图片描述
  • 测试2:fVal 浮点数据 = 1.000 、610、620,没问题;616 出错,读出来是608;619出错,读是623
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值