You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题根源分析

  1. R_TRIG触发逻辑错误:RisingEdge(CLK:=TRUE)会让上升沿检测只在程序第一次扫描时触发一次,后续无法再触发状态切换,这会限制状态机的触发流程,但更核心的问题是FB_FileOpen的执行逻辑错误。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:11:12