c语言串口 writefile返回997_matlab读取表格数据以固定周期通过串口发送

如题,这里对数据的处理对于熟悉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行以红色画出图来。

代码执行后首先会弹出选择窗口,手动选定要操作的文件

244fabba384f46753f7b8f37bcc0193f.png

图 1

注意这里可以自由选择不同路径下的文件,要操作的文件不一定在当前工作目录下。选择窗口的打开源于uigetfile()函数的执行,选择文件结束后函数返回被选择文件的路径和文件名

097f0e5a9bcba99f88cf530e8e7b36f6.png

图 2

而后,fullfile()合成被选择文件的完整路径,并返回给file变量,最后通过csvread()函数将文件数据读取进来并形成M数据矩阵,如下原csv文件与M数据对比,原数据类型依次为double/double/float/float/float/float

7d1d2125077898cf2ae164de64ca44c7.png

图 3

这里采用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;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要通过串口助手发送文件,你需要将文件读入内存,并将其通过串口发送。以下是一个简单的示例,假设你的文件名为“example.txt”,串口的波特率为9600,数据位为8,停止位为1,无校验位: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #define COMPORT "\\\\.\\COM1" // 串口号 #define BAUDRATE CBR_9600 // 波特率 #define DATABITS 8 // 数据位 #define STOPBITS ONESTOPBIT // 停止位 #define PARITY NOPARITY // 校验位 int main() { HANDLE hCom; DCB dcb; COMMTIMEOUTS timeouts; DWORD dwBytesWritten; char buf[1024]; FILE *fp; // 打开串口 hCom = CreateFile(COMPORT, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hCom == INVALID_HANDLE_VALUE) { printf("Error: cannot open COM port\n"); return 1; } // 配置串口 memset(&dcb, 0, sizeof(dcb)); dcb.DCBlength = sizeof(dcb); if (!GetCommState(hCom, &dcb)) { printf("Error: cannot get DCB\n"); CloseHandle(hCom); return 1; } dcb.BaudRate = BAUDRATE; dcb.ByteSize = DATABITS; dcb.StopBits = STOPBITS; dcb.Parity = PARITY; if (!SetCommState(hCom, &dcb)) { printf("Error: cannot set DCB\n"); CloseHandle(hCom); return 1; } // 设置超时 timeouts.ReadIntervalTimeout = 0; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 1000; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 1000; if (!SetCommTimeouts(hCom, &timeouts)) { printf("Error: cannot set timeouts\n"); CloseHandle(hCom); return 1; } // 打开文件 fp = fopen("example.txt", "rb"); if (fp == NULL) { printf("Error: cannot open file\n"); CloseHandle(hCom); return 1; } // 发送文件 while (!feof(fp)) { int n = fread(buf, 1, sizeof(buf), fp); if (n > 0) { if (!WriteFile(hCom, buf, n, &dwBytesWritten, NULL)) { printf("Error: cannot write to COM port\n"); fclose(fp); CloseHandle(hCom); return 1; } } } // 关闭文件和串口 fclose(fp); CloseHandle(hCom); return 0; } ``` 这个程序打开串口,设置波特率、数据位、停止位和校验位,并打开要发送的文件。然后它从文件中读取数据块,将其写入串口。程序在文件末尾停止,关闭文件和串口。你可以根据需要修改程序以适应不同的串口和文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值