TwinCAT 3问题排查:FB_FileOpen持续Busy致状态机卡顿
TwinCAT中FB_FileOpen的bBusy始终为True导致状态机卡住的问题解决
作为Beckhoff/TwinCAT新手,跟着教程制作简易事件日志器时遇到问题:调用FB_FileOpen后,其bBusy始终为True,状态机卡在FILE_OPEN状态。以下是原代码:
VAR fbFileOpen : FB_FileOpen; fbFilePuts : FB_FilePuts; RisingEdge : R_TRIG; eWriteState : (If_Trigger_Detection,OpenFile_Trigger, OpenFile, WaitForTheEvent, WriteFileTriggner, WriteFile, CloseFile, Error); stEventWriteToFile: ST_Event; CsvString : T_MaxString; END_VAR RisingEdge(CLK:=TRUE); CASE eWriteState OF If_Trigger_Detection: IF RisingEdge.Q THEN eWriteState:=OpenFile_Trigger; END_IF OpenFile_Trigger: fbFileOpen.bExecute := FALSE; fbFileOpen(sPathName:= 'C:\TwinCAT\Eventslog.txt',nMode:=FOPEN_MODEAPPEND OR FOPEN_MODETEXT,bExecute := TRUE); eWriteState:= OpenFile; OpenFile: fbFileOpen.bExecute := FALSE; IF fbFileOpen.bError THEN eWriteState := Error; ELSIF NOT fbFileOpen.bBusy AND fbFileOpen.hFile <>0 THEN eWriteState:= WaitForTheEvent; END_IF WaitForTheEvent: //do nothing just wait WriteFileTriggner: CsvString := CreateCsvString (stEvent:= stEventWriteToFile); //fbFilePuts(bExecute:=FALSE, // sLine:=CsvString); fbFilePuts.bExecute:=FALSE; fbFilePuts(sLine := CsvString,bExecute := TRUE); eWriteState := WriteFile; WriteFile: fbFilePuts(bExecute := FALSE); IF NOT fbFilePuts.bBusy THEN eWriteState := WaitForTheEvent; END_IF //CloseFile: Error: //Here we will write the code for error Handling END_CASE
问题根源分析
- R_TRIG触发逻辑错误:
RisingEdge(CLK:=TRUE)会让上升沿检测只在程序第一次扫描时触发一次,后续无法再触发状态切换,这会限制状态机的触发流程,但更核心的问题是FB_FileOpen的执行逻辑错误。 - FB_FileOpen的bExecute处理错误:
- 在
OpenFile_Trigger状态中,先设fbFileOpen.bExecute := FALSE再立刻调用功能块设为TRUE,属于冗余操作。 - 进入
OpenFile状态后立刻把fbFileOpen.bExecute := FALSE,直接中断了FB_FileOpen的异步执行流程——FB_FileOpen需要保持bExecute为TRUE直到bBusy变为FALSE,才能完成文件打开操作,中途取消会导致功能块一直处于busy状态。
- 在
修正后的代码
VAR fbFileOpen : FB_FileOpen; fbFilePuts : FB_FilePuts; RisingEdge : R_TRIG; eWriteState : (If_Trigger_Detection,OpenFile, WaitForTheEvent, WriteFileTriggner, WriteFile, CloseFile, Error); stEventWriteToFile: ST_Event; bTrigger : BOOL; // 替换为实际触发信号,比如按钮或事件标志 bWriteTrigger : BOOL; // 写入触发标志 CsvString : T_MaxString; END_VAR RisingEdge(CLK:=bTrigger); // 绑定到实际触发信号 CASE eWriteState OF If_Trigger_Detection: fbFileOpen.bExecute := FALSE; // 预先重置执行位 IF RisingEdge.Q THEN // 触发文件打开 fbFileOpen(sPathName:= 'C:\TwinCAT\Eventslog.txt',nMode:=FOPEN_MODEAPPEND OR FOPEN_MODETEXT,bExecute := TRUE); eWriteState:=OpenFile; END_IF OpenFile: // 保持bExecute为TRUE直到操作完成 IF fbFileOpen.bError THEN eWriteState := Error; fbFileOpen.bExecute := FALSE; // 出错后重置 ELSIF NOT fbFileOpen.bBusy AND fbFileOpen.hFile <>0 THEN fbFileOpen.bExecute := FALSE; // 操作完成后重置 eWriteState:= WaitForTheEvent; END_IF WaitForTheEvent: // 等待写入触发 IF bWriteTrigger THEN eWriteState := WriteFileTriggner; bWriteTrigger := FALSE; // 重置触发标志 END_IF WriteFileTriggner: fbFilePuts.bExecute := FALSE; CsvString := CreateCsvString (stEvent:= stEventWriteToFile); fbFilePuts(sLine := CsvString,bExecute := TRUE); eWriteState := WriteFile; WriteFile: IF fbFilePuts.bError THEN eWriteState := Error; fbFilePuts.bExecute := FALSE; ELSIF NOT fbFilePuts.bBusy THEN fbFilePuts.bExecute := FALSE; eWriteState := WaitForTheEvent; END_IF CloseFile: // 补充文件关闭逻辑,使用FB_FileClose // fbFileClose(hFile:=fbFileOpen.hFile, bExecute:=TRUE); // 等待关闭完成后处理 Error: // 错误处理逻辑,比如记录错误码fbFileOpen.nErrId END_CASE
关键修改点
- 将
RisingEdge的CLK绑定到实际触发信号(如bTrigger),而非固定TRUE,确保能正常触发状态切换。 - 合并
OpenFile_Trigger和If_Trigger_Detection的触发逻辑,在触发时直接调用FB_FileOpen并设置bExecute为TRUE,进入OpenFile状态后保持该位直到操作完成或出错。 - 所有功能块(FB_FileOpen、FB_FilePuts)都要在操作完成(bBusy为FALSE)或出错后再重置bExecute,避免中断异步执行流程。
- 补充了写入触发的逻辑,完善状态机的流转。
内容的提问来源于stack exchange,提问作者Aliciit
相关产品推荐
相关产品推荐

