在MATLAB中使用串口
- 格式:doc
- 大小:38.00 KB
- 文档页数:2
在MATLAB中使用串口首先,你需要了解有关串口的一些基本概念,例如波特率和数据位。
然后你需要确保你的计算机上有一个可用的串口。
接下来,你需要打开串口连接。
使用`serial`函数创建一个串口对象,如下所示:```matlabs = serial('COM1', 'BaudRate', 9600);```此代码将创建一个串口对象`s`,并指定使用COM1串口号,波特率为9600。
使用`fopen`函数打开串口连接:```matlabfopen(s);```现在你已经打开了一个串口连接。
接下来,你可以发送和接收数据。
使用`fwrite`函数向串口发送数据,例如:```matlabdata = 'Hello';fwrite(s, data);```此代码将向串口s发送字符串"Hello"。
使用`fread`函数从串口接收数据,例如:```matlabreceived = fread(s);```此代码将从串口s接收数据,并将其存储在变量`received`中。
最后,当你完成使用串口时,使用`fclose`函数关闭串口连接:```matlabfclose(s);```这是一个最简单的串口通信的示例。
当然,你还可以进行更多的配置,例如设置校验位或停止位等。
例如,如果你需要设置串口的数据位为8、停止位为1和没有校验位,可以使用以下代码:```matlabs = serial('COM1', 'BaudRate', 9600, 'DataBits', 8,'StopBits', 1, 'Parity', 'none');```。
文章标题:探索Matlab中的串口通信系统设计在当前的现代通信系统中,串口通信系统设计已经成为一项至关重要的任务。
在Matlab中,借助各种工具和函数,我们可以设计出高效、稳定和灵活的串口通信系统。
本文将从简单到复杂、由浅入深地探讨Matlab中的串口通信系统设计,为读者提供全面的了解和深入的思考。
1. 串口通信系统概述在进行Matlab中的串口通信系统设计之前,我们首先需要了解串口通信系统的基本概念和原理。
串口通信是通过串行接口进行数据传输的一种通信方式,它在各种领域中都有着广泛的应用,包括嵌入式系统、通信设备、工业控制等。
Matlab作为强大的工程计算软件,为我们提供了丰富的工具和函数来进行串口通信系统设计,包括串口对象、串口配置、数据读写等功能。
2. Matlab中的串口通信基本操作在Matlab中,我们可以通过串口对象来进行串口通信的基本操作。
我们需要创建一个串口对象,并进行相应的配置,包括波特率、数据位、停止位、校验位等参数。
我们可以使用该串口对象来进行数据的读写操作,可以发送数据到外部设备,也可以接收来自外部设备的数据。
通过Matlab中丰富的串口函数,我们可以轻松实现串口通信系统的基本功能。
3. Matlab中的串口通信系统设计在实际的工程应用中,我们通常需要设计更加复杂和灵活的串口通信系统。
在Matlab中,我们可以借助信号处理工具箱、通信工具箱等功能来进行串口通信系统的设计。
通过信号处理工具箱,我们可以实现对串口数据的解调、调制、滤波等操作,从而提高通信系统的稳定性和性能。
而通信工具箱中的各种算法和工具则可以帮助我们实现更加复杂的通信协议和数据处理。
4. 个人观点和总结在我看来,Matlab是一款非常适合进行串口通信系统设计的软件,它不仅提供了丰富的工具和函数,还具备强大的计算能力和灵活的编程环境。
通过Matlab,我们可以实现从简单到复杂的串口通信系统设计,为各种应用场景提供定制化的解决方案。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%本程序主要实现串口控制三轴转台进行自动标定,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%查找串口对象,若串口一开始被占用,需要加上这段程序释放串口,若串口没有被占用,则不需要这段程序scoms = instrfind;%%尝试停止、关闭删除串口对象stopasync(scoms);fclose(scoms); %关闭串口delete(scoms); %释放串口%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%clear all;clc;%%%%%串口配置通道1global s;s = serial('COM13'); %设置串口号s.baudrate = 57600; %设置波特率s.parity = 'none'; %校验位s.stopbits = 1; %停止位s.databits = 7; %数据位s.timeout = 2; %一次读/写的时间最长为0.5ss.InputBufferSize = 1024; %输入缓冲区s.OutputBufferSize = 1024; %输出缓冲区% s.BytesAvailableFcnMode = 'byte'; %中断触发事件为'bytes-available event' % s.BytesAvailableFcnCount = 8; %接收缓冲区每收到n个字节时,触发回调函数% s.BytesAvailableFcn = {'cmd_rec_callback', handles};%得到回调函数句柄fopen(s); %%%%打开串口fclose(s);%%%%%串口配置通道2global s2;s2 = serial('COM15'); %设置串口号s2.baudrate = 460800; %设置波特率s2.parity = 'none'; %校验位s2.stopbits = 1; %停止位s2.databits = 8; %数据位s2.timeout = 2; %一次读/写的时间最长为0.5ss2.InputBufferSize = 1024; %输入缓冲区s2.OutputBufferSize = 1024; %输出缓冲区% s.BytesAvailableFcnMode = 'byte'; %中断触发事件为'bytes-available event' % s.BytesAvailableFcnCount = 8; %接收缓冲区每收到n个字节时,触发回调函数% s.BytesAvailableFcn = {'cmd_rec_callback', handles};%得到回调函数句柄fopen(s2); %%%%打开串口fclose(s2);% InitPos(1)=InitPos(1)+0.3% Pos1=num2str(InitPos(1)');% Pos1=['Q010',Pos1(1,:),'$'];% A=[0 0 0 0 0 0 0 0 0 0 0];% fwrite(s2,A,'uint8')% AA=fread(s2,11,'uint8')%%%%%%%定义变量,存放星点位置PosX=zeros(41,51);PosY=zeros(41,51);AllX=zeros(30,2091);AllY=zeros(30,2091);n=1;InitPos=[0.3 0.0000 93.4253];Flag=0;MouseX=1354;MouseY=376;LeftC=1;global filename4;global filename5;filename4=['D:\1-3\*.bmp' ];filename5=['D:\1-3\'];%%%%%%%三轴转台,自动标定for j=1:41fopen(s);for i=1:51%%%%%%%%%%%控制鼠标左键,采集图像PressMouse(MouseX,MouseY,LeftC);PressMouse(MouseX,MouseY,LeftC);pause(5); %等待整数秒%%%%%%%%%%%%%读取转台位置坐标,进行反馈控制fopen(s2);[Flag]=ReadCoor(s2,InitPos);fclose(s2);while (Flag==1)%%%%%%%%%%%%%删除上次存储的点的图片filename6=dir(filename4); %显示xxx目录下的文件和文件夹[~,index] = sortrows({filename6.date}.'); %index变址向量,重新排序前的地址filename6 = filename6(index);clear indexpath=[filename5]; %查看或者改变路径for k=(length(filename6)-29): length(filename6)A=[path filename6(k).name];delete(A);end%%%%%%%%%%%%%向内轴发定位命令,位置:12.3456?;ASC码:Q01012.3456$ ;16进制数:51H 30H 30H 31H 31H 32H 2EH 33H 34H 35H 36H 24HPos1=num2str(InitPos(1)');Pos1=['Q010',Pos1(1,:),'$'];fwrite(s,Pos1,'char')pause(2);%%%%%%%%%%%%%向中轴发定位命令,位置:12.3456?;ASC码:Q01112.3456$ ;16进制数:51H 30H 31H 31H 31H 32H 2EH 33H 34H 35H 36H 24HPos2=num2str(InitPos(2)');Pos2=['Q011',Pos2(1,:),'$'];fwrite(s,Pos2,'char');pause(2);%%%%%%%%%%%%%向外轴发定位命令,位置:12.3456?;ASC码:Q01212.3456$ ;16进制数:51H 30H 32H 31H 31H 32H 2EH 33H 34H 35H 36H 24HPos3=num2str(InitPos(3)');Pos3=['Q012',Pos3(1,:),'$'];fwrite(s,Pos2,'char');fclose(s);pause(2);%%%%%%%%%%%控制鼠标左键,采集图像PressMouse(MouseX,MouseY,LeftC);PressMouse(MouseX,MouseY,LeftC);pause(5); %等待整数秒% B=[0 12 34 56 0 0 0 0 0 0 0];% fwrite(s2,B,'uint8')fopen(s2);[Flag]=ReadCoor(s2,InitPos);fclose(s2);end%%%%%%%%%%中轴坐标位置一次-0.3°InitPos(2)=InitPos(2)-0.3;%%%%%%%%串口给转台发送命令,设定增量模式,中框增量-0.3°,ASC码:Q02 1 -0.3$ 16进制数:51 30 32 31 2D 30 2E 33 24fwrite(s,'Q021-0.3$','char');pause(3); %等待整数秒end%%%%%%%%%每个点找一张图存到新建文件夹filename=['D:\',num2str(j)]new_folder = filename; % new_folder 保存要创建的文件夹,是绝对路径+文件夹名称mkdir(new_folder); % mkdir()函数创建文件夹filename=dir(filename5);[~,index] = sortrows({filename.date}.'); %index变址向量,重新排序前的地址filename = filename(index);clear indexfor r=1:51k=30*(r-1)+1;path=[filename5];A0=imread([path filename(k).name]);imshow(A0);B=['D:\j\',num2str(r),'.bmp'];imwrite(A0,B,'bmp');endfwrite(s,'Q02115$','char');pause(5);%%%%%%%%%%计算星点坐标[x,y,x0,y0]=SigleStarPointCalibration(j, filename4 ,filename5);PosX(j,:)=x;PosY(j,:)=y;AllX(:,n*51-50)=x0;AllY(:,n*51-50)=y0;n=n+1;%%%%%%%%%%中轴坐标位置回到初始位置InitPos(2)=InitPos(2)+15.3;%%%%%%%%%%内轴坐标位置增量+0.3°InitPos(1)=InitPos(1)+0.3;if (InitPos(1)>360)InitPos(1)=InitPos(1)-360;end%%%%%%%%串口给转台发送命令,增量模式,内框增量-0.3°,ASC码:Q01 0 0.3$ 16进制数:51 30 32 30 30 2E 33 24fwrite(s,'Q0200.3$','char');pause(3); %等待整数秒fclose(s);end%%%%%%%关闭串口fclose(s);%查找串口对象scoms = instrfind;% 尝试停止、关闭删除串口对象stopasync(scoms);fclose(scoms); %关闭串口delete(scoms); %释放串口。
matlab串口程序function serial_communication2_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject;warning('off');javaFrame = get(hObject, 'JavaFrame');javaFrame.setFigureIcon(javax.swing.ImageIcon('icon.jpg'));%% 初始化参数hasData = false; %表征串口是否接收到数据isShow = false; %表征是否正在进行数据显示,即是否正在执行函数dataDisp isStopDisp = false; %表征是否按下了【停止显示】按钮isHexDisp = false; %表征是否勾选了【十六进制显示】isHexSend = false; %表征是否勾选了【十六进制发送】numRec = 0; %接收字符计数numSend = 0; %发送字符计数strRec = ''; %已接收的字符串%% 将上述参数作为应用数据,存入窗口对象内setappdata(hObject, 'hasData', hasData);setappdata(hObject, 'strRec', strRec);setappdata(hObject, 'numRec', numRec);setappdata(hObject, 'numSend', numSend);setappdata(hObject, 'isShow', isShow);setappdata(hObject, 'isStopDisp', isStopDisp);setappdata(hObject, 'isHexDisp', isHexDisp);setappdata(hObject, 'isHexSend', isHexSend);guidata(hObject, handles);function start_serial_Callback(hObject, eventdata, handles) % 【打开/关闭串口】按钮的回调函数% 打开串口,并初始化相关参数%% 若按下【打开串口】按钮,打开串口if get(hObject, 'value')%% 获取串口的端口名com_n = sprintf('com%d', get(/doc/515782715.html,, 'value'));%% 获取波特率rates = [300 600 1200 2400 4800 9600 19200 38400 43000 56000 57600 115200]; baud_rate = rates(get(handles.rate, 'value'));%% 获取校验位设置switch get(handles.jiaoyan, 'value')case 1jiaoyan = 'none';case 2jiaoyan = 'odd';case 3jiaoyan = 'even';end%% 获取数据位个数data_bits = 5 + get(handles.data_bits, 'value');%% 获取停止位个数stop_bits = get(handles.stop_bits, 'value');%% 创建串口对象scom = serial(com_n);%% 配置串口属性,指定其回调函数set(scom, 'BaudRate', baud_rate, 'Parity', jiaoyan, 'DataBits',...data_bits, 'StopBits', stop_bits, 'BytesAvailableFcnCount', 10,...'BytesAvailableFcnMode', 'byte', 'BytesAvailableFcn', {@bytes, handles},... 'TimerPeriod', 0.05, 'timerfcn', {@dataDisp, handles});%% 将串口对象的句柄作为用户数据,存入窗口对象set(handles.figure1, 'UserData', scom);%% 尝试打开串口tryfopen(scom); %打开串口catch % 若串口打开失败,提示“串口不可获得!”msgbox('串口不可获得!');set(hObject, 'value', 0); %弹起本按钮return;end%% 打开串口后,允许串口发送数据,清空接收显示区,点亮串口状态指示灯,%% 并更改本按钮文本为“关闭串口”set(handles.period_send, 'Enable', 'on'); %启用【自动发送】按钮set(handles.manual_send, 'Enable', 'on'); %启用【手动发送】按钮set(handles.xianshi, 'string', ''); %清空接收显示区set(handles.activex1, 'value', 1); %点亮串口状态指示灯set(hObject, 'String', '关闭串口'); %设置本按钮文本为“关闭串口”else %若关闭串口%% 停止并删除定时器t = timerfind;if ~isempty(t)stop(t);delete(t);end%% 停止并删除串口对象scoms = instrfind;stopasync(scoms);fclose(scoms);delete(scoms);%% 禁用【自动发送】和【手动发送】按钮,熄灭串口状态指示灯set(handles.period_send, 'Enable', 'off', 'value', 0); %禁用【自动发送】按钮set(handles.manual_send, 'Enable', 'off'); %禁用【手动发送】按钮set(handles.activex1, 'value', 0); %熄灭串口状态指示灯endfunction dataDisp(obj, event, handles)global value% 串口的TimerFcn回调函数% 串口数据显示%% 获取参数hasData = getappdata(handles.figure1, 'hasData'); %串口是否收到数据strRec = getappdata(handles.figure1, 'strRec'); %串口数据的字符串形式,定时显示该数据numRec = getappdata(handles.figure1, 'numRec'); %串口接收到的数据个数%% 若串口没有接收到数据,先尝试接收串口数据if ~hasDatabytes(obj, event, handles);end%% 若串口有数据,显示串口数据if hasData%% 给数据显示模块加互斥锁%% 在执行显示数据模块时,不接受串口数据,即不执行BytesAvailableFcn回调函数setappdata(handles.figure1, 'isShow', true);%% 若要显示的字符串长度超过10000,清空显示区if length(strRec) > 10000strRec = '';setappdata(handles.figure1, 'strRec', strRec);end%% 显示数据set(handles.xianshi, 'string', strRec);%%value=get(handles.xianshi,'string');value=textscan(value,'%s'); %读取其中的数据value=value{1};%得到数据,存储到value中value=hex2dec(value);% value=cellfun(@str2double,value);%把得到的字符转换成数字figure(1),plot(value)%% 更新接收计数set(handles.rec,'string', numRec);%% 更新hasData标志,表明串口数据已经显示setappdata(handles.figure1, 'hasData', false);%% 给数据显示模块解锁setappdata(handles.figure1, 'isShow', false);endfunction bytes(obj, ~, handles)% 串口的BytesAvailableFcn回调函数% 串口接收数据%% 获取参数strRec = getappdata(handles.figure1, 'strRec'); %获取串口要显示的数据numRec = getappdata(handles.figure1, 'numRec'); %获取串口已接收数据的个数isStopDisp = getappdata(handles.figure1,'isStopDisp'); %是否按下了【停止显示】按钮isHexDisp = getappdata(handles.figure1, 'isHexDisp'); %是否十六进制显示isShow = getappdata(handles.figure1, 'isShow'); %是否正在执行显示数据操作%% 若正在执行数据显示操作,暂不接收串口数据if isShowreturn;end%% 获取串口可获取的数据个数n = get(obj, 'BytesAvailable');%% 若串口有数据,接收所有数据if n%% 更新hasData参数,表明串口有数据需要显示setappdata(handles.figure1, 'hasData', true);%% 读取串口数据a = fread(obj, n, 'uchar');%% 若没有停止显示,将接收到的数据解算出来,准备显示if ~isStopDisp%% 根据进制显示的状态,解析数据为要显示的字符串if ~isHexDispc = char(a');elsestrHex = dec2hex(a')';strHex2 = [strHex; blanks(size(a, 1))];c = strHex2(:)';end%% 更新已接收的数据个数numRec = numRec + size(a, 1);%% 更新要显示的字符串strRec = [strRec c];end%% 更新参数setappdata(handles.figure1, 'numRec', numRec); %更新已接收的数据个数setappdata(handles.figure1, 'strRec', strRec); %更新要显示的字符串endfunction qingkong_Callback(hObject, eventdata, handles)%% 清空要显示的字符串setappdata(handles.figure1, 'strRec', '');%% 清空显示set(handles.xianshi, 'String', '');function stop_disp_Callback(hObject, eventdata, handles)%% 根据【停止显示】按钮的状态,更新isStopDisp参数if get(hObject, 'Value')isStopDisp = true;elseisStopDisp = false;endsetappdata(handles.figure1, 'isStopDisp', isStopDisp);function hex_disp_Callback(hObject, eventdata, handles)%% 根据【十六进制显示】复选框的状态,更新isHexDisp参数if get(hObject, 'Value')isHexDisp = true;elseisHexDisp = false;endsetappdata(handles.figure1, 'isHexDisp', isHexDisp);function manual_send_Callback(hObject, eventdata, handles) scom = get(handles.figure1, 'UserData');numSend = getappdata(handles.figure1, 'numSend');val = get(handles.sends, 'UserData');numSend = numSend + length(val);set(handles.trans, 'string', num2str(numSend));setappdata(handles.figure1, 'numSend', numSend);%% 若要发送的数据不为空,发送数据if ~isempty(val)%% 设置倒计数的初值n = 1000;while n%% 获取串口的传输状态,若串口没有正在写数据,写入数据str = get(scom, 'TransferStatus');if ~(strcmp(str, 'write') || strcmp(str, 'read&write')) fwrite(scom, val, 'uint8', 'async'); %数据写入串口 break;endn = n - 1; %倒计数endendfunction clear_send_Callback(hObject, eventdata, handles) %% 清空发送区set(handles.sends, 'string', '')%% 更新要发送的数据set(handles.sends, 'UserData', []);function checkbox2_Callback(hObject, eventdata, handles) function period_send_Callback(hObject, eventdata, handles) % 【自动发送】按钮的Callback回调函数%% 若按下【自动发送】按钮,启动定时器;否则,停止并删除定时器if get(hObject, 'value')t1 = 0.001 * str2double(get(handles.period1, 'string'));%获取定时器周期t = timer('ExecutionMode','fixedrate', 'Period', t1, 'TimerFcn',...{@manual_send_Callback, handles}); %创建定时器set(handles.period1, 'Enable', 'off'); %禁用设置定时器周期的Edit Text对象set(handles.sends, 'Enable', 'inactive'); %禁用数据发送编辑区start(t); %启动定时器elseset(handles.period1, 'Enable', 'on'); %启用设置定时器周期的Edit Text对象set(handles.sends, 'Enable', 'on'); %启用数据发送编辑区t = timerfind; %查找定时器stop(t); %停止定时器delete(t); %删除定时器endfunction period1_Callback(hObject, eventdata, handles)function period1_CreateFcn(hObject, eventdata, handles)if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))set(hObject,'BackgroundColor','white');endfunction clear_count_Callback(hObject, eventdata, handles) %% 计数清零,并更新参数numRec和numSendset([handles.rec, handles.trans], 'string', '0')setappdata(handles.figure1, 'numRec', 0);setappdata(handles.figure1, 'numSend', 0);function copy_data_Callback(hObject, eventdata, handles)%% 设置是否允许复制接收数据显示区内的数据if get(hObject,'value')set(handles.xianshi, 'enable', 'on');elseset(handles.xianshi, 'enable', 'inactive');endfunction figure1_CloseRequestFcn(hObject, eventdata, handles)% 关闭窗口时,检查定时器和串口是否已关闭% 若没有关闭,则先关闭%% 查找定时器t = timerfind;%% 若存在定时器对象,停止并关闭if ~isempty(t)stop(t); %若定时器没有停止,则停止定时器delete(t);end%% 查找串口对象scoms = instrfind;%% 尝试停止、关闭删除串口对象trystopasync(scoms);fclose(scoms);delete(scoms);end%% 关闭窗口delete(hObject);function hex_send_Callback(hObject, eventdata, handles)%% 根据【十六进制发送】复选框的状态,更新isHexSend参数if get(hObject,'value')isHexSend = true;elseisHexSend = false;setappdata(handles.figure1, 'isHexSend', isHexSend);%% 更新要发送的数据sends_Callback(handles.sends, eventdata, handles);function sends_Callback(hObject, eventdata, handles)% 数据发送编辑区的Callback回调函数% 更新要发送的数据%% 获取数据发送编辑区的字符串str = get(hObject, 'string');%% 获取参数isHexSend的值isHexSend = getappdata(handles.figure1, 'isHexSend');if ~isHexSend %若为ASCII值形式发送,直接将字符串转化为对应的数值val = double(str);else %若为十六进制发送,获取要发送的数据n = find(str == ' '); %查找空格n =[0 n length(str)+1]; %空格的索引值%% 每两个相邻空格之间的字符串为数值的十六进制形式,将其转化为数值for i = 1 : length(n)-1temp = str(n(i)+1 : n(i+1)-1); %获得每段数据的长度,为数据转换为十进制做准备 if ~rem(length(temp), 2)b{i} = reshape(temp, 2, [])'; %将每段十六进制字符串转化为单元数组elsebreak;endendval = hex2dec(b)'; %将十六进制字符串转化为十进制数,等待写入串口%% 更新要显示的数据set(hObject, 'UserData', val);% --- 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)global valueh_temp=findobj('tag','edit2');outpath=get(h_temp,'String');outpath=[outpath '\'];str_img=strcat('data','.txt');value=get(handles.xianshi,'string');value=textscan(value,'%s'); %读取其中的数据value=value{1};%得到数据,存储到value中value=hex2dec(value);% value=cellfun(@str2double,value);%把得到的字符转换成数字save([outpath str_img],'value','-ascii');。
matlab之串口通信matlab之串口通信串口通信,一般是指RS232、RS422之间的通信。
matlab中有专门的serial函数来创建串口对象。
设串口ID号为COM1,则创建方法为:复制内容到剪贴板代码:>>scom= serial('com1');创建完串口对象后,一般需要设置串口对象的属性,否则,串口不会相互通信。
复制内容到剪贴板代码:>> get(scom)ByteOrder = littleEndianBytesAvailable = 0BytesAvailableFcn =BytesAvailableFcnCount = 48BytesAvailableFcnMode = terminatorBytesToOutput = 0ErrorFcn =InputBufferSize = 512Name= Serial-COM1ObjectVisibility = onOutputBufferSize = 512OutputEmptyFcn =RecordDetail = compactRecordMode = overwriteRecordName = record.txtRecordStatus = offStatus = closedTag=Timeout = 10TimerFcn =TimerPeriod = 1TransferStatus = idleType= serialUserData = []ValuesReceived = 0ValuesSent = 0SERIAL specific properties:BaudRate= 9600BreakInterruptFcn =DataBits = 8DataTerminalReady = onFlowControl = noneParity = nonePinStatus = [1x1 struct]PinStatusFcn =Port= COM1ReadAsyncMode = continuousRequestToSend = offStopBits = 1Terminator = LF这些属性中,要使串口真正通信,一般要设置这几个属性:BaudRate:波特率;Parity:奇偶校验类型;DataBits:数据位,一般为8,不用设置;StopBits:停止位,一般为1,不用设置;TimerFcn :定时回调函数;TimerPeriod:定时周期;BytesAvailableFcn:字节计数回调函数BytesAvailableFcnCount:字节计数BytesAvailableFcnMode:一般设置为字节模式,即byte串口通信时,数据一般按帧传送,有的数据量比较大,会将帧打包后发送。
matlab串口通信基础讲义①支持基于串行接口(RS-232、RS-422、RS-485)、GPIB总线(IEEE2488、HPIB标准)、VISA总线的通信;②通信数据支持二进制和文本(ASCII)两种方式,文本方式支持SCPI(Standard Commands for Programmable Instruments)语言;③支持异步通信和同步通信;④支持基于事件驱动的通信。
从以上的Matlab设备控制工具箱的特点可以看到,Matlab完全可以满足我们实现串行通信的要求。
3.1Matlab对串行口控制的基础知识Matlab对串行口的编程控制主要分为四个步骤。
①创建串口设备对象并设置其属性。
scom=serial('com1');%创建串口1的设备对象scomscom.Terminator='CR';%设置终止符为CR(回车符),缺省为LF(换行符)scom.InputBufferSize=1024;%输入缓冲区为256B,缺省值为512Bscom.OutputBufferSize=1024;%输出缓冲区为256B,缺省值为512Bscom.Timeout=0.5;%Y设置一次读或写操作的最大完成时间为0.5s,缺省值为10ss.ReadAsyncMode='continuous'(缺省方式);%在异步通信模式方式下,读取串口数据采用连续接收数据(continuous)的缺省方式,那么下位机返回的数据会自动地存入输入缓冲区中.注意:在些属性只有在对象没有被打开时才能改变其值,如InputBufferSize、OutputBufferSize属性等。
对于一个RS-232/RS-422/RS-485串口设备对象,其属性的缺省值为波特率9600b/s,异步方式,通信数据格式为8位数据位,无奇偶校验位,1位停止位。
如果要设置的串口设置对象的属性值与缺省值的属性值相同,用户可以不用另行设置。
使用MATLAB进行串口调试的两种方法方法1:在command window界面下输入tmtool,打开Test & Measurement Tool窗口,在Hardware→Serial下面找到已连接的串口设备(单片机开发板通过USB转串口,对应COM2),在communicate选项卡中对串口进行设置即可。
需要注意的是,程序功能是上位机发送16bit字符串,单片机通过串口接收并回显给上位机,这16bit的字符串是不包含字符串结束标志\n的,因此在sending data下面的data format下拉菜单中,要选择%s而不是%s\n。
为了使接收字符串的时间变短,可以在configure选项卡中将timeout选项设置为1.0。
方法2:直接在command window环境下用matlab提供的函数对串口进行操作,仍然以COM2为例。
在command window环境下依次输入以下代码:
s=serial('COM2') %将串口2赋给s
s.status%查看串口2的状态
fopen(s)%打开串口2
s.status
fprintf(s,'987654321abcdef')%给串口2的发送缓存写入数据987654321abcdef fscanf(s)%从串口2的接收缓存读数据
fclose(s)%关闭串口2
s.status
delete(s)
clear s
每一个语句的执行情况如下图所示:
其中需要注意的是fprintf()函数默认采用%s\n格式,因此在这里只能输入15个字符,系统会在15bit字符串的末尾自动添加字符串结束标志\n,该标志不能在数码管上显示。
在嵌入式当中,串口是一种是用的比较多的通信和调试方式,串口主要还是用于通信,虽然是比较老的一种通信方式,但是现在依然保留并有着其活力,基本所有单片机等嵌入式处理器都保留有串口模块。
调试只是串口的一个被用来是用的附加功能,想对于昂贵的在线调试工具,它有着很多其他方面的优势,直观的显示程序运行的状态和相关变量。
由于其长时间的使用,相关技术和程序也比较成熟,很多工具都提供对串口通信和调试的支持,MATLAB,gdb等,串口监视和调试助手等也随处可以得到,相对于其嵌入式通信方式,它简单实用,适合初学者和速率要求不高的场合。
之前用过蓝牙虚拟串口将串口无线化,单片机间串口通信,wifi模块和ARM7串口通信,单片机于PC机串口通信,这次的综合课程设计需要在PC上对串口数据进行频谱的分析,于是就想使用MATLAB数学计算软件,应该相对简单点,果然,在提供相关数学运算函数的前提下,对各种设备的支持也很强大,在这里说一下我我在这次试验中对MATLAB对串口操作的理解。
前提还是阅读MATLAB自带的help文档,这是软件提供的最权威和全面的支持,但是很多人却忽略。
检索对自己有用的信息也是一种能力。
在MATLAB中有三种方式来操作串口,但是最终原理都是一样的。
1,simulink工具箱仿真2,Instrument control toolbox3,使用MATLAB变成语言,编写自己的程序控制在Instrument control toolbox中,就像个串口助手,可以以图像化的方式设置各种参数,进行各种操作。
在工具箱中,可以将你进行的操作实时的转换成m 文件,如果你不知道怎么编写控制串口的m文件,可以进行相关操作,然后参考生成的m文件进行编程。
simulink工具箱相对而言是比较高级的功能仿真工具,一般是在隐藏硬件细节的前提下功能仿真,如果你不熟悉原理,使用起来会一头雾水,特别是出错时,所以建议在熟悉了底层实现的前提下使用。
在MATLAB中使用串口
3.2.1 MATLAB对RS232 的串口通信设计
MATLAB是一个跨平台软件,而此处使用的是自主设计的数据采集卡,因此不具备直接访问的能力。
但MATLAB的面向对象技术,已用一个对象把计算机串口封装起来,只要用Serial函数创建串口对象即可[6]。
关键语句为:s=ser ial(‘COM1’,‘BaudRate’,9600)。
MATLAB封装的串口对象支持对串口的异步读写操作,通过对异步读写设置,PC在执行读写串口函数时能立即返回,不必等待串口把数据串输完毕。
当指定数据传输结束时就触发事件,执行事件回调函数,对事件回调函数编程,进行数据处理,这样可以大大提高数据处理的效率。
MEX是MATLAB的可执行程序,是MATLAB调用其它语言编写的程序或算法的接口,在Windows环境下是扩展名为DLL的动态链接库。
对MEX 编译器进行配置的方法是:在MATLAB命令窗口中运行mex-setup,选择VC6.0++作为编译器。
用C语言编写端口读、写的操作程序,程序包含有头文件mex.h和m exFunction函数,mexFunction函数中nelhs表示输出变量的个数,plhs包含指向输出变量指针的数组,nrhs表示输入变量的个数,prhs包含指向输入变量指针的数组。
接口编形成的MEX文件与参考文献[7][8]类似,在此不再累述。
3.2.2 数据采集与分析
(1)数据读取的MATLAB实现
主要代码为:
%读取通道数及总数据量
fid=fopen(‘cardiogram.add’,‘r’);
Status=fseek(fid,56,‘bof’);
nDataChNum=fread(fid,1,‘long’);
status=fseek(fid,204, ‘bof’);
nAllDataLength=fre ad(fid,1, ‘long’);
%按通道数循环读出各通道起始地址
status=fseek(fid,76, ‘bof’);%
for i="1:" nDataChNum
pChannelAdr(i)=fread(fid,1, ‘long’)
end
%按通道数循环读出各通道数据
for i="1:nDataChNum"
status=fseek(fid,pChannelAdr(i)+360, ‘bof’)
nSegNum=fread(fid,1, ‘log’)
status=fseek(fid,pChannelAdr(i)+160*nSegNum+1024, ‘bof’);
data=fread(fid,nAllDataLength, ‘short’);
end
sta=fclose(fid);
(2)数据处理与图形绘制
利用MATLAB的图形用户接口,通过编程可以很方便地构建数据采集与分析的用户交互界面。
将数据采集系统采集的实际心电图信号,用RS232导入到PC 中。
在MATLAB环境下,运行以上已经编好的程序,即可得到如下的模拟实验结果。
不过要说明的是,此处使用的数据采集系统是八通道同步采集,而仿真时仅使用的是其中一个通道进行的操作。
figure 3 实际心电图信号的采集与处理效果图
4、结语
使用自主开发的数据采集系统,通过合理运用串口及MTLAB强大的数值计算和分析功能,实现了基于MATLAB的实时数据处理和分析。
通过模拟实验表明,该方法对于其它类似采集卡依然实用,具有一定的应用价值和发展前景。