Matlab - 串行超时但接收到多字节数据类型发送的良好数据

Matlab - Serial timeout but good data received with multibytes datatypes sending

我目前正在使用 Matlab 通过 UART 从 STM32 读取数据。

使用下面的程序,我已经能够读取单字节数据(uint8、int8、char),即使几个字节紧接着另一个。

当我尝试使用多字节数据类型(float32、uint32、...)时出现问题。控制台向我打印接收到的数据,这是 STM32 发送的数据,但是软冻结并且在 10 秒默认值超时后,我收到此警告:

Warning: The specified amount of data was not returned within the Timeout period. 'serial' unable to read all requested data. For more information on possible reasons, see Serial Read Warnings.

事实上我收到了发送的数字(并且当我用示波器检查时发送了很多比特)倾向于告诉我问题不是出在我的 STM32 软件上,而是在matlab 解释,似乎在等待其他东西。

提前感谢大家的想法

clear;
clc;

% ------------------------ TWEAKING PARAMETERS -------------------------- %
port = 'COM4'; %Serial port
    % seriallist : This command list all the COM port available
baudrate = 115200; % Frequency
dataType = 'uint32'; %Data to be received and transmitted
readDelay = 0.001; %The time between 2 buffer emptying in seconds
maxDataStored = 1000; %The number of data to be stored in final file
serialInBufferSize = 1024; %The input buffer size
    %Make sure that sending frequency < serialInBufferSize / readDelay
storeCSV = 0; %Enable storage in CSV file
% ----------------------------------------------------------------------- %

totalData = 0;
maxDataReached = 0;
timeStamps(maxDataStored) = datetime;
timeElapsed = zeros(1, maxDataStored);
receivedData = zeros(1, maxDataStored, dataType);

%Creates main control panel to end serial streaming
controlPanel = figure('WindowStyle', 'docked', ...
                        'MenuBar', 'none');
stop = uicontrol('Style', 'PushButton', ...
                    'String', 'End communication', ...
                    'Position', [0, 0, 200, 40], ...
                    'Callback', 'delete(gcbf)');
drawnow;

% Initializes serial port
disp(['Initialising serial port ' port]);
s = instrfind('port',port);
if not(isempty(s)) % Destroy existing serial port
    disp(['Killing existant communication on ' port]);
    fclose(s);
    delete(s);
    clear s
end
s = serial(port,'BaudRate',baudrate, ...
    'InputBufferSize', serialInBufferSize, ...
    'Parity', 'even');
fopen(s);

startTime = datetime('now');
disp(['Port ' port ' initialised successfully at ' num2str(baudrate) ...
    ' bauds']);
disp('Beginning of communication');
disp(' ');

% Main script to stream data
while (ishandle(stop) && maxDataReached == 0)
    %The < 4 condition was an unsuccessfull test, it used to be == 0
    while (s.BytesAvailable < 4 && ishandle(stop))
        pause (readDelay);
    end
    if(ishandle(stop))
        in = fread(s, s.BytesAvailable, dataType);
        for i = 1 : length(in)
            if (totalData + 1 > maxDataStored)
               maxDataReached = 1;
               disp(' ');
               disp('Maximum amount of received data reached');
               break 
            end
            dt = seconds((datetime('now') - startTime));
            %Storage
            timeStamps(totalData + 1) = datetime('now');
            timeElapsed(totalData + 1) = dt;
            receivedData(totalData + 1) = in(i);
            %Console printing
            disp([datestr(now,'HH:MM:SS.FFF'), '  ||  ', ...
                num2str(dt, '%.3f'), ...
                's since startup  ||  received : ', ...
                num2str(in(i))]);
            totalData = totalData + 1;
        end
        pause(0.01);
    end
end

% Closes serial port
disp(' ');
disp(['Ending communication on port ' port ' ...']);
fclose(s);
delete(s);
clear s
disp('Communication ended properly (I hope so...)');

%Script termination
close(gcf);
disp(' ');
disp('Script ended');

您正在尝试读取比可用数据字节多 4 倍的数据字节。

in = fread(s, s.BytesAvailable, 'uint32');,读取 s.BytesAvailable*4 个字节,因为 uint32 个元素的大小是 4 个字节。

根据fread (serial) documentation

A = fread(obj,size,'precision') reads binary data with precision specified by precision.
precision controls the number of bits read for each value and the interpretation of those bits as integer, floating-point, or character values.

文档不是很清楚,但是 size 参数指定了元素的数量(例如 uint32 元素的数量),而不是字节数。

您可以将大小除以 4:

dataType = 'uint32'; %Set dataType to 'uint32' or 'float32`.
in = fread(s, s.BytesAvailable/4, dataType);

更简洁的解决方案是读取 uint8 个元素,并使用 typecast

in = fread(s, s.BytesAvailable/4, '*uint8'); %The '*uint8' keeps data in uint8 class (not double).
in = typecast(in, dataType); %Convert to 'uint32' or 'single', according to dataType.
in = double(in); %Convert to double (for compatibility).