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



我目前正在使用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( 文档:

A = fread(obj,size,'precision'( 以精度指定的精度读取二进制数据。
精度控制每个值读取的位数,以及将这些位解释为整数、浮点或字符值。

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

您可以将大小除以 4:

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

一个更简洁的解决方案是读取uint8元素,并使用类型转换:

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).

相关内容

最新更新