TESEO-LIV3F低功耗GNSS模块UART配置全流程详解
2026/8/29 18:13:54 网站建设 项目流程

做低功耗定位项目时,我在一堆GNSS模块里挑了意法半导体这颗 TESEO-LIV3F,理由很简单:连续跟踪模式下功耗做到几毫安级别,比同级别很多模块省电一半以上,而且支持GPS/Galileo/Glonass/QZSS多星座。但模块到手后,真正磨人的不是定位,而是配置。这颗模块出厂默认参数通常是1Hz更新率、默认波特率、全量NMEA输出,直接上电能用,但放到实际产品里几乎都要改——更新率、NMEA语句裁剪、星座开关、串口波特率,每一项都得通过UART发命令重新设置。

这篇文章会把我在UART配置这条路上踩过的坑和最终跑通的流程完整记录下来,覆盖硬件连接、命令格式、参数保存、故障排查,以及在主控MCU里自动配置的思路。适合正在用或准备用TESEO-LIV3F做嵌入式定位项目的朋友,尤其是第一次接触ST这套$PSTM命令体系的开发者。配置本身不复杂,难的是那些不会写进数据手册的细节。

1. 为什么TESEO-LIV3F的配置绕不开UART

1.1 出厂默认参数够用,但离"好用"差得远

TESEO-LIV3F上电后默认会以一组固定参数运行,大概包含这些逻辑:定位更新率1Hz,串口输出多种NMEA语句,所有支持的星座全部开启。这种配置最适合做一件事——验证模块能不能定位。放在产品里就尴尬了。

举几个实际场景:

  • 产品靠电池供电,要求定位模块整机平均电流尽量低。1Hz更新率意味着每秒定位一次,对低功耗设备来说完全没必要,改成0.2Hz或0.1Hz能省不少电。
  • 主控MCU资源紧张,NMEA全开时每秒能吐出好几条语句,其中很多字段根本用不上。只保留$GNRMC$GNGGA,MCU解析负担会小很多。
  • 项目只在国内使用,不需要GLONASS或Galileo参与定位,关掉这些星座既能省电,还能减少搜索时间。

这些全部要靠UART配置命令去改。另一个容易被忽略的点是固件版本差异,不同批次的模块固件版本可能不同,对命令的支持细节也不太一样。拿到模块后先去查一下固件版本,后面配置会少很多莫名其妙的问题。

1.2 UART和I2C,配置阶段选哪个更合适

TESEO-LIV3F对外可用的串行接口主要有UART和I2C两种。虽然I2C也能读写模块内部寄存器,但在配置这个场景下,我强烈建议用UART。

对比维度UARTI2C
调试直观性高,PC串口工具直接看NMEA和命令回显低,要分析I2C时序
接线复杂度TX、RX两根线,加上GNDSDA、SCL两根线,同样要共地
配置命令支持支持完整的$PSTM命令体系也支持,但排查问题不如UART直观
运行时数据读取NMEA直接可读,人眼能懂需要MCU解析寄存器数据
工具链串口终端、逻辑分析仪,生态成熟需要I2C调试工具,门槛稍高

我的建议是:开发调试阶段务必用UART,把所有命令流程跑通,再决定量产方案。I2C适合运行时读取定位数据,但拿它来一条条敲配置命令,出了问题排查起来非常痛苦。

1.3 了解模块内部存储结构,配置逻辑才清晰

TESEO-LIV3F内部的配置区域大致可以理解为三块:ROM、RAM、Flash。ROM存放出厂固件和默认参数,上电时模块会把Flash里保存的配置加载到RAM,配置命令直接修改的是RAM里的当前值,而$PSTMSAVEPAR命令则把RAM里的当前参数写入Flash,作为下次上电的默认加载项。

理解了这层关系,就能解释很多现象:

  • 改了参数但没保存,断电重启后又恢复原样。
  • 保存命令之后马上断电,Flash写入不完整,下次上电配置异常。
  • 频繁调用保存命令,虽然Flash有擦写寿命指标,但开发阶段没有必要每次都保存。

所以我的习惯是:开发时只改RAM参数,确认全部正确后再统一保存一次,减少Flash不必要的损耗。

2. 硬件连接与USB转串口选型,第一步不要踩电平的坑

2.1 1.8V逻辑电平,新手最容易在这翻车

TESEO-LIV3F的VIO引脚是1.8V逻辑,所有串口引脚的电平标准都基于1.8V。这一点在数据手册里写得很清楚,但很多人看串口就慌了,随手从抽屉里拿出一块3.3V的USB转TTL板子直接怼上去。

结果通常是两种:运气好,模块还能工作,但通信偶尔不稳定,高电平判定时不时出错;运气不好,模块I/O被3.3V高电平持续冲击,直接烧坏。

原因很简单,3.3V的高电平已经超过模块I/O的绝对最大额定值。要安全跑UART配置,必须确保USB转串口板输出的TXD电平是1.8V,而不是3.3V或5V。

2.2 FT232R/FT231X的正确接法与驱动要点

很多人手里的USB转串口板用的是FT232R或FT231X芯片,这两颗芯片都支持通过VIO引脚调节IO输出电压,这是解决电平匹配的一个低成本方案。

FT232R的VIO引脚如果接到1.8V,它的TXD/RXD就会以1.8V逻辑电平输出,和TESEO-LIV3F正好匹配。接线就这么几根:

  • 模块TXD → 转串板RXD
  • 模块RXD → 转串板TXD
  • 模块GND → 转串板GND

TXD和RXD一定要交叉接,这是新手最常见的错误。很多人按同名端直连,结果串口什么都收不到,还以为模块坏了。FT231X是FT232R的升级款,VIO支持范围类似,接线逻辑相同。

驱动方面,Windows下需要安装VCP驱动。正常安装后设备管理器里会出现一个COM口,但有些精简版系统或新版本Windows会把驱动装错,设备管理器显示黄色感叹号。解决办法是去芯片厂商官网下载对应驱动,卸载旧驱动后重装。macOS和Linux下系统自带FTDI驱动,一般插上就能识别。

建议买板子时选那种VIO有跳线帽或者引脚引出的版本,方便直接接1.8V。有些板子VIO固定在3.3V,拿它调试1.8V模块就得额外加电平转换芯片,性价比不高。

2.3 供电和天线,对配置过程也有隐性影响

TESEO-LIV3F供电电压典型值1.8V,电流在几毫安到几十毫安之间浮动。配置命令发送过程本身不会引起明显电流冲击,但如果电源纹波太大,或者LDO选型不当,模块内部状态机可能出错,具体表现就是配置命令时灵时不灵,一会儿回ACK,一会儿完全没反应。

天线问题更容易被忽视。无源陶瓷天线开路或短路会导致射频前端工作异常,严重时模块启动初始化失败,连串口都看不见任何输出。我调试时习惯先接好天线再上电,哪怕暂时不关注定位结果,也要让射频链路处于正常状态。

注意:给模块供电的电源和给电平转换电路供电的电源最好共地,否则串口信号参考电位不一致,通信会出现随机丢字节。

3. 配置命令体系:$PSTM专有命令的结构与语义

3.1 为什么ST要用NMEA风格的命令格式

TESEO系列在标准NMEA协议之上扩展了一套以$PSTM开头的专有命令。之所以采用NMEA风格,而不是自定义一套二进制协议,主要有几个考虑:标准NMEA和专有命令共用同一条UART链路,现有串口工具链完全兼容;命令内容人眼可读,日志排查比十六进制流直观太多;标准NMEA接收程序遇到未知的$PSTM句子会自动跳过,兼容性也好。

一条完整的配置命令长这样:

$PSTM<命令名>,<参数1>,<参数2>...*<校验和>\r\n

命令以$PSTM开头,后面跟具体命令名和逗号分隔的参数,*后面是两位十六进制校验和,行尾必须带\r\n

3.2 校验和的计算,手写脚本时最容易错

NMEA校验和算法是固定标准:从$后面第一个字符开始,到*之前为止的所有字符,按字节依次异或,结果转成两位十六进制大写。

用Python写就几行:

def nmea_checksum(cmd): cksum = 0 for ch in cmd.encode('ascii'): cksum ^= ch return f"{cksum:02X}" # 示例:对 "PSTMSETPAR,1,2" 计算校验和 cmd = "PSTMSETPAR,1,2" print(nmea_checksum(cmd))

注意:计算时不要把$*以及*后面的校验和本身算进去。手写脚本时最容易犯的错就是把$也算进去,或者忘了把参数转成ASCII字节直接对字符串做异或,这两种情况算出来的校验和都是错的。

3.3 配置命令的四类操作

ST这套命令体系大致分成四类:

操作类型命令示例作用范围典型用途
查询$PSTMGETPAR只读读取当前配置值
设置$PSTMSETPAR修改RAM修改参数并立即生效
保存$PSTMSAVEPAR写入Flash把当前RAM配置固化
恢复默认$PSTMRESTORE重置参数恢复出厂默认配置

查询命令在配置前一定要先跑一次,它能把模块当前参数读回来,避免盲目修改。恢复默认命令适合把配置搞乱之后自救,比一条条改回去高效得多。

3.4 解析错误里的"no"到底在说什么

调试配置命令时,串口日志里可能会看到类似[eparseerror]的错误提示。我最早看到[eparseerror] no的时候也懵了一下,以为是模块在说"No"表示拒绝命令。后来对比正确命令和错误命令的差异才发现,这里的no不是英文单词NO,而是错误响应里对导致解析失败的那个字段的占位标记。

换句话说,模块在解析命令时发现某个位置的字段非法,无法对应到已知的参数定义,就会返回解析错误,并把出问题的位置标记出来。所以看到[eparseerror]时的第一反应不应该是"命令被拒绝了",而应该是"我去对照一下命令格式,看哪个字段写法有误"。这个方向对了,排查速度会快很多。

3.5 常用配置项和映射关系

更新率、NMEA句子开关、波特率、星座开关,这些都能通过SETPAR命令修改。但是具体参数ID每个固件版本有差异,这里不列出不能保证准确的ID值。要查对应固件版本支持的参数映射,ST官方参考手册的Configuration章节里面有详细列表。

我每次拿到新固件版本的模块,第一件事就是把手册里的参数映射表下载下来,按版本归档。同一个参数ID在不同固件里含义不同这种事,我是真遇到过。

4. 实测:从0配置一台TESEO-LIV3F的完整过程

4.1 准备工具和确认链路

配置前需要准备:

  • TESEO-LIV3F模块或评估板
  • USB转串口板,VIO调到1.8V
  • 串口终端工具(Tera Term、PuTTY、minicom都行)
  • 或者Python环境,用pyserial发命令

上电后如果模块天线状态正常,串口会周期性输出NMEA语句。看到$GNRMC$GNGGA这类句子,说明链路已经通了。如果输出是乱码,大概率波特率不对。如果完全没有任何输出,先检查接线、供电、天线,再怀疑模块。

TESEO-LIV3F多数固件默认波特率是38400bps,但这并不是绝对的。我手上的模块是这个值,不代表你手里那批也是。拿到不确定的模块时,写个脚本轮流尝试9600、19200、38400、115200几个常见波特率,看哪个能收到正常NMEA,这就是当前模块的默认波特率。

4.2 发送查询命令,确认命令通道可靠

确认NMEA链路正常后,别急着改参数,先发一条查询命令,确认模块能正确处理专有命令。

在串口终端里发送:

$PSTMGETPAR,<param_id>*<checksum>

这里的<param_id>替换成要查询的参数ID,<checksum>用前面给的Python函数算出来。如果模块回复对应的参数值,说明命令通道可靠。

这一步看起来多余,但它能把"串口链路正常"和"配置命令通道正常"这两件事区分开。如果查询命令都没反应,后面改参数必然也是白搭。

4.3 修改更新率和配置波特率

假设要把更新率从默认的1Hz改成2Hz。

先算一下串口带宽是否够:每条NMEA语句大约80到120字节,2Hz更新率意味着每秒输出2套完整NMEA句子集,大约1600到2400 Bps。38400bps的串口实际有效数据吞吐约3800字节/秒,完全够用。如果打算把更新率推到10Hz,建议波特率至少设到115200,否则串口会成为瓶颈,NMEA语句会被截断。

发送设置命令:

$PSTMSETPAR,<rate_param_id>,2*<checksum>

等模块回复确认后,观察输出频率,如果每秒出现两套完整NMEA句子,说明更新率已生效。如果没生效,检查参数ID是否对应更新率这一项,以及波特率是否和当前串口工具设置一致。

如果要改模块串口波特率,比如从38400改成115200,发送对应设置命令后,模块会立刻以新波特率运行。这时候串口工具那边也要同步改成115200,才能继续看到NMEA输出。这就是为什么改波特率要放在其他配置之后,否则丢了通信通道,后续命令都发不进去。

4.4 裁剪NMEA句子,降低MCU负担

如果项目只需要经纬度、速度、时间,保留$GNRMC$GNGGA通常足够了,其余句子全关掉。这不仅能减少串口带宽占用,还能降低主控MCU的解析工作量。

通过SETPAR命令关闭不需要的NMEA语句类型,确认当前输出里只剩需要的句子。这个过程比改更新率还要小心,关错了句子,关键数据就丢了。建议一次只关一类句子,观察一下输出,再决定下一步。

4.5 保存到Flash并复位验证

所有参数都调好之后,发送保存命令:

$PSTMSAVEPAR*<checksum>

等模块返回确认,再等1到2秒,让Flash写入彻底完成,然后断电重启。

重启后先看NMEA输出是否还是刚才配置的更新率和裁剪后的句子集合。如果配置还在,说明Flash保存成功。如果回到出厂默认,说明保存命令没执行成功,或者发送的保存命令本身格式有问题。另一种可能是保存后立刻断电,Flash还没写完,这种情况我遇到过,所以保存后一定要等足时间再断电。

5. 配置没生效?这些坑我全踩过

5.1 能收到NMEA,但命令发出去毫无反应

这是最让人抓狂的情况。串口明明能看到正常NMEA输出,说明链路是通的,但发出去的配置命令就像石沉大海。

排查顺序是这样的:

  1. 确认串口工具的行尾设置。NMEA命令必须以\r\n结尾,只发\n或者只发\r都有可能被模块忽略。
  2. 确认本地回显没被打开。有些串口终端默认把本地输入回显到屏幕,看起来像发了命令,实际上模块收到的是混入回显字节的无效内容。
  3. 确认命令前缀没有打错。$PSTM是前缀,不是$PMTK也不是$PSTN,大小写也不能错。
  4. 用逻辑分析仪抓一下UART TX,确认模块确实收到了完整字节流。

5.2 看到eparseerror,第一反应应该是查格式

[eparseerror]这个错误我在配置过程中见过很多次,最常见的触发原因是命令格式和固件期望的格式对不上。几个高频错误来源:

  • 参数之间不小心多了空格,$PSTMSETPAR, 1, 2这种写法就是错的,逗号后面不能有空格。
  • 参数ID超出当前固件支持范围,要对照手册确认。
  • 参数值用了错误的进制,比如十六进制数没带对应前缀,或者十进制数写成了ASCII字符。
  • 命令名拼写有误,或者大小写不一致。

排查时把命令精简到最小,一条条加字段,逐步逼近出错的字段。这个方法虽然笨,但在面对格式问题时非常有效。

5.3 校验和明明算了,模块还是返回错误

算校验和时最容易犯的错是把$字符也参与异或。NMEA标准明确规定校验和从$后面的第一个字符算起,到*前为止。另外校验和必须是大写十六进制,小写字母在某些固件里会解析失败。

我后来写配置脚本时,把校验和计算、命令拼接、行尾追加全部封装成一个函数,避免每次手算出错。

import serial def build_pstm_command(command_body: str) -> bytes: cksum = 0 for ch in command_body.encode('ascii'): cksum ^= ch cmd = f"${command_body}*{cksum:02X}\r\n" return cmd.encode('ascii') ser = serial.Serial('COM10', 38400, timeout=1) cmd = build_pstm_command("PSTMGETPAR,<param_id>") ser.write(cmd) resp = ser.readline() print(resp)

5.4 保存后断电重启,配置又回到出厂状态

如果保存命令返回了确认,但断电重启后配置仍然丢失,问题可能出在保存时序上。

模块执行Flash写入需要时间,保存命令返回确认后立刻断电,Flash写入可能还没完成。正确做法是等1到2秒再断电。另外,如果保存命令本身格式不对,模块不会写入Flash,它可能返回一个错误响应,需要仔细看串口回显。

还有一类情况是模块固件本身有保护逻辑,某些关键参数不允许写入Flash。如果反复确认参数ID没问题、保存时序也没问题,那就要考虑是不是固件对这个参数的写入有限制,这时候需要查阅对应固件版本的文档。

5.5 电平问题和电源噪声导致的"时好时坏"

这种故障最隐蔽,因为它不是必现的。模块大部分时间工作正常,偶尔配置命令无响应,或者模块莫名其妙自动复位。我用3.3V电平直接接模块时就遇到过这种问题,通信看起来正常,但高电平持续一段时间后模块就复位。后来加了1.8V电平转换,问题彻底消失。

电源噪声的表现类似。如果电源纹波过大,模块内部逻辑电平判定会不稳定,命令响应时好时坏。排查这种问题,示波器看电源纹波和串口波形是最高效的手段。

6. 进阶:在主控MCU里实现自动配置

6.1 为什么不完全依赖Flash固化

如果产品批量很大,配置一次固化到Flash,之后主控只管解析NMEA,这个方案最省心。但开发阶段经常要改参数,或者同一批模块固件版本有差异,每次都手动配置效率太低,所以让主控上电后自动配置更可靠。

还有一个场景:产品需要在运行时动态切换工作模式,比如正常模式下用1Hz更新率,进入低功耗模式后用0.2Hz。这种需求不可能靠Flash固化解决,必须在主控运行时发配置命令。

6.2 一套简单可靠的配置流程

我的做法是模块上电后,主控延时500到1000毫秒,等模块完成内部初始化,再依次发送配置命令。每条命令之间延时至少50毫秒,避免模块来不及处理上一条就收到下一条。

伪代码大致这样:

void GNSS_Config(void) { uint8_t cmds[][64] = { "$PSTMSETPAR,<rate_param_id>,2*<checksum>", "$PSTMSETPAR,<nmea_param_id>,<value>*<checksum>", "$PSTMSAVEPAR*<checksum>" }; HAL_Delay(500); // 等模块启动完成 for (int i = 0; i < 3; i++) { GNSS_UART_Send((uint8_t *)cmds[i], strlen(cmds[i])); HAL_Delay(50); } }

注意,发送配置序列时不要把保存命令放在最前面。应该先设置所有参数,最后统一保存。如果把保存命令放在中间,后续参数设置又改了RAM,那保存的配置就是旧的,断电重启后还是会丢失。

6.3 时序细节:延时、行尾、发送完整性

主控发送UART配置命令时,要注意以下几个方面:

  • 模块上电初始化需要时间,不等它启动完成就发命令,命令会被丢弃。
  • 每条命令的\r\n必须完整发送,有些UART驱动发送字符串时会漏掉\r只发\n,要检查。
  • 发送缓冲区要足够大,命令不能在半路被截断。
  • 用DMA发送时,要等DMA传输完成再去执行下一条命令,否则后一条命令可能覆盖前一条的数据。

6.4 自动配置的验证方法

配置写完不能直接扔到产品里就不管了,要验证。我的习惯是在开发板上保留一个调试串口输出,主控每次执行配置后,把模块返回的响应原样打印出来,人工确认收到的不是错误响应。

如果项目没有调试串口,就在主控里做简单校验:发送设置命令后,查询同一参数,确认查询结果和设置值一致,再做下一步。虽然麻烦一点,但比盲发命令可靠得多。

另一个好工具是逻辑分析仪。UART TX和RX分别挂两个通道,抓一次完整的配置交互过程,波特率对不对、命令有没有截断、模块返回了什么,一眼就能看明白。我调试配置问题时基本都会挂上逻辑分析仪,省去了很多猜来猜去的时间。

最后说一个我个人的小习惯:每次调参前先把模块当前配置完整查询一遍并记录下来。模块配置这东西,改多了真的会乱,有备份才能快速恢复。如果真的把配置改乱了,直接恢复默认再从头来一遍,比盲目猜测快得多。TESEO-LIV3F的UART配置流程本身不难,难都在细节——电平匹配、行尾、校验和、Flash保存时机,把这几件事理清楚,配置这个环节就能稳定复现,不会再折磨人。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询