如何在Matlab中连续读取串口?

时间:2015-01-15 21:08:32

标签: multithreading matlab serial-port

这是我的代码:

serialPort = 'COM3';
s = serial(serialPort,'BaudRate',9600);    
if (s.Status == 'closed')       
    s.BytesAvailableFcnMode = 'byte';
    s.BytesAvailableFcnCount = 200;
    s.BytesAvailableFcn = @Serial_OnDataReceived;

    fopen(s);
end

这是CallBack功能

function Serial_OnDataReceived(obj,event)
global s;
global i;
global endCheck;
global yVals;
global xVals;

if (s.Status == 'open')
    while s.BytesAvailable > 0 && endCheck ~= '1',
        data = str2num(fgetl(s));
        dlmwrite ('SensorsReading.csv', data, '-append');

        yVals = circshift(yVals,-1);
        yVals(end) = data(3);

        xVals = circshift(xVals,-1);
        i = i + 0.0125;
        xVals(end) = i;
    end

    figure(1);
    plot(xVals,yVals);

end    

FOPEN功能之后,我收到此警告:

  

BytesAvailableFcn正在被禁用。启用回调属性   要么使用FOPEN连接到硬件,要么设置BytesAvailableFcn属性。

回调函数Serial_OnDataReceived中发生的逻辑是否在另一个线程上运行?

有没有办法将参数传递给函数?我想从回调函数修改主脚本中的数组,该函数位于不同的文件中。最好的方法是什么? 我还试图在他们更新时绘制值以显示某种动态动画。

2 个答案:

答案 0 :(得分:0)

我不确定是什么产生了警告,但是为了回答你的另一个问题(如何将参数传递给回调以及如何更新情节),更好的方法是准备你的情节以外的回调,然后将句柄传递给回调仅用于更新。

nPointsInFigure = 10 ;  %// number of "sliding points" in your figure
step = 0.0125 ;         %// X points spacing
xVals = linspace(-(nPointsInFigure-1)*step,0,nPointsInFigure) ; %// prepare empty data for the plot
yVals = NaN(nPointsInFigure,1) ;

figure(1) ;
hp = plot( xVals , yVals ) ; %// Generate the plot (with empty data) it will be passed to the callback.

serialPort = 'COM3';
s = serial(serialPort,'BaudRate',9600);  
if (s.Status == 'closed')       
    s.BytesAvailableFcnMode = 'byte';
    s.BytesAvailableFcnCount = 200;
    s.BytesAvailableFcn = {@Serial_OnDataReceived,hp,step} ; %// note how the parameters are passed to the callback 
    fopen(s);
end

您的回调将变为:

function Serial_OnDataReceived(obj,event,hp,step)

global endCheck; %// I don't know how you use that so I could not get rid of it.

xVals = get(hp,'XData') ; %// retrieve the X values from the plot
yVals = get(hp,'YData') ; %// retrieve the Y values from the plot

while obj.BytesAvailable > 0 && endCheck ~= '1',
    data = str2num(fgetl(s));
    dlmwrite ('SensorsReading.csv', data, '-append');

    yVals = circshift(yVals,-1);
    yVals(end) = data(3);

    xVals = circshift(xVals,-1);
    xVals(end) = xVals(end-1) + step ;
end

set( hp , 'XData',xVals , 'YData',yVals ) ; %// update the plot with the new values

另请注意:(1)您无需在回调函数中检查串口的状态是否打开/关闭。如果事件被触发,则表示端口已打开。 (2)您不需要将s声明为全局,obj参数实际上是串行对象本身。

答案 1 :(得分:0)

如果Hoki的建议不起作用,请尝试使用计时器。

% The following line is useful for debugging 
mytimerCallback = @(~, ~) disp('Caught error For Tenzo Timer');

if isempty(timerXbee)
     timerXbee = timer('ExecutionMode','FixedRate','Period',0.1,...
                    'TimerFcn',{@storeDataFromSerial},'ErrorFcn', mytimerCallback);
     try
         start(timerXbee);  
     catch
         disp('Timer Xbee');
         disp '******** InstrumentSubscription ERROR *********'
         disp (exception.message);
         disp '***********************************************'
     end
end

% If you are using a polling approach, request data

sendRequest(cmd);
connectionRequested = true;

然后实现将在每个句点调用的计时器函数

function storeDataFromSerial(~,~,~)
    while (get(xbee, 'BytesAvailable')~=0)
        serialProtocol();                
    end
end  

如果要断开设备并关闭通信,请不要忘记使用

停止计时器
stop(timerXbee)