如题,这里对数据的处理对于熟悉matlab各函数操作的同学来讲,是常规操作,但对于matlab新手或只是想借用matlab工具将存于PC端文件中的数据通过串口发送出去的工程人员来说,由于对matlab软件比较陌生,实现各种功能所应该调用的函数没有头绪,所以还是比较麻烦的。这里先简单介绍实现这项操作过程中的几个步骤,然后贴出完整代码,供大家需要时查询。
这里主要以功能分以下步骤:
- matlab读取指定文件数据
- 不同类型数据转换为字节数据
- 固定时间间隔的实现
- 操作串口发送数据
matlab读取指定文件数据
这里介绍两种读取方式:选择读取和指定读取
- 选择读取
所谓选择读取即在m文件执行过程中由操作者自己选择要读取的文件,先上代码
clear all%要操作的数据行数(从首行算起)sym num ;num=693;%定义1列,num行数组变量data_lat=zeros(1,num);%选择读取文件数据[FileName PathName]=uigetfile()file=fullfile(PathName,FileName)M=csvread(file);%单独操作M矩阵的第一列1~num行数据data_lat=M(1:num,1);%画出读取的纬度数据,红色plot(data_lat,'r');
上述代码的最终实现是选择文件读取其数据到M矩阵,并将数据的第一列的1~num行以红色画出图来。
代码执行后首先会弹出选择窗口,手动选定要操作的文件
注意这里可以自由选择不同路径下的文件,要操作的文件不一定在当前工作目录下。选择窗口的打开源于uigetfile()函数的执行,选择文件结束后函数返回被选择文件的路径和文件名
而后,fullfile()合成被选择文件的完整路径,并返回给file变量,最后通过csvread()函数将文件数据读取进来并形成M数据矩阵,如下原csv文件与M数据对比,原数据类型依次为double/double/float/float/float/float
这里采用csvread()函数读取数据是因为笔者的原数据文件为.csv格式,需根据文件不同格式选择读取函数,如xlsread()函数
此外,matlab中数组和C语言的不同在于,没有0号元素,即没有0号下标的元素,都是从1号元素开始
- 指定读取
指定读取即在m文件中直接指定要读取文件的完整路径,在程序执行过程中无需再选择文件
clear all%要操作的数据行数(从首行算起)sym num ;num=693;%定义1列,num行数组变量data_lat=zeros(1,num);%选择读取文件数据% [FileName PathName]=uigetfile()% file=fullfile(PathName,FileName)% M=csvread(file);%指定读取文件数据M=csvread('D:studymatlabuart3926_vehicle_global_position_0.csv');%单独操作M矩阵的第一列1~num行数据data_lat=M(1:num,1);%画出读取的纬度数据,红色plot(data_lat,'r');
不同类型数据转换为字节数据
串口常规发送8位字节数据,这里不同类型数据只有按计算机存储规则先转换为字节发送给接收端,接收端再按相同的存储规则将字节数据转换为原数据类型以完成数据的传输,这里首先存在一个数据转换的问题
%整型inti2ubuff=zeros(1,4);i2ubuff=typecast(int(12345),'uint8');%单精度浮点型floatf2ubuff=zeros(1,4);f2ubuff=typecast(single(data_lon(i)),'uint8');%双精度浮点型doubled2ubuff=zeros(1,8);d2ubuff=typecast(double(data_lat(i)),'uint8');
‘=’左侧即为不同数据类型返回的无符号字节数组数据,这里还有要注意的一项是发送端和接收端的数据存储模式,也即大端、小端问题
固定时间间隔的实现
数据准备好之后,有时需要一股脑的将数据全部发送出去,有时又需要以固定的周期,定时一部分一部分的发送出去。后者的定时作用,在单片机上一般由定时器timer或滴答定时器等实现精准的时间把控,在matlab中则需要调用函数来实现
- 整秒定时
对于整秒时间间隔可以调用pause()函数,如定时3秒调用 pause(3) 即可实现
- 压秒级定时
当要实现的时间间隔单位低于秒级时,pause()函数就无能为力了,tic toc函数可以实现
% 延时200msticwhile toc < 0.2 end
tic执行时,会获取实时系统时间t0,toc则一直获取当前系统时间t1与t0的时间差,如上,当时间间隔大于或等于0.2时,程序会跳出while循环向下执行,否则会在while中等待,注意这种延时存在一定的精度误差
操作串口发送数据
由于只执行简单的串口操作,和单片机控制串口的操作很相似
- 指定端口,创建端口设备
s=serial('COM18');
- 设置串口属性
set(s,'BaudRate',115200,'parity','none','databits',8,'stopbits',1);
属性名字,紧跟要设置成的属性
- 打开串口
fopen(s);
- 发送数据
fwrite(s,sendbuff);
关闭串口,删除内存中串口设备对象,清除工作空间中串口设备对象
fclose(s);delete(s);clear s;
有时打开串口后,程序由于某种原因未能执行完毕,中途退出后,再次运行程序会显示打开串口错误,要打开的串口被占用,这是因为上次运行出错的程序未能正确关闭串口。此时有两种选择,一是关闭matlab软件,解除占用,但是打开matlab并等待就绪会占用很长一段时间,挺让人不耐烦的。二是在命令窗口运行下列函数,解除占用
%强行关闭串口scoms=instrfindall;stopasync(scoms);fclose(scoms);delete(scoms);
完整代码
最后贴出笔者的完整代码,该代码的实现是读取.csv数据以5hz的频率将数据按固定格式发送出去
%串口发送程序%测试数据在excel表中列顺序:经度、纬度、高度、y轴(东)速度、x轴(北)速度、z轴(下)速度clear all%操作的每列数据行数,从第一行算起sym numnum=693;%中间数据global sendbuffglobal f2ubuffglobal d2ubuffglobal data_latglobal data_longlobal data_altglobal data_vyglobal data_vxglobal data_vzsendbuff=zeros(1,48);f2ubuff=zeros(1,4);d2ubuff=zeros(1,8);data_lat=zeros(1,num);data_lon=zeros(1,num);data_alt=zeros(1,num);data_vy=zeros(1,num);data_vx=zeros(1,num);data_vz=zeros(1,num);%获取日志数据[FileName PathName]=uigetfile();file=fullfile(PathName,FileName);M=csvread(file);data_lat=M(1:num,1);data_lon=M(1:num,2);data_alt=M(1:num,3);data_vy=M(1:num,4);data_vx=M(1:num,5);data_vz=M(1:num,6);%选定串口,创建串口设备对象s=serial('COM18');fclose(s);%设置串口属性set(s,'BaudRate',115200,'parity','none','databits',8,'stopbits',1); %打开串口fopen(s);%固定字节sendbuff(1)='$';sendbuff(2)='E';sendbuff(3)='X';sendbuff(4)='Y';sendbuff(5)='F';sendbuff(6)=48;sendbuff(7)=0;sendbuff(8)=20;sendbuff(9)=20;sendbuff(42)=1;sendbuff(43)=0;sendbuff(44)=0;sendbuff(45)=160;sendbuff(46)=64;sendbuff(47)=0;sendbuff(48)=63;for i=1:num%纬度d2ubuff=typecast(double(data_lat(i)),'uint8');sendbuff(10)=d2ubuff(1);sendbuff(11)=d2ubuff(2);sendbuff(12)=d2ubuff(3);sendbuff(13)=d2ubuff(4);sendbuff(14)=d2ubuff(5);sendbuff(15)=d2ubuff(6);sendbuff(16)=d2ubuff(7);sendbuff(17)=d2ubuff(8);%经度d2ubuff=typecast(double(data_lon(i)),'uint8');sendbuff(18)=d2ubuff(1);sendbuff(19)=d2ubuff(2);sendbuff(20)=d2ubuff(3);sendbuff(21)=d2ubuff(4);sendbuff(22)=d2ubuff(5);sendbuff(23)=d2ubuff(6);sendbuff(24)=d2ubuff(7);sendbuff(25)=d2ubuff(8);%高度f2ubuff=typecast(single(data_lon(i)),'uint8');sendbuff(26)=f2ubuff(1);sendbuff(27)=f2ubuff(2);sendbuff(28)=f2ubuff(3);sendbuff(29)=f2ubuff(4);%vyf2ubuff=typecast(single(data_vy(i)),'uint8');sendbuff(30)=f2ubuff(1);sendbuff(31)=f2ubuff(2);sendbuff(32)=f2ubuff(3);sendbuff(33)=f2ubuff(4);%vxf2ubuff=typecast(single(data_vx(i)),'uint8');sendbuff(34)=f2ubuff(1);sendbuff(35)=f2ubuff(2);sendbuff(36)=f2ubuff(3);sendbuff(37)=f2ubuff(4);%vzf2ubuff=typecast(single(data_vz(i)),'uint8');sendbuff(38)=f2ubuff(1);sendbuff(39)=f2ubuff(2);sendbuff(40)=f2ubuff(3);sendbuff(41)=f2ubuff(4);fwrite(s,sendbuff);% 延时200msticwhile toc < 0.2 endend%延时一段时间等待数据发送完毕再关闭串口,数据未发送完毕时,不能正常关闭串口pause(3);%关闭串口fclose(s);%删除内存中串口设备对象delete(s);%清除工作空间中串口设备对象clear s;