百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

matlab读取表格数据以固定周期通过串口发送

wptr33 2025-06-09 00:39 16 浏览

如题,这里对数据的处理对于熟悉matlab各函数操作的同学来讲,是常规操作,但对于matlab新手或只是想借用matlab工具将存于PC端文件中的数据通过串口发送出去的工程人员来说,由于对matlab软件比较陌生,实现各种功能所应该调用的函数没有头绪,所以还是比较麻烦的。这里先简单介绍实现这项操作过程中的几个步骤,然后贴出完整代码,供大家需要时查询。

这里主要以功能分以下步骤:

  1. matlab读取指定文件数据
  2. 不同类型数据转换为字节数据
  3. 固定时间间隔的实现
  4. 操作串口发送数据

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:\study\matlab\uart\3926_vehicle_global_position_0.csv');

%单独操作M矩阵的第一列1~num行数据
data_lat=M(1:num,1);
%画出读取的纬度数据,红色
plot(data_lat,'r');

不同类型数据转换为字节数据

串口常规发送8位字节数据,这里不同类型数据只有按计算机存储规则先转换为字节发送给接收端,接收端再按相同的存储规则将字节数据转换为原数据类型以完成数据的传输,这里首先存在一个数据转换的问题

%整型int
i2ubuff=zeros(1,4);
i2ubuff=typecast(int(12345),'uint8');
%单精度浮点型float
f2ubuff=zeros(1,4);
f2ubuff=typecast(single(data_lon(i)),'uint8');
%双精度浮点型double
d2ubuff=zeros(1,8);
d2ubuff=typecast(double(data_lat(i)),'uint8');

‘=’左侧即为不同数据类型返回的无符号字节数组数据,这里还有要注意的一项是发送端和接收端的数据存储模式,也即大端、小端问题

固定时间间隔的实现

数据准备好之后,有时需要一股脑的将数据全部发送出去,有时又需要以固定的周期,定时一部分一部分的发送出去。后者的定时作用,在单片机上一般由定时器timer或滴答定时器等实现精准的时间把控,在matlab中则需要调用函数来实现

  • 整秒定时

对于整秒时间间隔可以调用pause()函数,如定时3秒调用 pause(3) 即可实现

  • 压秒级定时

当要实现的时间间隔单位低于秒级时,pause()函数就无能为力了,tic toc函数可以实现

% 延时200ms
tic
while 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 num
num=693;

%中间数据
global sendbuff
global f2ubuff
global d2ubuff
global data_lat
global data_lon
global data_alt
global data_vy
global data_vx
global data_vz
sendbuff=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)='#39;;
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);
%vy
f2ubuff=typecast(single(data_vy(i)),'uint8');
sendbuff(30)=f2ubuff(1);
sendbuff(31)=f2ubuff(2);
sendbuff(32)=f2ubuff(3);
sendbuff(33)=f2ubuff(4);
%vx
f2ubuff=typecast(single(data_vx(i)),'uint8');
sendbuff(34)=f2ubuff(1);
sendbuff(35)=f2ubuff(2);
sendbuff(36)=f2ubuff(3);
sendbuff(37)=f2ubuff(4);
%vz
f2ubuff=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);
% 延时200ms
tic
while toc < 0.2
    
end

end

%延时一段时间等待数据发送完毕再关闭串口,数据未发送完毕时,不能正常关闭串口
pause(3);
%关闭串口
fclose(s);
%删除内存中串口设备对象
delete(s);
%清除工作空间中串口设备对象
clear s;

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...