【问题标题】:How to run callback functions independently guide matlab如何独立运行回调函数指导matlab
【发布时间】:2016-05-01 13:13:47
【问题描述】:

存在带有两个按钮的 MATLAB GUI。每个按钮开始执行从 Com-Port(不同)读取串行数据的无限循环。当我按下一个按钮时,while 循环读取串行端口,但是当我按下下一个按钮时,port1 停止,然后 port2 开始读取,当我停止时port2port1 正在恢复。所以我的问题是,所有带有 while 循环的回调函数如何能够独立并同时工作..

function samplegui_OpeningFcn(hObject, ~, handles, varargin)



handles.output = hObject;
handles.vec_A=[];
handles.vec_B=[];
handles.vec_C=[];

handles.vec_A_1=[];
handles.vec_B_1=[];
handles.vec_C_1=[];
guidata(hObject, handles);

function open_Callback(hObject, eventdata, handles) % push button1 to receive serial data.

cnt=0;

while 1

       % Getting data  from Serial Port
        get_lines=fgets(handles.se) % getting data from serial port 
           if~isempty(get_lines)
            cnt=cnt+1;   
       if strfind(get_lines,'T')   %Parsing data
       handles.vec_A=[handles.vec_A;[timet newword]];
       plot(handles.vec_A(:,1),handles.vec_A(:,2:end),'r'); % plotting

       % Same follows for parsing and plot vec_B and Vec_C
       drawnow(); % to update the Plots
       end
     end
Pause(.05);


end
guidata(hObject, handles);

function open2_Callback(hObject, eventdata, handles) % push button2 to receive serial data.

cnt=0;

while 1

       % Getting data  from Serial Port
        get_lines=fgets(handles.se2) % getting data from serial port2 
           if~isempty(get_lines)
            cnt=cnt+1;   
       if strfind(get_lines,'T')   % Parsing data
       handles.vec_A_1=[handles.vec_A;[timet newword]];
       plot(handles.vec_A_1(:,1),handles.vec_A_1(:,2:end),'r'); % plotting

       % Same follows for parsing and plot vec_B and Vec_C
       drawnow(); % to update the Plots
       end
     end
Pause(.05);


end
guidata(hObject, handles)

【问题讨论】:

    标签: multithreading matlab callback matlab-guide


    【解决方案1】:

    您无法在 MATLAB 中执行此操作,因为一次只能执行一个任务。解决这个问题的方法是有一个timer,它以给定的时间间隔监听每个串行端口,并且按钮启动/停止这个计时器。在这种情况下,您不需要带有pausewhile 循环,您只需要一个从串行端口获取数据一次并在每次定时器触发时调用此函数的函数。

    %// Function called each time a timer is fired, gets data from specified serial port
    function getData(hObject, handles, serialport)
        get_lines = fgets(serialport);
    
        if isempty(get_lines)
            return
        end
    
        if strfind(get_lines,'T')
            handles.vec_A = [handles.vec_A; [timet newword]];
            plot(handles.vec_A(:,1),handles.vec_A(:,2:end),'r');
            drawnow();
        end
    
        guidata(hObject, handles);
    end
    
    %// And for your button callbacks that will toggle the timers on/off
    function open2_Callback(hObject, eventdata, handles)
    
        if ~isfield(handles, 't2') || ~isvalid(handles.t2) || ~handles.t2.Running
            %// Create a timer that checks the serial port twice a second
            handles.t2 = timer('ExecutionMode', 'fixedRate', ...
                               'Period', 0.5, ...
                               'TimerFcn', @(s,e)getData(hObject, handles, handles.se2));
    
            %// Start the timer
            start(handles.t2);
        else
            %// Stop and destroy the timer
            stop(handles.t2);
            delete(handles.t2);
        end
    
        guidata(hObject, handles);
    end
    
    function open_Callback(hObject, eventdata, handles)
        if ~isfield(handles, 't1') || ~isvalid(handles.t1) || ~handles.t1.Running
            handles.t1 = timer('ExecutionMode', 'fixedRate', ...
                               'Period', 0.5, ...
                               'TimerFcn', @(s,e)getData(hObject, handles, handles.se1));
            start(handles.t1);
        else
            stop(handles.t1);
            delete(handles.t1);
        end
    
        guidata(hObject, handles);
    end
    

    更新

    正如 cmets 中的@Hoki 所提到的,您还可以设置串行连接的byteAvailableFcn 属性,该属性会在新数据到达时自动触发(有点异步)。这将使您不必定期轮询串行端口以获取新数据。

    function getData(serialport, hObject, handles)
        get_lines = fgets(serialport);
    
        if strfind(get_lines,'T')
            handles.vec_A = [handles.vec_A; [timet newword]];
            plot(handles.vec_A(:,1),handles.vec_A(:,2:end),'r');
            drawnow();
        end
    
        guidata(hObject, handles);
    end
    
    set([handles.se2, handles.se1], 'BytesAvailableFcn', @(s,e)getData(s, hObject, handles);
    

    【讨论】:

    • 如果预期的数据量很大,我也倾向于使用计时器,但您也可以提到串行端口的内置回调byteavailableFcn,它也会静默监听并在数据时触发到达串口。
    • @Suever 是否可以分别从端口保存和绘制数据!!
    • @MaK 您可以为每个串行端口设置单独的回调,并在回调中进行自定义绘图。
    • @Suever 我为串口写了三个独立的函数,获取_data1,获取_data2,获取data3。并使用相应的按钮调用计时器功能。我仍然无法并行读取端口。
    • @MaK 正如我一开始所说,它永远不会真正平行。如果您发布一些您拥有的代码,我可以帮助您找出问题所在
    【解决方案2】:
    function samplegui_OpeningFcn(hObject, ~, handles, varargin)
    
        handles.output = hObject;
    
        handles.vec_A=[];
        handles.vec_B=[];
        handles.vec_C=[];
    
        handles.vec_A_1=[];
        handles.vec_B_1=[];
        handles.vec_C_1=[];
    
        guidata(hObject, handles);
    end
    
    function getData_1(hObject, handles, serialport)
        get_lines = fgets(handles.se_1);
    
        if isempty(get_lines)
            return;
        end
    
        if strfind(get_lines,'T')
            handles.vec_A = [handles.vec_A; [timet newword]];
            plot(handles.axes1,handles.vec_A(:,1),handles.vec_A(:,2:end),'r');
            drawnow();
        end
    
        guidata(hObject, handles);
    end
    
    function getData_2(hObject, handles, serialport) 
        figure;
        hold on;
        ax(1)=subplot(3,1,1);
        ax(2)=subplot(3,1,2);
        ax(3)=subplot(3,1,3);
    
        get_lines = fgets(serialport);
    
        if isempty(get_lines)
            return
        end
    
        if strfind(get_lines,'T')
            handles.vec_A_1 = [handles.vec_A; [timet newword]];
            plot(handles.vec_A_1(:,1),handles.vec_A_1(:,2:end),'r');
            drawnow();
        end
    
        guidata(hObject, handles);
    end
    
    function open2_Callback(hObject, eventdata, handles)
    
        if ~isfield(handles, 't2') || ~isvalid(handles.t2) || ~handles.t2.Running
            %// Create a timer that checks the serial port twice a second
            handles.t2 = timer('ExecutionMode', 'fixedRate', ...
                               'Period', 0.5, ...
                               'TimerFcn', @(s,e)getData_2(hObject, handles, handles.se2));
    
            %// Start the timer
            start(handles.t2);
        else
            %// Stop and destroy the timer
            stop(handles.t2);
            delete(handles.t2);
        end
    end
    
    function open1_Callback(hObject, eventdata, handles)
        if ~isfield(handles, 't1') || ~isvalid(handles.t1) || ~handles.t1.Running
    
            %// Create a timer that checks the serial port twice a second
            handles.t2 = timer('ExecutionMode', 'fixedRate', ...
                               'Period', 0.5, ...
                               'TimerFcn', @(s,e)getData_2(hObject, handles, handles.se2));
    
            %// Start the timer
            start(handles.t2);
        else
            %// Stop and destroy the timer
            stop(handles.t2);
            delete(handles.t2);
        end
    end
    

    你给出的代码是相似的。添加了while循环,因为它无法在端口连续读取数据。

    【讨论】:

    • 我已将您的帖子更新为真正可读。还修复了一些错误。发布时应该没有任何问题。如果有,请发布确切的错误消息。
    猜你喜欢
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多