如何过滤含垃圾二进制的非标准串口数据并提取GPS的lt/ln值?
解决方案:提取非标准GPS串口数据中的经纬度值
因为数据存在异常字符、额外换行导致逐行读取失效,核心思路是先累积串口数据到缓冲区,再用正则表达式精准匹配目标字段,忽略无关的乱码和格式问题。
MATLAB 实现步骤
1. 串口配置与数据缓冲
使用serialport对象接收数据,将所有接收到的内容累积到缓冲区,避免因额外换行导致的行不完整问题。
2. 正则匹配提取数据
用正则表达式直接定位@GPS_STAT开头的片段,并提取其中的lt(纬度)和ln(经度)值,无需关心中间的乱码或换行。
% 串口参数请根据你的GPS接收机调整 port = serialport('COM3', 9600); % 替换为实际串口号和波特率 buffer = ''; while true % 读取串口新数据并追加到缓冲区 newData = read(port, port.NumBytesAvailable, 'char'); buffer = [buffer, newData]; % 正则匹配规则:匹配@GPS_STAT开头,提取lt和ln的数值 pattern = '@GPS_STAT.*?lt=([\d\.-]+).*?ln=([\d\.-]+)'; matches = regexp(buffer, pattern, 'tokens'); if ~isempty(matches) % 遍历所有匹配结果,解析经纬度 for idx = 1:length(matches) ltVal = str2double(matches{idx}{1}); lnVal = str2double(matches{idx}{2}); % 这里替换成你的实时绘图逻辑 fprintf('纬度:%.6f,经度:%.6f\n', ltVal, lnVal); end % 截断缓冲区,移除已处理的内容,避免重复解析 lastMatchEnd = regexp(buffer, pattern, 'end'); buffer = buffer(lastMatchEnd(end)+1:end); end pause(0.1); % 降低循环频率,减少资源占用 end
Python 实现(可转译为MATLAB)
如果需要参考Python的逻辑,核心思路一致,利用正则的多行匹配特性忽略换行乱码:
import serial import re # 串口配置 ser = serial.Serial('COM3', 9600, timeout=0.1) buffer = '' while True: # 读取串口数据,忽略解码失败的乱码 new_data = ser.read(ser.in_waiting).decode('utf-8', errors='ignore') buffer += new_data # 正则匹配(re.DOTALL让.匹配换行符) pattern = r'@GPS_STAT.*?lt=([\d\.-]+).*?ln=([\d\.-]+)' matches = list(re.finditer(pattern, buffer, re.DOTALL)) for match in matches: lt = float(match.group(1)) ln = float(match.group(2)) print(f'纬度:{lt:.6f},经度:{ln:.6f}') # 截断缓冲区,保留未处理的剩余数据 if matches: buffer = buffer[matches[-1].end():]
关键注意事项
- 确保串口参数(波特率、数据位、停止位、奇偶校验)与GPS接收机完全一致,否则会出现大量乱码
- 如果解码乱码问题严重,可以尝试更换编码格式(比如
gbk),或者直接过滤掉非ASCII字符(MATLAB中可用regexprep(buffer, '[^\x20-\x7E]', '')) - 实时绘图时,建议初始化一次绘图对象,之后仅更新数据点,避免频繁创建图形窗口导致卡顿
内容的提问来源于stack exchange,提问作者Nathan Bonney
相关产品推荐
相关产品推荐

