三、上位机控制单片机部分
1、实现功能:
——通过Matlab工具箱中函数对单片机发送数据;
——通过Matlab工具箱中函数接收单片机数据;
2、函数介绍:
- 建立一个串口对象
重中之重:在串口通信是一定要将上位机接口的波特率与下位机设置的波特率相同!!!!
>> s=serial('COM4')
>>set(s,'BaudRate',4800);
>>set(s,'Parity','none');
>>set(s,'DataBits',8);
>>set(s,'StopBits',1);
>>set(s,'OutputBufferSize',512);
>>set(s,'InputBufferSize',1024);
>>set(s,'BytesAvailableFcnMode','byte');
>>set(s,'BytesAvailableFcnCount',1);
>>set(s,'Timeout',1);
Serial Port Object : Serial-COM4
Communication Settings
Port: COM4
BaudRate: 4800
Terminator: 'LF'
Communication State
Status: closed
RecordStatus: off
Read/Write State
TransferStatus: idle
BytesAvailable: 0
ValuesReceived: 0
ValuesSent: 0
串口对象属性
属性值 | 描述 |
---|---|
BaudRate | 波特率 |
DataBits | 数据位数目 |
Parity | 奇偶校验类型 |
StopBits | 字节终止位数 |
Terminator | 终端字符 |
与写入数据相关属性
参数名 | 功能描述 |
---|---|
BytesToOutput | 显示当前输出缓冲中的字节数 |
OutputBufferSize | 显示当前缓冲区的字节大小 |
TimeOut | 显示完成一个读写操作的时间 |
与读入数据相关属性
属性名 | 功能描述 |
---|---|
InputBufferSize | 输入缓冲的字节大小 |
BytesAvailableFcnMode | 接收缓冲区每收到数据的模式 |
BytesAvailableFcnCount | 接收缓冲区每收到n个字节时,触发回调函数 |
以上的属性参数值都可以使用set()函数来设置
- 连接到设备
>> fopen(s)
连接上设备后可以查看其是否连接成功
>> s.Status
ans =
open
若输出为‘open’,则连接成功。
- 向串口设备写数据
函数名 | 功能 |
---|---|
fprintf | 将文本文件写入设备 |
fwrite | 将二进制文件写入设备 |
>> fprintf(s,'H')%%%向下位机写入'H'
- 向串口设备读数据
函数名 | 功能 |
---|---|
fscanf | 将文本数据读入设备 |
fread | 将二进制数据读入设备 |
>> out=fscanf(s)%%%向下位机读数据
out =
ok
返回的数据在之前给下位机编写的程序中修改
注:fprintf对应fscanf,fwrite对应fread!!!!!!
- 断开串口连接并清空工作空间
>> fclose(s)
>> delete(s)
>> clear s
调用完串口必须清理串口,否则再使用接口是会报错
四、上位机串口通信及调用相机GUI界面
通过以上部分知识的理解,我们便可以将调用相机、串口通信打包做成一个界面,使其更容易进行人机交互,使用门槛低。
1、创建一个空的GUI界面:
- 第一步
- 第二步
新建一个空的GUI,并将其另存为。然后点击‘确定’ - 第三步
在生成’.fig’文件的同时会自动生成此文件的’.m’文件。
2、GUI界面布局设计: - 第一步
通过界面左边的功能栏对界面进行设计,放置各个元素模块。 - 第二步
修改每一个元素模块的属性值。
属性名 | 值 |
---|---|
Units | normalized |
FontUnits | normalized |
Resize (主界面) | on |
在检查器菜单中还有许多属性设置,可以根据要求设定,但以上三个必须设定。
3、GUI界面的初始函数设计:
global seris;
global p1;
global p2;
global p3;%%%%定义全局变量
p1=handles.pushbutton1;
p2=handles.edit1;
p3=handles.pushbutton3;%%%分配全局变量
handles.c='0';%%%%%%函数输出值的初始赋值
handles.s=serial('COM4','BaudRate',4800,'Parity','none','DataBits',8,'StopBits',1);%%%建立一个串口对象
seris=handles.s;
set(handles.s,'OutputBufferSize',512);%%%设置串口的属性值
set(handles.s,'InputBufferSize',1024);
set(handles.s,'BytesAvailableFcnMode','byte');
set(handles.s,'BytesAvailableFcnCount',1);
set(handles.s,'Timeout',1);
set(handles.popupmenu3,'string',{'50';'100';'125';'200';'250';'500';'625';'1000';'1250';'2500';'5000'});
set(handles.popupmenu3,'Value',7);
set(handles.s,'BytesAvailableFcn',{@mycallback,handles.s});%%%%定义Bytes-Available事件回调函数
set(p3,'Enable','off');
set(p4,'Enable','off');设置按钮的使能控制
info=imaqhwinfo('winvideo');%%%查询相机的参数
handles.obj=videoinput('winvideo',1,'YUY2_640x480');%%%创建一个视频输入对象
set(handles.obj,'FrameGrabInterval',5);
set(handles.obj,'ReturnedColorSpace','grayscale');%%%%设置拍摄图像为灰度图
t1=get(handles.obj,'VideoResolution');
t2=get(handles.obj,'NumberOfBands');
t=image(zeros(t1(2),t1(1),t2));%%%设置预览窗口的句柄
axes(handles.axes1);
preview(handles.obj,t)%%%打开预览窗口
fopen(handles.s);%%%打开串口
guidata(hObject, handles);
uiwait(handles.figure1);
将以上函数放入.m文件自动生成的function TX_OpeningFcn(hObject, eventdata, handles, varargin)
中。
4、GUI界面的回调函数设计:
- 主回调函数
global p1
global p2
global p3
if s.BytesAvailable>0
out1=fread(s,2);
out=char(out1);
out=out';
if strcmp(out,'OK')
set(p1,'Enable','off');
set(p3,'Enable','on');
set(p2,'string','OK!');
else
set(p2,'string','Error!');
set(p1,'Enable','on');
set(p3,'Enable','off');
end
end
将以上函数放入.m文件中的function mycallback(hObject, eventdata, s)
中。(此函数需自己编写)
- ’ 测试’ 回调函数
fprintf(handles.s,'H');
将以上函数放入.m文件中的function pushbutton1_Callback(hObject, eventdata, handles)
中。
- ’ 开始’ 回调函数
if handles.c=='0'
warndlg('请先选择频率','警告');
return;
else
grayscale111=getsnapshot(handles.obj);
imwrite(grayscale111,'text.bmp','bmp');
i=1;
t=0;
while t==0
grayscale=getsnapshot(handles.obj);%%%%%获取背景图像图片
grayscale=im2bw(grayscale,0.90);
t=sum(sum(grayscale));
if t>0
start(handles.obj);
else
fprintf(handles.s,'D'); %%%%控制电机移动一点距离然后停止
end
end
while t>0
grayscale=getsnapshot(handles.obj);
grayscale=im2bw(grayscale,0.90);
t=sum(sum(grayscale));
if t==0
stop(handles.obj);
fprintf(handles.s,'S');%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%这里写停止转动
else
switch handles.c
case '50'
fprintf(handles.s,'1');
case '100'
fprintf(handles.s,'2');
case '125'
fprintf(handles.s,'3');
case '200'
fprintf(handles.s,'4');
case '250'
fprintf(handles.s,'5');
case '500'
fprintf(handles.s,'6');
case '625'
fprintf(handles.s,'7');
case '1000'
fprintf(handles.s,'8');
case '1250'
fprintf(handles.s,'9');
case '2500'
fprintf(handles.s,'a');
case '5000'
fprintf(handles.s,'b');
end %%%%%%%%%%%%%%%%控制电机转动
f=getsnapshot(handles.obj);
D(:,:,:,i)=f;
imwrite(D(:,:,:,i),strcat(num2str(i),'.bmp'),'bmp');%%%获取光圈图像,并将其保存到四维数组中
i=i+1;
end
end
end
handles.output=i-1;%%%函数返回的值(拍摄图像的帧数)
guidata(hObject, handles);
uiresume(handles.figure1);
将以上函数放入.m文件中的function pushbutton3_Callback(hObject, eventdata, handles)
中。
- 弹出式菜单回调函数
global ttt
value = get(handles.popupmenu3, 'Value');
contents=get(handles.popupmenu3, 'String');
handles.c=contents{value};
ttt=handles.c;
guidata(hObject, handles);
将以上函数放入.m文件中的function popupmenu3_Callback(hObject, eventdata, handles)
中。
- 界面关闭函数
fclose(handles.s);
delete(handles.s);
clear handles.s
将以上函数放入.m文件中的function figure1_DeleteFcn(hObject, eventdata, handles)
中。
5、GUI界面.m文件所有代码:
function varargout = serial1(varargin)
% SERIAL MATLAB code for serial.fig
% SERIAL, by itself, creates a new SERIAL or raises the existing
% singleton*.
%
% H = SERIAL returns the handle to a new SERIAL or the handle to
% the existing singleton*.
%
% SERIAL('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in SERIAL.M with the given input arguments.
%
% SERIAL('Property','Value',...) creates a new SERIAL or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before serial_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to serial_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help serial
% Last Modified by GUIDE v2.5 10-Nov-2019 16:56:51
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @serial_OpeningFcn, ...
'gui_OutputFcn', @serial_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 serial is made visible.
function serial_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 serial (see VARARGIN)
% Choose default command line output for serial
handles.output = hObject;
global seris;
global p1;
global p2;
global p3;
global p4;
p1=handles.pushbutton1;
p2=handles.edit1;
p3=handles.pushbutton3;
% 设置串口
handles.c='0';
handles.s=serial('COM4','BaudRate',4800,'Parity','none','DataBits',8,'StopBits',1);
seris=handles.s;
set(handles.s,'OutputBufferSize',512);
set(handles.s,'InputBufferSize',1024);
set(handles.s,'BytesAvailableFcnMode','byte');
set(handles.s,'BytesAvailableFcnCount',1);
set(handles.s,'Timeout',1);
set(handles.popupmenu3,'string',{'50';'100';'125';'200';'250';'500';'625';'1000';'1250';'2500';'5000'});
set(handles.popupmenu3,'Value',7);
set(handles.s,'BytesAvailableFcn',{@mycallback,handles.s});
set(p3,'Enable','off');
set(p4,'Enable','off');
info=imaqhwinfo('winvideo');
handles.obj=videoinput('winvideo',1,'YUY2_640x480');
set(handles.obj,'FrameGrabInterval',5);
set(handles.obj,'ReturnedColorSpace','grayscale');
t1=get(handles.obj,'VideoResolution');
t2=get(handles.obj,'NumberOfBands');
axes(handles.axes1);
% axes()
t=image(zeros(t1(2),t1(1),t2));
preview(handles.obj,t)
fopen(handles.s);
% Update handles structure
guidata(hObject, handles);
uiwait(handles.figure1);
% UIWAIT makes serial wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = serial_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output1;
% delete(handles.figure1);
% --- Executes on button press in pushbutton1.
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)
fprintf(handles.s,'H');
function edit1_Callback(hObject, eventdata, handles)
% hObject handle to edit1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of edit1 as text
% str2double(get(hObject,'String')) returns contents of edit1 as a double
% --- Executes during object creation, after setting all properties.
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 mycallback(hObject, eventdata, s)
global p1
global p2
global p3
if s.BytesAvailable>0
out1=fread(s,2);
out=char(out1);
out=out';
if strcmp(out,'OK')
set(p1,'Enable','off');
set(p3,'Enable','on');
set(p2,'string','OK!');
else
set(p2,'string','Error!');
set(p1,'Enable','on');
set(p3,'Enable','off');
end
end
% guidata(hObject, s);
% --- Executes on button press in pushbutton2.
% --- Executes during object deletion, before destroying properties.
function figure1_DeleteFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
fclose(handles.s);
delete(handles.s);
clear handles.s
% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%自动控制
if handles.c=='0'
warndlg('请先选择频率','警告');
return;
else
grayscale111=getsnapshot(handles.obj);
imwrite(grayscale111,'text.bmp','bmp');
i=1;
t=0;
while t==0
grayscale=getsnapshot(handles.obj);
grayscale=im2bw(grayscale,0.90);
t=sum(sum(grayscale));
if t>0
start(handles.obj);
else
fprintf(handles.s,'D'); %%%%控制电机移动一点距离然后停止
end
end
while t>0
grayscale=getsnapshot(handles.obj);
grayscale=im2bw(grayscale,0.90);
t=sum(sum(grayscale));
if t==0
stop(handles.obj);
fprintf(handles.s,'S');%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%这里写停止转动
else
switch handles.c
case '50'
fprintf(handles.s,'1');
case '100'
fprintf(handles.s,'2');
case '125'
fprintf(handles.s,'3');
case '200'
fprintf(handles.s,'4');
case '250'
fprintf(handles.s,'5');
case '500'
fprintf(handles.s,'6');
case '625'
fprintf(handles.s,'7');
case '1000'
fprintf(handles.s,'8');
case '1250'
fprintf(handles.s,'9');
case '2500'
fprintf(handles.s,'a');
case '5000'
fprintf(handles.s,'b');
end %%%%%%%%%%%%%%%%控制电机转动
f=getsnapshot(handles.obj);
D(:,:,:,i)=f;
imwrite(D(:,:,:,i),strcat(num2str(i),'.bmp'),'bmp');
i=i+1;
end
end
end
handles.output=i-1;
guidata(hObject, handles);
uiresume(handles.figure1);
% --- Executes on selection change in popupmenu3.
function popupmenu3_Callback(hObject, eventdata, handles)
% hObject handle to popupmenu3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global ttt
value = get(handles.popupmenu3, 'Value');
contents=get(handles.popupmenu3, 'String');
handles.c=contents{value};
ttt=handles.c;
guidata(hObject, handles);
% Hints: contents = cellstr(get(hObject,'String')) returns popupmenu3 contents as cell array
% contents{get(hObject,'Value')} returns selected item from popupmenu3
% --- Executes during object creation, after setting all properties.
function popupmenu3_CreateFcn(hObject, eventdata, handles)
% hObject handle to popupmenu3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: popupmenu 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
由以上可以看出.m文件框架结构 代码都是在GUI界面设计完之后点击运行自动生成的,只需补充回调函数即可。
5、GUI界面运行: