MATLAB并行结构中serialport read函数调用报错问题排查
串口并行读取ADC数据的MATLAB问题排查与解决
需求
- 并行读取两个通过串口(COM设备)传输的ADC数据
现状
- 单设备场景下,使用
serialport和read函数可正常读取数据,设备及串口配置验证无误 - 尝试通过
backgroundPool、parfeval、fetchOutputs实现并行读取,代码如下:
s = serialport("COM5",4000000,"Timeout",15); % ADC #1 Port s2 = serialport("COM6",4000000,"Timeout",15); % ADC #2 Port RX2 = parfeval(backgroundPool,@read,1,s2,4e6,'uint8'); rawdata = read(s,4e6,"uint8"); rawdata_2 = fetchOutputs(RX2);
报错信息
- 调用
fetchOutputs时提示:Undefined function 'read' for input arguments of type 'double' - 将
4e6改为字符串"4000000"后,提示参数类型应为数值型而非字符串 - 尝试转换为
single、uint64等数值类型仍报类似错误
环境
- MATLAB 2022b及2023a版本(非授权版本,无法提交官方反馈)
问题分析与解决方案
问题根源在于**serialport对象无法被序列化传递到backgroundPool工作线程**。MATLAB的backgroundPool采用序列化机制传递参数,而serialport这类硬件句柄对象属于不可序列化类型,传递到线程后会被转化为无效的数值占位符,导致read函数无法识别正确的串口对象。
解决方法1:改用旧版serial对象
旧版serial对象支持跨线程传递,替换serialport后使用fread读取数据,示例代码:
s = serial("COM5", "BaudRate", 4000000, "Timeout", 15); fopen(s); s2 = serial("COM6", "BaudRate", 4000000, "Timeout", 15); fopen(s2); RX2 = parfeval(backgroundPool, @fread, 1, s2, 4e6, 'uint8'); rawdata = fread(s, 4e6, 'uint8'); rawdata_2 = fetchOutputs(RX2); fclose(s); fclose(s2); delete(s); delete(s2);
解决方法2:封装独立读取函数
将串口的打开、读取、关闭逻辑封装为独立函数,在工作线程内完成串口的生命周期管理,避免直接传递serialport对象,示例代码:
% 定义ADC读取函数 function data = readADC(port, baud, numBytes, dtype) s = serialport(port, baud, "Timeout", 15); data = read(s, numBytes, dtype); delete(s); end % 主程序逻辑 RX1 = parfeval(backgroundPool, @readADC, 1, "COM5", 4000000, 4e6, "uint8"); RX2 = parfeval(backgroundPool, @readADC, 1, "COM6", 4000000, 4e6, "uint8"); rawdata = fetchOutputs(RX1); rawdata_2 = fetchOutputs(RX2);
解决方法3:时间分片轮询读取
若上述方法不可行,可在主线程中交替读取两个串口的小批量数据,最终合并为完整数据集(适合实时性要求不极高的场景)。
结论
这并非MATLAB的bug,属于操作疏漏——忽略了serialport对象无法跨线程序列化传递的特性,调整实现方式即可解决问题。
内容的提问来源于stack exchange,提问作者Couponpon
相关产品推荐
相关产品推荐

