作者:岚膺麒钿
日期:2020.2.18
咨询QQ:2498317094(加QQ时要注明是干什么的)
关于Matlab,很多人只知道它是一个强大的数学工具,但是Matlab也可以用于嵌入式,制作界面,和下位机交互数据,实时绘制出曲线图。本文将简单介绍如何利用Matlab制作串口接收界面,实时绘制曲线。这里要用到的知识有很多,例如:matlab的GUI编程、定时器,串口通信、回调函数、Matlab的画图等。
一些知识也不多废话,直接上代码
一、主界面代码(main.m)
clc;
clear;
close all;
%%%%%%%%%%%%%%%%%%%%全局变量定义%%%%%%%%%%%%%%%%%%%%%
global Xmin Xmax Ymax Ymin X_Start X_End Y_Start Y_End %画曲线的重要变量
global ReceiveFlag FlagStartOrEnd COM_flag %标志位
global hf ha T hb1 hb4 hb2 scom hbcomText hbPlotText hbDataText %句柄变量
global comReceiveData AllReceiveY
%变量初始化
Xmin=-1;
Xmax=10;
Ymax=10;
Ymin=-1;
X_Start=0;
X_End=0;
Y_Start=0;
Y_End=0;
AllReceiveY=[];
FlagStartOrEnd=0;
COM_flag=0;
ReceiveFlag=0;
T=[];
scom=[];
comReceiveData=[];
% 建立界面
hf = figure('Units', 'Normalized', 'Menubar', 'figure','NumberTitle', 'off','Name', '程隆军制作(天津工业大学)','menubar','none');
set(gcf,'position',[0.2,0.1 0.6,0.8]);
ha = axes('Parent', hf, 'Units', 'Normalized','Position', [0.2 0.05 0.75 0.9]);
T = timer('Period',0.1,'ExecutionMode','FixedRate', 'TasksToExecute',inf,'TimerFcn','TimeCallback();');
hb4 = uicontrol('Parent', hf, 'Units', 'Normalized','Position', [0.02 0.85 0.1 0.1], ...
'String', '打开串口','fontsize',16,... %控件字体大小...
'Callback','COM_OffOrOn();');
hb1 = uicontrol('Parent', hf, 'Units', 'Normalized',...
'fontsize',16,... %控件字体大小
'Position', [0.02 0.7 0.1 0.1], 'String', '开始',...
'Callback','StartOrEnd();');
hb2 = uicontrol('Parent', hf, 'Units', 'Normalized',...
'fontsize',16,... %控件字体大小
'Position', [0.02 0.55 0.1 0.1], 'String', '保存',...
'Callback','SaveData(AllReceiveY);');
hbPlotText = uicontrol('Parent', hf, 'Units', 'Normalized','Position', [0 0.2 0.15 0.03 ], 'String', '停止',...
'Style', 'text',...
'fontname','仿宋',... %控件字体
'fontsize',16,... %控件字体大小
'foregroundc',[0 0 0],... %控件内字的颜色
'backgroundcolor',[1 1 1]); %控件背景颜色设置
hbcomText = uicontrol('Parent', hf, 'Units', 'Normalized','Position', [0 0.1 0.15 0.03], 'String', '串口关闭了',...
'Style', 'text',...
'fontname','仿宋',... %控件字体
'fontsize',16,... %控件字体大小
'foregroundc',[0 0 0],... %控件内字的颜色
'backgroundcolor',[1 1 1]); %控件背景颜色设置
hbDataText = uicontrol('Parent', hf, 'Units', 'Normalized','Position', [0 0.3 0.15 0.03], 'String', '无数据',...
'Style', 'text',...
'fontname','仿宋',... %控件字体
'fontsize',16,... %控件字体大小
'foregroundc',[0 0 0],... %控件内字的颜色
'backgroundcolor',[1 1 1]); %控件背景颜色设置
set(hf, 'DeleteFcn', {@DeleteAll});
二、串口配置代码(COM_OffOrOn.m)
function COM_OffOrOn()
global scom COM_flag hb4 FlagStartOrEnd hbcomText
if (FlagStartOrEnd==0)
if (COM_flag==0)
ComName_list1=inputdlg('请输入串口名称');
ComName_list=ComName_list1{1,1};
BaudRateName_list_Str=inputdlg('请输入串口比特率');
BaudRateName_list_num=str2num(BaudRateName_list_Str{1,1});
delete(instrfindall) % 关闭串口,此句十分重要,下篇再详细解释
% global s; % 全局变量,供串口中断函数使用
% s = serial('com3'); %使用默认设置创建串口s
% fopen(s); %打开串口
% set(s,'BytesAvailableFcnMode','Terminator'); %设置中断触发方式
% set(s,'Terminator','H');
% s.BytesAvailableFcn =@ReceiveCallback; % 定义中断响应函数对象
scom=serial(ComName_list);
% scom=serial(ComName_list,'BaudRate',BaudRateName_list_num,'Parity','none','DataBits',8,'StopBits',1);%设置串口属性
set(scom,'BaudRate',BaudRateName_list_num,...
'Parity','none',...
'DataBits',8,...
'StopBits',1);
set(scom,'BytesAvailableFcnMode','terminator');
set(scom,'terminator',10);
scom.BytesAvailableFcn=@ReceiveCallback;
try
fopen(scom);
set(hb4,'String', '关闭串口','foregroundc',[1 0 0]);
COM_flag=1;
catch
errordlg('串口打开失败!');
fclose(scom);%关闭串口设备对象
delete(scom);%删除内存中的串口设备对象
clear scom; %清除工作空间中的串口设备对象
end
else
COM_flag=0;
set(hb4,'String', '打开串口','foregroundc',[0 1 0]);
fclose(scom);%关闭串口设备对象);%关闭串口设备对
set(hbcomText,'String','串口关闭了','foregroundc',[0 0 0]);
end
else
errordlg('请先停止!');
end
三、绘制曲线代码(MyPlot.m)
function MyPlot(Data)
global Xmin Xmax Ymax Ymin X_Start X_End Y_Start Y_End ha AllReceiveY
Y_End=Data;
X_End=length(AllReceiveY)*0.1;
line([X_Start(1) X_End(1)],[Y_Start(1) Y_End(1)],'color','r','linestyle','-','Parent',ha,'linewidth',1);
if (Xmin>min(X_End))
Xmin=min(X_End);
end
if (Xmax<max(X_End))
Xmax=max(X_End);
end
if (Ymin>Y_End)
Ymin=Y_End;
end
if (Ymax<Y_End)
Ymax=Y_End;
end
if (Xmax-Xmin>10)
Xmin=Xmin+0.1;
end
axis(ha,[Xmin Xmax Ymin Ymax]);
Y_Start=Y_End;
X_Start=X_End;
四、串口接收代码(ReceiveCallback.m)
function ReceiveCallback(obj,event)
global scom ReceiveFlag comReceiveData hbcomText
temp = fscanf(scom) ; % 接收数据并显示(无分号)
if (temp(1)=='$')
comReceiveData=temp(2:1:end);
ReceiveFlag=1;
set(hbcomText,'String','串口接收成功','foregroundc',rand(1,3));
else
set(hbcomText,'String','串口接收失败','foregroundc',[1 0 0]);
end
% I = 'I received' % 检验是否中断响应函数正常被触发(无分号)
五、保存数据代码(SaveData.m)
function SaveData(Data)
global FlagStartOrEnd
if (FlagStartOrEnd==1)
errordlg('请先停止!');
else
if (length(Data)==0)
errordlg('数据为空!');
else
DataName=inputdlg('请输入文件名称,本次保存为文本文件');
DataName_list=DataName{1,1};
fid=fopen([DataName_list,'.txt'],'a');
[m,n]=size(Data);
for i=1:m
for j=1:n
if (j==n)
fprintf(fid,'%d',Data(i,j));
else
fprintf(fid,'%d,\t\t',Data(i,j));
end
end
fprintf(fid,'\r\n');
end
fclose(fid);
end
end
六、开始/暂停(StartOrEnd.m)
function StartOrEnd()
global FlagStartOrEnd hb1 T COM_flag hbPlotText
if (COM_flag==1)
if (FlagStartOrEnd==0)
FlagStartOrEnd=1;
start(T);
set(hb1,'String','停止','foregroundc',[1 0 0]);
% set(hbPlotText,'String','画图ing!','foregroundc',rand(1,3));
else
FlagStartOrEnd=0;
stop(T);
set(hb1,'String','开始','foregroundc',[0 0 1]); %控件背景颜色设置;
set(hbPlotText,'String','停止画图!','foregroundc',[0 0 0]);
end
else
errordlg('请先打开串口!');
end
七、定时器回调函数(TimeCallback.m)
function TimeCallback()
global ReceiveFlag comReceiveData hbPlotText AllReceiveY hbcomText hbDataText
Data=0;
if (ReceiveFlag==1)
ReceiveFlag=0;
Data=str2num(comReceiveData);
if (length(Data)==1)
AllReceiveY=[AllReceiveY;Data];
MyPlot(Data);
Data=[];
set(hbPlotText,'String','画图ing!','foregroundc',rand(1,3));
set(hbDataText,'String',comReceiveData,'foregroundc',[0 0 1]);
comReceiveData=[];
else
set(hbPlotText,'String','数据格式错误!','foregroundc',[1 0 0]);
set(hbDataText,'String','无数据','foregroundc',[1 1 1]);
end
else
set(hbPlotText,'String','画图失败!','foregroundc',[1 0 0]);
set(hbcomText,'String','串口接收失败','foregroundc',[1 0 0]);
set(hbDataText,'String','无数据','foregroundc',[1 1 1]);
end
八、安全关闭窗口代码(DeleteAll.m)
function DeleteAll(hObject, eventdata,~)
global scom T COM_flag
if (isempty(T)~=1)
stop(T);
delete(T);
else
clear T;
end
if(isempty(scom)~=1 )
fclose(scom);%关闭串口设备对象
delete(scom);%删除内存中的串口设备对象
clear scom; %清除工作空间中的串口设备对象
else
clear scom;
end
好了,以上就是全部代码,一共是8个.m文件。因为我喜欢分开写代码,所以就写在了8个脚本文件中,下图就是界面图。
说明
功能:串口单坐标轴单曲线接收,并可以保存数据。
使用方法:
1、运行"main.m"
2、点击“打开串口按键”,输入串口名称(例如:com1)和比特率(例如:9600)
3、点击“开始”按键,即开始画图
注意:
1、先打开串口,再开始
2、先停止,再关闭串口
3、先停止,再保存数据
4、串口发送格式:$+数据+回车,例如:$12(回车) “$”和“回车”很重要!!!!!!!