MATLAB GUI图形界面实现串口通讯实时绘图(一)

MATLAB GUI图形界面实现串口通讯实时绘图(一)

前言

之前做了一些概念性的理解,现在把实现GUI界面串口实时绘图的主要注意方面记录一下,以防以后忘记。
主要参考了文库的一篇文章——MATLAB串口操作教程,翻译的应该是官方的教程。基础的东西不再提了,说一下需要注意的地方

串口通讯

  • 最好在使用s=serial(‘COM1’);命令打开串口之前,写上delete(instrfindall);就是关闭其他没有在用的端口。
  • s.ReadAsyncMode='continuous';或者s.ReadAsyncMode='manual';其中’continuous’模式是发完一段一起读进来,'manual’是有啥就读。
  • 在发过来的字符串中,刚刚打开时字符串不完整,使用
if length(out)<73
   continue
else
   ......

语句来判断发送过来的字符串完整度,其中continue的作用是直接返回下一个循环不再向下执行语句。

  • 使用完后要将打开的端口关闭,这是个好习惯

实时绘图

  • 实时绘图的方法有这几个,还了解过animateline结合addpoints和drawnow的方法,但是貌似只能适用一条曲线,我要画出6条,所以不适用(有大神能实现可以讨论一下啊)。最后选择了hold on模式下的 动态多条曲线(即时数据) 的方法,其中plot(x,y,'EraseMode','background','MarkerSize',5);的’EraseMode‘,'background’被提示不用了(Matlab版本2017b),将其删除后效果不变,不影响运行。

  • 若要实现x轴的实时变化就需要对坐标轴进行实时改动

    ......
    
      x_qujian=0;
    
      axis([x_qujian x_qujian+10 20000 50000])
    
      ......
      for i=1:1000
     ......
          drawnow
             x_qujian=x_qujian+0.1;
             axis([x_qujian x_qujian+10 min(min(b1)) max(max(b1))])
     .....
     end
    

其中…为其他中间过程,省略。b1为矩阵,写成上面代码中的样子是为了实时调整纵坐标范围,使曲线一直显示在坐标中。

  • 根据上述的教程中的方法,编写多条动态曲线时,需要事先写上在plot中…相当于是定义出来吧,例如real_plot=plot(x_p,y_p1,x_p,y_p2,x_p,y_p3,x_p,y_p4,x_p,y_p5,x_p,y_p6,'MarkerSize',5);我想以x_p为横坐标y_p?为纵坐标画6条曲线,就需要事先这样写。纵坐标的数据必须放到不同的变量中,如果放到同一个矩阵中利用取行列的方式表示,就不能画出曲线,原因未知。设置多条动态曲线的格式如下
        hold on
        x_p=[x_p 5+0.1*(j+1)];
        y_p1=[y_p1 b1(j,1)];y_p2=[y_p2 b1(j,2)];y_p3=[y_p3 b1(j,3)];y_p4=[y_p4 b1(j,4)];y_p5=[y_p5 b1(j,5)];y_p6=[y_p6 b1(j,6)];
        set(real_plot(1),'XData',x_p,'YData',y_p1)
        set(real_plot(2),'XData',x_p,'YData',y_p2)
        set(real_plot(3),'XData',x_p,'YData',y_p3)
        set(real_plot(4),'XData',x_p,'YData',y_p4)
        set(real_plot(5),'XData',x_p,'YData',y_p5)
        set(real_plot(6),'XData',x_p,'YData',y_p6)
        drawnow

x_p是每条曲线的起始点,通过不断给x_p赋值来时曲线更新,赋值方式与横坐标轴的赋值方式最好一致。

  • 有一个清空缓冲区的命令fread(s,s.BytesAvailable);原理未知。

GUI图形界面

先看一下GUI图形界面的整体布局以及实现功能(数据转化肯定不准确,后期需要优化,先看功能实现)
在这里插入图片描述

  • 端口号是利用seriallist函数获得活跃端口,存储到矩阵中,在显示在下拉菜单中,目前手头只有一个串口,无法测试功能完整性(目测会在矩阵cell与string之间转换出现问题)
  • handles.***是将属性名为***的值在不同的控件中传递,但好像只有原始的handles.***的值发生改变后才会使这个变量变化,若在其他控件中改变其值,返回后仍为原值(应该是所谓的局部变量吧)。在每次给handles.***赋值后,要用guidata(hObject, handles);将结构更新
  • 如果需要在很多控件中使用并改变变量值,需要使用全局变量global ***
  • 按钮的字符串互相转换,是利用strcmp对比字符串函数实现
  • 在不同的坐标轴中画图,要利用plot(handles.axes1,x,y)。改变横纵坐标利用handles.axes3.XLimhandles.axes3.YLim。改变其他参量,双击参看属性值。

遇到的问题

  • 目前对中断回调还不是很明白,不太会用,回调函数是自己创建的么?我想实现一个打开串口错误就退出重新加载窗口的回调函数,怎么实现?

完整代码

  • 其中pushbutton4为GUI中的打开串口按钮,pushbutton1为清零按钮,
function varargout = chuankou02(varargin)

gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @chuankou02_OpeningFcn, ...
                   'gui_OutputFcn',  @chuankou02_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before chuankou02 is made visible.
function chuankou02_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to chuankou02 (see VARARGIN)

% Choose default command line output for chuankou02
handles.output = hObject;
%初始化参数
saomiao=seriallist;
set(handles.popupmenu2,'string',saomiao)
handles.x_qujian=0;
global j_0
j_0=1;
guidata(hObject, handles);
% UIWAIT makes chuankou02 wait for user response (see UIRESUME)
% uiwait(handles.figure1);

function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global j_0
j_0=handles.j;
guidata(hObject, handles);
% --- Executes on button press in pushbutton2.

function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global s j_0 biaoji
if strcmp(get(handles.pushbutton4,'string'),'打开串口')
    try
        delete(instrfindall) %关闭没用的,这句很重要
        duankou_zhi=get(handles.popupmenu2,'value');
        duankou_zong=get(handles.popupmenu2,'string');
        handles.duankou=duankou_zong(duankou_zhi,:);
        handles.botelv=str2double(get(handles.edit1,'string'));
        s=serial(handles.duankou);%创建串口
        set(s,'BaudRate',handles.botelv); %设置波特率
        set(s,'inputBufferSize',1024000) %设置输入缓冲区域为1M
        s.ReadAsyncMode='continuous';
        fopen(s);
        biaoji=1;
        set(handles.pushbutton4,'string','关闭串口');
        msgbox(['打开',handles.duankou,'成功']);
    catch err
        msgbox('打开失败');
    end   
        x_qujian=handles.x_qujian;
        hold off
 
        x_p=5;
        y_p1=0;y_p2=0;y_p3=0;y_p4=0;y_p5=0;y_p6=0;
        real_u_plot=plot(handles.axes1,x_p,y_p1,x_p,y_p2,x_p,y_p3,x_p,y_p4,x_p,y_p5,x_p,y_p6,'MarkerSize',5);
        handles.axes1.XLim=[x_qujian x_qujian+10];handles.axes1.YLim=[20000 50000];
        handles.axes1.XGrid='on';handles.axes1.YGrid='on';
 
        x_p_chazhi=5;
        y_p_chazhi1=0;y_p_chazhi2=0;y_p_chazhi3=0;y_p_chazhi4=0;y_p_chazhi5=0;y_p_chazhi6=0;
        chazhi_u_plot=plot(handles.axes2,x_p_chazhi,y_p_chazhi1,x_p_chazhi,y_p_chazhi2,x_p_chazhi,y_p_chazhi3,x_p_chazhi,y_p_chazhi4,x_p_chazhi,y_p_chazhi5,x_p_chazhi,y_p_chazhi6,'MarkerSize',5);
        handles.axes2.XLim=[x_qujian x_qujian+10];handles.axes2.YLim=[-5 5];
        handles.axes2.XGrid='on';handles.axes2.YGrid='on';
 
        x_p2=5;
        y_p_ft1=0;y_p_ft2=0;y_p_ft3=0;y_p_ft4=0;y_p_ft5=0;y_p_ft6=0;
        ft_u_plot=plot(handles.axes3,x_p,y_p_ft1,x_p,y_p_ft2,x_p,y_p_ft3,x_p,y_p_ft4,x_p,y_p_ft5,x_p,y_p_ft6);
        handles.axes3.XLim=[x_qujian x_qujian+10];handles.axes3.YLim=[-5 5];
        handles.axes3.XGrid='on';handles.axes3.YGrid='on';
 
        net0=load('C_cal_net01');
        net=net0.net;
 
        %赋值给表格窗口,实时显示============================================
        u_chazhi_juzhen=zeros(4,6);
        Ft_2_juzhen=zeros(4,6);
        j=1;
        for i=1:500
%             zhuangtai=s.status
            if biaoji==2
                biaoji=1;
                break
            end
            out=fscanf(s);
            if length(out)<72
             continue
            else
                data_16{j,:}=out;
                fenlie_16(j,:)=regexp(data_16{j,:},'\t','split');
                a1=fenlie_16{j,1};a2=fenlie_16{j,2};a3=fenlie_16{j,3};a4=fenlie_16{j,4};a5=fenlie_16{j,5};a6=fenlie_16{j,6};
                a1(find(isspace(a1)))=[];a2(find(isspace(a2)))=[];a3(find(isspace(a3)))=[];a4(find(isspace(a4)))=[];a5(find(isspace(a5)))=[];a6(find(isspace(a6)))=[];
                b1(j,1)=hex2dec(a1(6:9));b1(j,2)=hex2dec(a2(6:9));b1(j,3)=hex2dec(a3(6:9));b1(j,4)=hex2dec(a4(6:9));b1(j,5)=hex2dec(a5(6:9));b1(j,6)=hex2dec(a6(6:9));
                %输入电压动态曲线=========================
                hold on
                x_p=[x_p 5+0.1*(j+1)];
                y_p1=[y_p1 b1(j,1)];y_p2=[y_p2 b1(j,2)];y_p3=[y_p3 b1(j,3)];y_p4=[y_p4 b1(j,4)];y_p5=[y_p5 b1(j,5)];y_p6=[y_p6 b1(j,6)];
                set(real_u_plot(1),'XData',x_p,'YData',y_p1)
                set(real_u_plot(2),'XData',x_p,'YData',y_p2)
                set(real_u_plot(3),'XData',x_p,'YData',y_p3)
                set(real_u_plot(4),'XData',x_p,'YData',y_p4)
                set(real_u_plot(5),'XData',x_p,'YData',y_p5)
                set(real_u_plot(6),'XData',x_p,'YData',y_p6)
                drawnow
                x_qujian=x_qujian+0.1;
                handles.axes1.XLim=[x_qujian x_qujian+10];
                handles.axes1.YLim=[min(min(b1))-1000 max(max(b1))+1000];
                %电压差值动态曲线=================================
                hold on
                handles.j=j;
                u_0=b1(j_0,:);
                u_real=b1(j,:);
                u_chazhi=u_real-u_0;
                x_p_chazhi=[x_p_chazhi 5+0.1*(j+1)];
                y_p_chazhi1=[y_p_chazhi1 u_chazhi(:,1)];y_p_chazhi2=[y_p_chazhi2 u_chazhi(:,2)];y_p_chazhi3=[y_p_chazhi3 u_chazhi(:,3)];y_p_chazhi4=[y_p_chazhi4 u_chazhi(:,4)];y_p_chazhi5=[y_p_chazhi5 u_chazhi(:,5)];y_p_chazhi6=[y_p_chazhi6 u_chazhi(:,6)];
                set(chazhi_u_plot(1),'XData',x_p_chazhi,'YData',y_p_chazhi1)
                set(chazhi_u_plot(2),'XData',x_p_chazhi,'YData',y_p_chazhi2)
                set(chazhi_u_plot(3),'XData',x_p_chazhi,'YData',y_p_chazhi3)
                set(chazhi_u_plot(4),'XData',x_p_chazhi,'YData',y_p_chazhi4)
                set(chazhi_u_plot(5),'XData',x_p_chazhi,'YData',y_p_chazhi5)
                set(chazhi_u_plot(6),'XData',x_p_chazhi,'YData',y_p_chazhi6)
                handles.axes2.XLim=[x_qujian x_qujian+10];
                handles.axes2.YLim=[-100 100];
                drawnow
                %力/力矩动态曲线================================================
                u_min=-310;u_max=781;
                u_guiyi=((2*(u_chazhi-u_min))/(u_max-u_min))-1;
                FT_guiyi=sim(net,u_guiyi.').';
                f_min=-20.5740;f_max=21.7350;
                FT=(((FT_guiyi+1)*(f_max-f_min))/2)+f_min;
                hold on
                x_p2=[x_p2 5+0.1*(j+1)];
                y_p_ft1=[y_p_ft1 FT(:,1)];y_p_ft2=[y_p_ft2 FT(:,2)];y_p_ft3=[y_p_ft3 FT(:,3)];y_p_ft4=[y_p_ft4 FT(:,4)];y_p_ft5=[y_p_ft5 FT(:,5)];y_p_ft6=[y_p_ft6 FT(:,6)];
                set(ft_u_plot(1),'XData',x_p2,'YData',y_p_ft1)
                set(ft_u_plot(2),'XData',x_p2,'YData',y_p_ft2)
                set(ft_u_plot(3),'XData',x_p2,'YData',y_p_ft3)
                set(ft_u_plot(4),'XData',x_p2,'YData',y_p_ft4)
                set(ft_u_plot(5),'XData',x_p2,'YData',y_p_ft5)
                set(ft_u_plot(6),'XData',x_p2,'YData',y_p_ft6)
                handles.axes3.XLim=[x_qujian x_qujian+10];
                handles.axes3.YLim=[-100 100];
                drawnow
        %赋值给文本窗口,实时显示============================================
                Ft_2=roundn(FT,-2);
                u_chazhi_juzhen(j,:)=u_chazhi;
                Ft_2_juzhen(j,:)=Ft_2;
                if j<4
                    u_chazhi_biaoge=u_chazhi_juzhen;
                    Ft_2_biaoge=Ft_2_juzhen;
                else
                    u_chazhi_biaoge=u_chazhi_juzhen(j-3:j,:);
                    Ft_2_biaoge=Ft_2_juzhen(j-3:j,:);
                end
                set(handles.uitable1,'Data',u_chazhi_biaoge)
                set(handles.uitable2,'Data',Ft_2_biaoge)
                %==================================================================
                j=j+1;
                pause(0.1)
                guidata(hObject, handles);
%               huancun=s.BytesAvailable
                if mod(j,100)==0
                qinghuancun=fread(s,s.BytesAvailable);
%               huancun=s.BytesAvailable
                end
            end
        end
  else
    try
        biaoji=2;
        fclose(s);
        delete(s)
%         clear(s)
        set(handles.pushbutton4,'string','打开串口');
        msgbox(['关闭',handles.duankou,'成功']);
    catch err
        msgbox('关闭失败');
    end
end

 

% --- Executes on button press in pushbutton5.

function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function edit2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function edit3_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

果然,今天调试时有了两个串口,就出错了,因为是cell类型的,所以传递不了,用char强制转换为string的就行了。具体的将上述第63行改为 s=serial(char(handles.duankou));即可
各个窗口标签

刚开始学习这方面,很多不懂的,功能都是凑出来的,如果哪位大神觉得有改进的地方,欢迎指出。

  • 41
    点赞
  • 240
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
### 回答1: MATLAB是一款非常强大的软件,可以用于各种科学计算和工程设计。在MATLAB中,我们可以利用自带的串口通讯函数,实现与其他设备(如传感器、单片机等)的数据通信。 为了设计一个串口通讯工具,我们可以首先使用MATLAB串口通信函数`serial`创建一个串口对象。可以通过`serial`函数设置串口的端口号、波特率等参数。 接下来,我们可以使用`fopen`函数打开串口,并通过`fwrite`函数向串口发送数据,或通过`fread`函数从串口读取数据。通过这些函数,我们可以实现与其他设备之间的双向通信。 在设计串口通讯工具时,我们可以将以上的串口通信函数封装到一个自定义的MATLAB函数中,以便于使用和调用。这个函数可以根据具体需要,传入设备地址、命令、数据等参数,并返回读取到的数据或执行结果。 另外,在实际使用中,还可以通过MATLAB的图形用户界面(GUI)设计一个界面,用于显示发送和接收的数据,以及一些操作按钮。这样更加方便直观地进行串口通信。 总之,通过MATLAB串口通信函数,我们可以很方便地设计一个串口通讯工具,用于与其他设备进行数据交互。这样的工具在物联网、嵌入式系统等领域有着广泛的应用。 ### 回答2: MATLAB 是一种高级的科学计算和数据可视化软件,常被用于各种工程和科学领域的应用。其内置了许多功能强大的工具箱,可以进行信号处理、图像处理、控制系统设计等任务。 在MATLAB中设计串口通讯工具意味着我们可以利用MATLAB提供的函数和库来实现串口通信的功能。串口通信常被用于嵌入式系统、自动化控制系统等领域,用于与外部设备进行数据交换。 在设计串口通讯工具时,我们可以使用MATLAB提供的串口通信函数,如`serial`函数来创建串口对象。然后,可以使用该对象进行串口的打开、关闭、读写等操作。例如,可以使用`fopen`函数打开串口,并使用`fread`函数来读取串口接收到的数据。 除了基本的串口通信操作,我们还可以利用MATLAB的数据处理和可视化功能来处理和分析串口数据。例如,可以使用MATLAB绘图函数将串口接收到的数据绘制成曲线图,以便更好地观察数据的变化趋势。 在CSDN上,我们可以查找到许多关于MATLAB串口通信的教程和代码示例。这些资源可以帮助我们更好地理解和学习如何使用MATLAB设计串口通讯工具。我们可以利用这些资源来获取关于串口通信的基础知识、示例代码和常见问题的解答,从而更好地应用MATLAB进行串口通信的设计和开发。 总而言之,MATLAB提供了强大的功能和工具,可以帮助我们设计和实现串口通讯工具。通过学习和使用这些工具,我们可以更好地处理和分析串口数据,实现与外部设备的数据交换。在CSDN上,我们可以找到许多有用的资源和教程,帮助我们更好地应用MATLAB进行串口通信的设计和开发。 ### 回答3: Matlab是一种功能强大的编程软件,可以用于设计串口通讯工具。通过使用Matlab提供的串口通讯功能,可以实现与外部设备的数据交互。 首先,需要在Matlab中设置并打开串口对象。可以使用内置的串口函数来创建串口对象,并设置串口的通信参数,例如波特率、数据位数、停止位、校验位等。 创建串口对象后,可以使用Matlab提供的读写函数来实现串口设备的数据交互。通过写入数据到串口,可以向外部设备发送指令或者数据。而通过读取串口数据,可以获取来自外部设备的反馈信息。 在串口通讯过程中,需要注意数据的编码和解码。根据外部设备的通讯协议,可以使用Matlab提供的字符串处理函数来分析、提取和解析串口的收发数据。 另外,为了提高串口通讯的稳定性和效率,还可以在Matlab中设计一些错误处理机制和数据处理算法。例如,可以使用循环结构来实现数据的持续读取和发送;可以设置超时时间来处理串口通讯异常;可以对收到的数据进行预处理和后处理,实现数据的校验和转换。 最后,为了方便使用和调试,可以将整个串口通讯工具封装为函数或者脚本文件,并提供相应的接口和参数。这样,其他用户可以通过调用这个工具来实现串口通讯的功能。 总之,Matlab提供了丰富的函数和工具,可以帮助设计串口通讯工具。通过合理地利用这些功能,我们可以从Matlab中构建一个功能强大、可靠稳定的串口通讯工具。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值