Matlab - тайм-аут последовательного порта, но хорошие данные получены при отправке многобайтовых типов данных - PullRequest
1 голос
/ 08 октября 2019

В настоящее время я читаю из STM32 через UART с использованием Matlab.

С помощью следующей программы я смог прочитать однобайтовые данные (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');

1 Ответ

1 голос
/ 08 октября 2019

Вы пытаетесь прочитать 4 байта данных больше, чем доступно.

in = fread(s, s.BytesAvailable, 'uint32');, читает s.BytesAvailable*4 байтов, потому что размер uint32 элементов равен 4 байта.

Согласно fread (serial) документации :

A = fread (obj, size, 'precision') считывает двоичные данные с точностью, определенной точностью. Точность
контролирует количество считываемых битов для каждого значения и интерпретацию этих битов как целочисленных, с плавающей запятой или символьных значений.

Документация не так ясна, но 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).
...