使用MATLAB与ModBus RTU设备进行串行通信的代码及说明,分为高级封装方法 (推荐)和底层手动实现两种方案:
一、高级封装方法(推荐,需Instrument Control Toolbox)
使用MATLAB内置的modbus
对象简化通信流程,自动处理数据帧封装和CRC校验。
1. 初始化Modbus连接
matlab
% 创建Modbus RTU对象
modbusObj = modbus('serialrtu', 'COM5', ... % 串口号(根据设备修改)
'BaudRate', 9600, ... % 波特率(需与设备一致)
'Parity', 'none', ... % 校验位:none/even/odd
'Timeout', 10, ... % 超时时间(秒)
'WordOrder', 'little-endian'); % 字节序(设备相关)
% 检查连接状态
disp(modbusObj.Status); % 显示"Connected"表示成功
2. 读写操作示例
matlab
%% 读取保持寄存器(功能码03)
% 参数:起始地址、寄存器数量、从机地址
data = read(modbusObj, 'holdingregs', 11, 8, 1); % 从地址11读8个寄存器,从机地址1
disp(data); % 输出:[值1, 值2, ..., 值8]
%% 写入单个线圈(功能码05)
write(modbusObj, 'coils', 16385, 1); % 向线圈地址16385写入1(启动设备)
%% 写入多个寄存器(功能码16)
values = [100.5, 30.2]; % 待写入的数据(浮点数)
write(modbusObj, 'holdingregs', 29339, values, 'single'); % 从地址29339写入
二、底层手动实现(无工具箱)
通过串口对象手动构造Modbus帧,适合无工具箱或特殊需求场景。
1. 串口配置与CRC计算函数
matlab
function crc = calculateCRC(data)
% Modbus CRC-16算法(多项式0xFFFF)
crc = uint16(65535);
for i = 1:length(data)
crc = bitxor(crc, uint16(data(i)));
for j = 1:8
flag = bitand(crc, 1);
crc = bitshift(crc, -1);
if flag
crc = bitxor(crc, 40961); % 0xA001(多项式逆序)
end
end
end
crc = [bitand(crc, 255), bitshift(crc, -8)]; % 低字节在前
end
2. 读取保持寄存器(功能码03)
matlab
% 配置串口
s = serialport('COM1', 9600, 'StopBits', 1, 'DataBits', 8, 'Parity', 'none');
configureTerminator(s, 'CR'); % 设置终止符(可选)
% 构造请求帧
deviceAddress = uint8(1); % 从机地址
functionCode = uint8(3); % 功能码03
startAddr = uint16(11); % 起始地址
regCount = uint8(8); % 寄存器数量
requestData = [deviceAddress, functionCode, ...
typecast(startAddr, 'uint8'), regCount];
crc = calculateCRC(requestData); % CRC校验
requestFrame = [requestData, crc];
% 发送请求并接收响应
write(s, requestFrame, 'uint8');
pause(0.1); % 等待响应
response = read(s, s.NumBytesAvailable, 'uint8');
% 解析响应(数据段长度=2*regCount)
dataBytes = response(3:3+2*regCount-1);
values = typecast(dataBytes, 'uint16'); % 转为16位整数
三、常见问题解决
-
数据分包/粘包
添加延迟和字节数检查:
matlabwhile s.NumBytesAvailable < 8 % 等待完整帧 pause(0.01); end response = read(s, 8, 'uint8'); % 读取固定长度
-
字节序问题
设备若为小端序(低位在前),需调整数据解析:
matlab% 示例:将字节[0x34, 0x12] 解析为 0x1234 value = double(response(2))*256 + double(response(1));
-
MATLAB作为从站
需手动实现状态机响应主站指令(详见中的从站代码)。
四、调试技巧
-
虚拟串口测试
使用虚拟串口软件(如VSPD)和ModbusSlave模拟设备:
matlab% 虚拟串口对:COM4<->COM5 % MATLAB连接COM5,ModbusSlave连接COM4
-
帧数据打印
以十六进制显示收发帧:
matlabdisp(sprintf('TX: %02X ', requestFrame)); % 发送帧 disp(sprintf('RX: %02X ', response)); % 接收帧
总结建议
- 首选高级封装方案:效率高、代码简洁,适合大多数场景;
- 特殊需求选底层实现:如自定义CRC、非标准协议或从站开发;
- 调试关键:虚拟串口测试 + 帧数据打印,快速定位通信故障。
参考代码模板:用于与ModBus RTU模式进行串行通信的matlab代码 https://www.youwenfan.com/contentcsd/98901.html
扩展阅读:功能码06(写寄存器)示例 https://blog.csdn.net/weixin_48867130/article/details/141607763