由于最近需要使用一个利用UDP网口进行传输数据的浪高仪,且它需要基于Matlab平台与程序进行数据融合,这里同时接触到一些新的数据编译工作。在这里简单记录一下开发该程序的全过程。
目录
一、UDP协议介绍
二、通讯代码
三、数据编译代码
四、采用网络调试助手辅助验证算法
五、源代码
UDP类似于我上文提到的串口RS485的Modbus协议,不像TCP是两者固定的连接,而是使用广播的方式进行通信。
fclose(instrfindall); %先关闭之前可能存在的UDP
ipA = '192.168.0.2'; %这个根据说明书所设定的本地IP地址
portA = 10000; %这个是所设定的本地主机端口
ipB = '192.168.0.21'; %这个是仪器的远程ip地址(前面三段数字相同,网络即处于同一网段)
portB = 10000; %这个是所设定的远程主机端口
handles.udpA = udp(ipB,'RemotePort',portB,'LocalPort',portA); %新建一个udp对象
udpA.OutputBufferSize=8192; %根据传输的数据长度来定
udpA.TimeOut=10; %超时时间为10ms
udpA.BytesAvailableFcnCount = 'byte';
udpA.BytesAvailableFcnCount = 1024; %触发中断的数据数量
fopen(udpA); %设备之间网络连接
for i=1:1:10
fwrite(udpA,(hex2dec(['DA'; '05'; '01'; '02'; '00'; 'E2']))); %发送指令
pause(1); %一定的延时(需要把控精确的计算时间的可以采用下面注释的代码)
if(c.BytesAvailable) %若满足传输的字节为9个字节
data1= fread(udpA,9); %读取9个字节
end
end
fclose(udpA);
delete(udpA);
注意:
1.电脑主机IP的更改在网络设置里面更改Internet协议版本4(TCP/IPv4) 属性。
2.这里端口需要统一, 才可以连接
3.写数据和读取数据的方式跟串口通讯是一模一样的。
根据说明书中的指令,经过NetAssist V5.0.3的试验,其发送指令和相应的响应指令如下:
T:DA 05 01 02 00 E2
R:DC 00 FF 00 81 17 BA 8C 43
由于浪高仪发送回来的是浮点数,且遵循低位在前,高位在后的原则,这里需要这样进行编译。
4个字节的16进制字符可以转换为32bit浮点数。
b = 'BA8C8117';
c = typecast(uint32(hex2dec(b)),'single');
提前先采用网络调试助手来与matlab进行连接,是因为这样可以看到发送和接受的信息,若直接和设备相连无法看到发送过去的是什么内容。同样的,这里由于测试是在一个机器上进行通讯,因此改为只有一个本地的ip地址(即127.0.0.1)。另外这里通讯的时候,两个端口是相反的(且由于在同一个地址内,端口不能相同),这个应该好理解。代码如下:
clc
clear
delete(instrfindall); %先关闭之前可能存在的UDP
udpA = udp('127.0.0.1','RemotePort',8080,'LocalPort',8086); %这里'127.0.0.1'指的是本地
udpA.OutputBufferSize=8192; %根据传输的数据长度来定
udpA.TimeOut=10; %超时时间为10ms
udpA.BytesAvailableFcnMode = 'byte';
udpA.BytesAvailableFcnCount = 9; %触发中断的数据数量
fopen(udpA); %设备之间网络连接
for i=1:1:10
fwrite(udpA,(hex2dec(['DA'; '05'; '01'; '02'; '00'; 'E2']))); %发送指令
pause(1); %一定的延时(需要把控精确的计算时间的可以采用下面注释的代码)
%% tic
%% for t = 0.001:0.001:0.2
%% while toc < t
%% end
%% end
if(udpA.BytesAvailable) %若满足传输的字节为9个字节
data1= fread(udpA,9); %读取9个字节
end
end
fclose(udpA);
delete(udpA);
这代表在正式的仪器连接中,仪器是能够接受到正确的指令。(如果这里只发送前面指令,而不发送附加位,这里可以勾选checksum8)
可以看到,matlab也成功接受了由网络调试助手发送的DC 00 FF 00 81 17 BA 8C 43指令,并将其解析为实际的数据。即由于matlab中是不显示16进制的,只会以10进制显示所收到的数据。因此这里需要将返回来的数据先变为第三节代码所需要的数据形式,即一个一维的字符串。方法有点笨拙,有改进的请在评论区发给我吧。
H=dec2hex(data1(5:8)); %将十进制的double型数据变为十六进制的二维字符串
H1=H(1,:);
H2=H(2,:);
H3=H(3,:);
H4=H(4,:);
data2=[H3,H4,H1,H2]; %拼接成一维的字符串,且低位在前,高位在后
clc
clear
delete(instrfindall); %先关闭之前可能存在的UDP
udpA = udp('127.0.0.1','RemotePort',8080,'LocalPort',8086); %这里'127.0.0.1'指的是本地
udpA.OutputBufferSize=8192; %根据传输的数据长度来定
udpA.TimeOut=10; %超时时间为10ms
udpA.BytesAvailableFcnMode = 'byte';
udpA.BytesAvailableFcnCount = 9; %触发中断的数据数量
fopen(udpA); %设备之间网络连接
pause(5)
for i=1:1:10
fwrite(udpA,(hex2dec(['DA'; '05'; '01'; '02'; '00'; 'E2']))); %发送指令
pause(1); %一定的延时(需要把控精确的计算时间的可以采用下面注释的代码)
if(udpA.BytesAvailable) %若满足传输的字节为9个字节
data1= fread(udpA,9); %读取9个字节
end
H=dec2hex(data1(5:8)); %将十进制的double型数据变为十六进制的二维字符串
H1=H(1,:);
H2=H(2,:);
H3=H(3,:);
H4=H(4,:);
data2=[H3,H4,H1,H2]; %拼接成一维的字符串
data3 = typecast(uint32(hex2dec(data2)),'single');
end
fclose(udpA);
delete(udpA);