我有一个MATLAB代码:
function [s] = serialstart(opt)
% Function for initializing a serial interface in matlab for interfacing
% Functions using the serial port must be passed the serial port object
% s in order for the serial port to be accessible.
port = 502;
s = tcpip('192.168.2.177',port);
%?????
set(s, 'InputBufferSize', 3000000);
% Initialize serial port on specified com port
date_addr = 40001;
date_num=1;
date_addr_high = floor(date_addr/100);
date_addr_low = mod(date_addr,100);
date_num_high = floor(date_num/100);
date_num_low = mod(date_num,100);
%Open serial connection
fopen(s);
% Specify Terminator
s.terminator='CR/LF';
fwrite(s,0,'char') %Transactio identifier 0x00
fwrite(s,0,'char') % Transactio identifier 0x00
fwrite(s,0,'char') % Protokol identifier 0x00
fwrite(s,0,'char') % Protokol identifier 0x00
fwrite(s,0,'char') % Data Bytes 0x00
fwrite(s,1,'char') % Data Bytes 0x06
fwrite(s,255,'char') % unit identifier 0xff
fwrite(s,3,'uint8') % Function 0x03
fwrite(s,date_addr_high,'uint8') %Register High Byte
fwrite(s,date_addr_low,'uint8') %Register Low Byte
fwrite(s,date_num_high,'uint8') %How many Register Low Byte
fwrite(s,date_num_low,'uint8') %How many Register High Byte
out = fread(s,1,'char');
fclose(s); 但我得到了以下答复:
警告:未成功读取:指定的数据量在超时期间内未返回。
下面是TCPIP对象的设置:
TCPIP Object : TCPIP-192.168.2.177
Communication Settings
RemotePort: 502
RemoteHost: 192.168.2.177
Terminator: 'CR/LF'
NetworkRole: client
Communication State
Status: closed
RecordStatus: off
Read/Write State
TransferStatus: idle
BytesAvailable: 0
ValuesReceived: 0
ValuesSent: 12连接是成功的,但我没有收到任何数据。我不知道怎么接受约会。
编辑:
我在结尾加了这个:
while ~s.BytesAvailable
end
s.BytesAvailable
res=fread(s,s.BytesAvailable)
fclose(s);现在我没有得到任何回应。
发布于 2016-04-19 13:55:30
我知道这是一个旧的帖子,所以我不愿意撞它,但是我让Modbus TCP与Matlab一起工作,这是我尝试让它工作时遇到的帖子之一,所以我想在这里发布一个关于它的答案。
首先,我要说,这是通过Matlab的this Toolbox完成的,因为这是tcpip()命令所必需的。稍后,我将在没有工具箱的情况下努力使它工作,因为只为Modbus TCP获取整个工具箱是过分的,但为了快速开发的目的,工具箱的试用版已经足够让您通过一段时间了。
因此,首先配置端口:
IPADDR='192.168.0.1';
PORT=502;
tcpip_pipe=tcpip(IPADDR, PORT);
set(tcpip_pipe, 'InputBufferSize', 512);
tcpip_pipe.ByteOrder='bigEndian';然后,打开港口:
try
if ~strcmp(tcpip_pipe.Status,'open')
fopen(tcpip_pipe);
end
disp('TCP/IP Open');
catch err
disp('Error: Can''t open TCP/IP');
return;
end现在,我发现起作用的是准备好整个消息,然后立即写完整个消息。我认为这很有帮助,因为您在上面用te .ByteOrder指定了endianness,所以您不需要真正担心它是如何设置的,或者您是否按照正确的顺序编写消息,等等。
现在,详细介绍如何构造Modbus TCP消息:
那么,让我们来举一个例子。我希望事务代码为3(同样,我选择的任意数字,并在每次传输中递增,以使我能够匹配对特定传输的响应)。我希望函数代码是4(读寄存器),我想从寄存器0开始,我想读取12个寄存器。对于记录,一个寄存器通常是2个字节,所以这意味着我想从寄存器0开始,准备24个字节的信息。
该消息如下所示:
message = [...
%*** TRANSACTION ID ***%
uint8(0); ... %
uint8(3); ... % Two byte transaction ID
%*** PROTOCOL ***%
uint8(0); ... %
uint8(0); ... % Two byte protocol ID - all zeros means Modbus TCP
%*** BYTES REMAINING ***%
uint8(0); ... %
uint8(6); ... % Two byte number of bytes for everything after this
%*** SLAVE ID ***%
uint8(255); ... % Slave ID - use if end device is after a modbus tcp/rtu router, otherwise use 255
%*** FUNCTION ID ***%
uint8(4); ... % 4 - read input registers
%*** DATA ***%
%***** Starting Register *****%
uint8(0); ... %
uint8(0); ... % Two byte number that gives the starting register to read
%***** Number of Registers to Read *****%
uint8(0); ... %
uint8(12)]; % Two byte number that gives how many registers to read现在,将此消息写入设备:
fwrite(tcpip_pipe, message,'int8');然后,等待回复:
while ~tcpip_pipe.BytesAvailable,end然后读取返回的数据:
response = fread(tcpip_pipe,tcpip_pipe.BytesAvailable);头信息应该与预期的一样。同样,如果事务ID与您发送的不匹配,则应该丢弃该消息。函数代码应该与您发送的代码相同。如果不是,这可能是一个错误- 错误函数码与您发送的内容相同,加上128个。因此,在我的示例中,我希望读取输入寄存器(函数代码4),如果有错误(比如我的消息格式不正确,请指定无效的寄存器号,等等)。然后,我在响应中得到的函数代码将是4+128 = 132。
最后,我要补充的是,对read命令的响应中的第一个字节是寄存器的数量(而不是字节)!寄存器是响应中跟随的两个字节,对我来说这似乎是多余的,因为Modbus TCP头中已经有一个有效负载长度,但我没有制定协议。
希望这是关于Modbus TCP如何工作的一个很好的入门,所有提供的代码都是我的功能脚本中的Matlab代码,所以它应该适用于您。如果您想要更多关于您应该发送和接收的确切消息的信息,请查看Modbus上的维基百科页面。一旦你明白了这一切就很简单了。
发布于 2014-01-28 21:39:26
看起来,在收到来自s的任何数据之前,您已经执行了fread操作。在尝试读取数据之前,请检查s.BytesAvailable,以确保确实收到了某些内容。
https://stackoverflow.com/questions/21416239
复制相似问题