How can I read and write serial port immediatly and continuously?

39 views (last 30 days)
Hi,guys
I need to use matlab to read and write serial port for getting data from my MCU.
But actually the code is not efficiently in that I have to add a line "pause (1);" in the code to make the code run well. If I do not, the code cannot read data later.
here is the code:
-------------------the---following----is----my----code---------
%1.configure the serial port
s=serial('COM21');
s.BaudRate=115200;
fopen(s);
set(s,'ByteOrder','bigEndian');
while 1
%2.write the port
fwrite(s,61680,'uint16');
fwrite(s,m1,'uint16');
fwrite(s,m2,'uint16');
fwrite(s,m3,'uint16');
fwrite(s,m4,'uint16');
%3.read the port
start=fread(s,1,'uint16');
r_m1=fread(s,1,'uint16');
r_m2=fread(s,1,'uint16');
r_m3=fread(s,1,'uint16');
r_m4=fread(s,1,'uint16');
yaw=fread(s,1,'float32');
roll=fread(s,1,'float32');
pitch=fread(s,1,'float32');
attitude=fread(s,1,'double');
height=fread(s,1,'double');
p= fread(s, s.BytesAvailable) ; %clear the buffer
%4.display data
spr=sprintf('start=%d,m1=%d,m2=%d,m3=%d,m4=%d,yaw=%f,roll=%f,pitch=%f,attitude=%e,height=%e'
,...start,r_m1,r_m2,r_m3,r_m4,yaw,roll,pitch,attitude,height );
disp(spr);
pause(1);
end
----------------code----is----end---here-----------------------
if I add the line "pause(1);",the result is good ,but I am afraid it is too slow for my project.
but if I delete the line, it goes wrong from the second run :
I have been stuck in this problem for several days,I really hope you could help me out of this,Thanks :)

Answers (1)

Geoff Hayes
Geoff Hayes on 27 Jul 2014
Jack - Perhaps you can make use of the second return parameter from serial.fread which returns the number of variables read:
[A,count,msg] = fread(...) returns the number of values read to count, and a warning message to msg if the read operation was unsuccessful.
Is it safe to assume that once the start variable is read successfully, then those that follow should be available too? If so, then you could try the following. Remove the pause(1) that you added, and replace
start=fread(s,1,'uint16');
with
% declare a 10 millisecond delay
delaySec = 0.01;
% read from the serial port
[start,varcount,msg] = fread(s,1,'uint16');
% keep reading until the start data is returned
while varcount==0
% pause
pause(delaySec);
% try again
[start,varcount,msg] = fread(s,1,'uint16');
end
The above will continue to read from the serial port until some data is returned. A problem is getting stuck in the while loop if no data is ever going to be sent again. To get around this, you could put a cap on the number of iterations in the while loop.
% declare a 10 millisecond delay
delaySec = 0.01;
% if more than 10 seconds have passed without data, then exit
maxIters = 10/delaySec;
% use to keep track at which iteration we are at
atIter = 1;
% read from the serial port
[start,varcount,msg] = fread(s,1,'uint16');
% keep reading until the start data is returned
while varcount==0 && atIter<=maxIters
% increment the iteration count
atIter = atIter + 1;
% pause
pause(delaySec);
% try again
[start,varcount,msg] = fread(s,1,'uint16');
end
if atIter==maxIters
% 10 seconds without data so may as well quit outer while loop
break;
end
Try the above and see what happens! You can always adjust the delaySec to whatever you think is appropriate for your app.
  2 Comments
Jack Zhang
Jack Zhang on 28 Jul 2014
Edited: Jack Zhang on 28 Jul 2014
Hi,
I have tried your method,but it seems it doesn't work.I replace
start=fread(s,1,'uint16');
with
[start,varcount,msg]=fread(s,1,'uint16');
while varcount==0
pause(0.1);
[start,varcount,msg]=fread(s,1,'uint16');
end
but it cannot work.
----- ---------- -------- ------ ---------- -------- ------ -----------
-------- --------- ------- ----- ---------- -------- ------ ----------
the function fread, if there is no data, will finish until the Timeout(10s by default);
In my former code, If I add "pause(1);", the next "start=frea(s,1,'uint16')"
can receive data;but if I do not, the next "start=fread(s,1,'uint16')"
have to wait for data for about 10s.
This 10s here is longer than the 1s in "pause(1);". Theoretically,It will receive some data,but actually it receives nothing.
In your code , enven if I change pause(0.1) to pause(2),it doesn't receive anything .
the line "[start,varcount,msg]=fread(s,1,'uint16');" still have to wait for 10s if no data input.
I don't know what's wrong with my matlab code, it is very weird. 1s here
work,but 10s in another place does not work any more.
Geoff Hayes
Geoff Hayes on 28 Jul 2014
Hi Jack - I hand't realized that there was a timeout on the serial object and that its default is 10 seconds. You can change this value when you instantiate the object. Try replacing
s=serial('COM21');
with
s=serial('COM21','Timeout',0.01);
or use some other timeout value.

Sign in to comment.

Categories

Find more on Programming in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!