1. 为什么EC25的VoLTE配置值得单独拿出来讲移远EC25这颗模组在物联网圈子里算是老面孔了LTE Cat 4、全球频段覆盖、Mini PCIe和LGA两种封装做车载终端、工业网关、共享设备的基本都绕不开它。但很多人拿到模组之后发现一个尴尬的事数据业务跑得好好的一打电话就掉到2G/3G甚至直接提示无法建立语音呼叫。这不是模组坏了而是VoLTE没配通。VoLTE说白了就是把语音承载在LTE网络上走的是IMSIP Multimedia Subsystem这套架构。跟传统的CS域通话相比VoLTE接通更快、音质更好而且通话时数据不断网。对于做车载紧急呼叫、智能手表、对讲设备的人来说VoLTE不是可选项是必选项。EC25本身是支持VoLTE的但出厂默认配置不一定打开了IMS相关的能力需要你通过AT指令去把这条链路打通。我前后在几个项目里调过EC25的VoLTE从最开始一脸懵地翻手册到后来能比较快地定位问题中间踩了不少坑。这篇文章就把整个配置流程、关键指令、常见故障排查整理出来给正在折腾这块的同行一个可复现的参考。不管你是刚接触AT指令的新手还是已经用过几款模组的老手应该都能从里面找到有用的东西。2. 动手之前先把这些概念理清楚2.1 VoLTE和IMS到底是什么关系很多刚上手的朋友会把VoLTE和IMS当成两个并列的东西其实不是。VoLTE是一种业务能力IMS是支撑这个能力的核心网架构。你可以这么理解IMS是一套“电话交换机系统”VoLTE是这套系统提供的一种“通话服务”。模组要能打VoLTE电话前提是它得成功注册到运营商的IMS网络上。注册IMS的过程涉及几个关键环节首先是LTE附着Attach模组要接入LTE网络并建立默认承载然后是IMS PDN连接的建立这需要模组发起一个专门的APN激活请求通常APN名是“ims”接着是SIP注册模组通过SIP协议向IMS服务器注册自己的身份最后才是呼叫的建立和媒体协商。整个链条里任何一环出问题VoLTE都用不了。EC25内部已经集成了IMS协议栈你不需要自己写SIP信令模组会帮你处理。你要做的是通过AT指令告诉模组用哪个APN、开不开IMS、怎么发起注册。这也是为什么配置的核心就是几条AT指令的事但前提是你得知道每条指令在干什么。2.2 EC25支持VoLTE的前提条件不是所有EC25都能直接上VoLTE有几个硬性条件得先确认。第一是固件版本早期出货的EC25固件可能没有完整开放IMS相关指令你需要确认固件版本号太老的版本建议先升级。第二是运营商支持VoLTE是运营商网络侧的能力你得确认你用的SIM卡所属运营商在你所在的区域已经开通了VoLTE服务而且这张卡本身是支持VoLTE的。第三是硬件射频配置EC25有不同的频段版本比如EC25-E、EC25-A、EC25-AU等要确保你用的版本支持当地运营商的LTE频段。我遇到过一种情况模组、固件、SIM卡都没问题但就是注册不上IMS最后发现是测试区域的运营商VoLTE覆盖还不完整。这种时候你再怎么调AT指令也没用得换地方或者换运营商。所以动手之前先做基本的环境确认能省掉很多无效调试。2.3 AT指令在VoLTE配置中的角色AT指令本质上是你和模组之间的对话语言。模组内部有很多功能模块IMS就是其中之一但默认状态下这些功能不一定全部激活。AT指令的作用就是去查询状态、修改配置、触发动作。跟VoLTE相关的AT指令大致分几类一类是查询模组能力和当前状态的比如查固件版本、查IMS注册状态一类是配置IMS参数的比如设置IMS APN、开启IMS功能还有一类是操作类的比如手动触发IMS注册、发起语音呼叫。理解这个分类你在看指令手册的时候就不会迷路。需要特别说明的是不同固件版本的EC25在指令支持上可能有差异。有些指令在某个版本里能用换一个版本就返回ERROR。所以下面我给出的指令清单是基于常见固件版本的实践总结你在实际使用时要结合自己模组的实际情况来验证。3. 核心AT指令逐条拆解与实操要点3.1 基础状态查询先搞清楚模组现在是什么状态在改任何配置之前先查状态。这跟医生看病一样得先知道病人现在什么情况才能决定怎么治。最常用的几条查询指令如下。ATCGMR用来查固件版本。返回的字符串里包含了固件版本号和编译日期。我一般会把这个信息记下来后面如果遇到问题需要查手册或者找FAE支持这个信息是必须的。ATCPIN?查SIM卡状态。返回CPIN: READY说明卡正常。如果返回CPIN: SIM PIN说明卡被PIN锁了需要先用ATCPINxxxx解锁。如果返回ERROR或者无响应检查卡座接触和卡本身是否损坏。ATCREG?查网络注册状态。返回格式是CREG: n,stat其中stat为1表示已注册到本地网络5表示已注册到漫游网络。如果stat是2说明正在搜索0说明未注册。VoLTE的前提是至少已经注册到LTE网络。ATCGREG?查GPRS/PS域注册状态逻辑跟CREG类似。对于LTE网络主要看CREG和CEREG。ATCEREG?查EPS网络注册状态这是LTE专用的。返回CEREG: n,statstat为1或5表示已注册。这条指令比CREG更直接反映LTE附着状态。ATCSQ查信号质量。返回CSQ: rssi,berrssi在0到31之间越大越好99表示无信号。VoLTE对信号质量有一定要求rssi太低比如低于10的时候IMS注册可能会失败。ATQCFGims这条是移远私有指令用来查询IMS功能的当前配置状态。返回的内容会告诉你IMS是否使能、当前注册状态等信息。不同固件版本返回格式可能略有不同但核心信息是一致的。我通常会把上面这些查询指令按顺序跑一遍把结果记录下来。这样后面配置改完之后再查一遍就能对比出哪些状态发生了变化方便定位问题。3.2 IMS功能开关与APN配置把路修通确认基础状态正常之后接下来就是配置IMS相关的参数。核心思路是告诉模组用哪个APN去建立IMS PDN连接然后把IMS功能打开。ATQCFGims,1这条指令用来使能IMS功能。参数1表示开启0表示关闭。执行之后模组会尝试建立IMS PDN连接并注册。有些固件版本可能需要先配置APN再开IMS顺序反了会失败。ATCGDCONT用来定义PDP上下文。对于IMS你需要单独定义一个context通常用cid2或者更高的编号cid1一般留给默认数据APN。指令格式是ATCGDCONTcid,IP,apn。IMS的APN通常是“ims”但不同运营商可能不一样。比如国内某运营商的IMS APN就是“ims”而有些海外运营商可能用“ims.mncxxx.mccxxx.gprs”这种格式。这个信息你得从运营商那里确认或者查运营商公开的APN配置文档。举个例子假设你要在cid2上定义IMS APN为“ims”指令就是ATCGDCONT2,IP,ims执行成功返回OK。然后你可以用ATCGDCONT?查询当前所有PDP上下文定义确认配置生效。ATQICSGP是移远用来配置TCP/IP上下文参数的指令跟IMS场景关系不大但如果你后续要在IMS PDN上跑数据可能会用到。这里先不展开。ATQIACT用来激活PDP上下文。对于IMS context你可以用ATQIACTcid来手动激活。不过如果你已经通过ATQCFGims,1开启了IMS模组通常会自动激活IMS PDN不需要手动再激活一次。手动激活主要用于调试比如你想确认这个APN能不能正常建立连接。这里有个细节值得注意IMS PDN连接和普通数据PDN连接是分开的。普通数据走cid1IMS走cid2或你指定的其他cid。两者互不干扰这也是为什么VoLTE通话时数据不会断的原因——语音走IMS PDN数据走默认PDN各走各的路。3.3 IMS注册状态查询与手动触发确认是否真的注册上了配置完APN并开启IMS之后最关键的一步是确认IMS是否真的注册成功了。这里有几条指令可以用。ATQCFGims再次查询这次重点看返回里的注册状态字段。如果显示已注册通常是一个特定的状态码或文字说明IMS注册成功。如果显示未注册或正在注册说明还有问题。ATCIREG?这条指令用来查询IMS注册状态。返回格式通常是CIREG: n,reg_info其中reg_info为1表示已注册0表示未注册。不同固件版本可能略有差异但核心逻辑一样。ATQIMSREG?部分固件版本支持这条指令直接返回IMS注册状态。如果你的模组不支持返回ERROR那就用上面那条。如果查询发现没有注册上可以尝试手动触发。ATQCFGims,1本身就会触发注册但有时候需要先关闭再打开来强制重新注册ATQCFGims,0 ATQCFGims,1这个操作相当于重启IMS功能在调试阶段很常用。我遇到过好几次配置看起来都对但就是注册不上关一下再开就好了可能是模组内部状态机卡住了。还有一个可能影响注册的因素是IMS APN的认证方式。有些运营商的IMS APN需要用户名和密码认证这时候你需要用ATCGAUTH来配置认证参数ATCGAUTHcid,auth_type,username,passwordauth_type通常为1PAP或2CHAP具体用哪种得看运营商要求。国内运营商的IMS APN一般不需要认证但海外有些运营商是需要的。3.4 语音呼叫相关指令从注册成功到打通电话IMS注册成功之后理论上就可以发起VoLTE呼叫了。EC25支持通过AT指令发起语音呼叫常用的指令如下。ATDnumber;用来发起语音呼叫。注意号码后面要加分号表示这是语音呼叫而不是数据呼叫。比如拨打10086就是ATD10086;。执行成功后会返回OK然后模组会输出一系列状态码比如QIND: voice call, 1之类的表示呼叫状态变化。ATA用来接听来电。当有来电时模组会输出RING或者CRING: VOICE之类的提示这时候执行ATA就能接听。ATH用来挂断电话。不管是主叫还是被叫执行ATH都会挂断当前通话。ATCLCC用来查询当前呼叫列表。返回的信息包括呼叫方向主叫/被叫、呼叫状态拨号中/振铃中/通话中、呼叫模式语音/数据等。调试的时候这条指令很有用能让你清楚地知道当前呼叫处于什么阶段。ATCMUT用来静音/取消静音麦克风。参数1表示静音0表示取消静音。这个在调试音频通路的时候会用到。ATCLVL用来设置扬声器音量。参数范围通常是0到某个最大值具体取决于固件。调试音频的时候可以逐级调整找到合适的音量。ATQAUDMOD是移远用来设置音频模式的指令。EC25支持多种音频模式比如手持模式、免提模式、耳机模式等。不同的音频模式对应不同的增益参数VoLTE通话时如果声音太小或者有回声可能需要调整这个。这里要提醒一点VoLTE呼叫的建立时间通常比CS域呼叫要短但首次注册IMS之后的第一通电话可能会稍慢一些因为涉及到IMS PDN的建立和SIP注册的完成。后续通话就会很快。如果你发现第一通电话要等很久才接通不一定是配置问题可能是正常的首次注册开销。4. 完整配置流程与实操记录4.1 从零开始的配置步骤下面我把整个配置流程按顺序整理一遍你可以直接照着操作。假设你用的是EC25固件版本支持IMS相关指令SIM卡已开通VoLTE。第一步确认基础状态。依次执行ATCGMR ATCPIN? ATCSQ ATCEREG?确认固件版本、SIM卡就绪、信号质量正常、LTE已注册。如果CEREG返回未注册先解决网络注册问题别急着配IMS。第二步配置IMS APN。假设用cid2ATCGDCONT2,IP,ims执行后返回OK。然后用ATCGDCONT?确认配置已写入。第三步开启IMS功能ATQCFGims,1返回OK后等待几秒钟让模组建立IMS PDN并注册。第四步查询IMS注册状态ATQCFGims ATCIREG?如果显示已注册说明配置成功。如果未注册尝试关闭再开启ATQCFGims,0 ATQCFGims,1再查一次状态。第五步发起测试呼叫ATD10086;观察返回信息和后续的URC非请求结果码确认呼叫是否成功建立。如果听到回铃音或者对方接听说明VoLTE通路已经打通。第六步挂断ATH整个流程走下来顺利的话十分钟以内能搞定。但实际调试中往往会遇到各种意外下面我把常见问题和排查方法整理一下。4.2 关键参数的计算与选择逻辑在配置过程中有几个参数需要你根据实际情况做选择这里说一下背后的逻辑。cid的选择cid1通常被默认数据APN占用所以IMS建议用cid2或更高。但有些运营商的默认数据APN和IMS APN是同一个这种情况下你也可以直接用cid1不过我不推荐这么做因为混在一起容易出问题。分开配置的好处是清晰数据归数据IMS归IMS互不影响。APN的确定IMS APN不是随便填的必须跟运营商网络侧配置一致。国内三大运营商的IMS APN通常就是“ims”但海外运营商可能不同。如果你不确定可以查运营商公开的APN设置文档或者用ATCGDCONT?看看模组自动配置的APN列表里有没有IMS相关的条目。有些模组在插入SIM卡后会自动从网络获取APN配置你可以先查一下再决定要不要手动配。认证方式的选择如果运营商IMS APN需要认证你得知道用PAP还是CHAP。这个信息运营商文档里会有。如果不确定可以先不配认证试一下注册不上再补。国内运营商一般不需要。音频模式的选择EC25的音频模式通过ATQAUDMOD设置。不同的音频模式对应不同的硬件通路和增益参数。如果你用的是模组厂商的参考设计通常有一个推荐的音频模式。如果你自己设计的音频电路可能需要根据实际情况调整。这个没有固定答案得实测。4.3 实操现场一次完整的调试记录我拿最近一次调试EC25 VoLTE的过程做个记录把关键步骤和返回信息都列出来供你参考。模组上电串口工具打开波特率115200。先发几条基础查询AT OK ATCGMR EC25EFAR06A10M4G OK ATCPIN? CPIN: READY OK ATCSQ CSQ: 22,99 OK ATCEREG? CEREG: 0,1 OK固件版本是EC25EFAR06A10M4GSIM卡就绪信号质量22还不错LTE已注册。基础状态正常。接下来配IMS APNATCGDCONT2,IP,ims OK ATCGDCONT? CGDCONT: 1,IP,cmnet,0.0.0.0,0,0,0,0 CGDCONT: 2,IP,ims,0.0.0.0,0,0,0,0 OK可以看到cid1是默认数据APN“cmnet”cid2是我们刚配的IMS APN“ims”。两条都在。开启IMSATQCFGims,1 OK等了几秒查询状态ATQCFGims QCFG: ims,1,1 OK返回的第二个参数是1表示IMS已注册。再用CIREG确认一下ATCIREG? CIREG: 1,1 OK也是已注册状态。到这里IMS注册就成功了。发起测试呼叫ATD10086; OK然后模组陆续输出了一些URCQIND: voice call, 1 QIND: voice call, 2呼叫状态从1拨号中变成2振铃中说明呼叫已经建立正在等待对方接听。听筒里能听到回铃音。等了一会儿对方接听通话正常声音清晰没有断流。挂断ATH OK QIND: voice call, 0呼叫状态回到0通话结束。整个过程大概用了两三分钟其中大部分时间是在等IMS注册。第一次注册确实会慢一点后面再打电话就很快了。5. 常见问题排查与避坑经验5.1 IMS注册不上怎么办这是最常见的问题表现是ATQCFGims返回的注册状态一直是0或者ATCIREG?返回未注册。排查思路按以下顺序来。先确认LTE网络注册是否正常。如果ATCEREG?返回的stat不是1或5说明模组根本没附着到LTE网络那IMS肯定注册不上。先解决网络注册问题。再确认IMS APN是否正确。用ATCGDCONT?查一下cid2的APN是不是“ims”。如果APN写错了IMS PDN建立不起来自然注册不上。如果你不确定运营商的IMS APN可以试着不手动配让模组用默认的有些固件会自动从网络获取。然后确认IMS功能是否真的开启了。ATQCFGims返回的第一个参数应该是1。如果是0说明没开重新执行ATQCFGims,1。如果以上都正常但还是注册不上尝试关闭再开启IMS功能强制重新注册。还不行的话检查SIM卡是否开通了VoLTE服务。有些SIM卡虽然能上网但VoLTE功能没开这种情况得联系运营商。最后如果所有配置都正确但就是注册不上可能是当地运营商VoLTE覆盖问题。换个地方或者换张卡试试。5.2 能注册但打不了电话IMS注册成功但发起呼叫失败或者呼叫建立后没有声音。这种情况通常跟音频通路或者呼叫参数有关。先确认呼叫是否真的发起了。用ATCLCC查呼叫列表看看有没有活跃的呼叫。如果没有说明ATD指令可能没执行成功检查号码格式是否正确别忘了分号。如果有呼叫但没声音检查音频模式设置。ATQAUDMOD?查当前音频模式试着切换到其他模式测试。有时候默认音频模式跟你的硬件设计不匹配导致声音走错了通路。还要检查麦克风和扬声器的硬件连接。EC25的音频接口是模拟的如果你自己画的板子确认一下偏置电压和耦合电容是否合适。这个属于硬件层面AT指令解决不了。另外有些运营商对VoLTE呼叫的编解码格式有要求。EC25支持AMR-WB等编解码但具体用哪种是模组和网络协商的你一般不需要手动干预。如果协商失败可能会没有声音。这种情况比较少见但如果遇到了可以查一下模组的音频配置参数。5.3 常见问题速查表问题现象可能原因排查方法解决措施IMS注册状态一直为0LTE未注册查ATCEREG?先解决LTE附着问题IMS注册状态一直为0APN配置错误查ATCGDCONT?修正IMS APNIMS注册状态一直为0IMS功能未开启查ATQCFGims执行ATQCFGims,1IMS注册状态一直为0SIM卡未开通VoLTE联系运营商确认开通VoLTE服务注册成功但呼叫失败号码格式错误检查ATD指令号码后加分号呼叫建立但无声音音频模式不匹配查ATQAUDMOD?切换音频模式呼叫建立但无声音硬件音频通路问题检查电路修正硬件设计首次呼叫很慢IMS首次注册开销观察后续呼叫正常现象无需处理通话中数据断网IMS PDN未建立查ATCGDCONT?确认IMS APN已配5.4 几个容易忽略的细节第一个细节是AT指令的响应时间。有些指令执行后不是立刻返回OK比如ATQCFGims,1之后模组需要几秒钟去建立PDN和注册这期间你发其他指令可能会返回ERROR。我的做法是执行完开启指令后等5到10秒再查状态别急着连续发指令。第二个细节是URC的处理。模组会主动上报一些状态变化比如呼叫状态、网络注册变化等。如果你的串口工具没有正确处理URC可能会把这些信息当成指令响应导致解析混乱。建议在代码里把URC和指令响应分开处理。第三个细节是固件版本差异。不同版本的EC25固件在IMS指令支持上可能有细微差别。比如有些版本用ATQCFGims有些版本可能用ATQIMS之类的。遇到指令返回ERROR的时候先查一下你那个固件版本对应的指令手册别硬套。第四个细节是SIM卡的热插拔。EC25支持SIM卡热插拔检测但如果你在IMS注册成功之后拔卡再插卡IMS状态可能会变得不正常。建议拔插卡之后重新执行一遍IMS配置流程。6. 常用AT指令清单与速查6.1 状态查询类指令指令功能典型返回ATCGMR查固件版本EC25EFAR06A10M4GATCPIN?查SIM卡状态CPIN: READYATCSQ查信号质量CSQ: 22,99ATCEREG?查LTE注册状态CEREG: 0,1ATCGREG?查PS域注册状态CGREG: 0,1ATCREG?查CS域注册状态CREG: 0,1ATQCFGims查IMS配置与状态QCFG: ims,1,1ATCIREG?查IMS注册状态CIREG: 1,1ATCLCC查当前呼叫列表CLCC: 1,0,0,0,0,10086,129ATQAUDMOD?查当前音频模式QAUDMOD: 06.2 配置类指令指令功能示例ATCGDCONT定义PDP上下文ATCGDCONT2,IP,imsATQCFGims,1开启IMS功能ATQCFGims,1ATQCFGims,0关闭IMS功能ATQCFGims,0ATCGAUTH配置PDP认证ATCGAUTH2,1,user,passATQAUDMOD设置音频模式ATQAUDMOD0ATCLVL设置扬声器音量ATCLVL3ATCMUT麦克风静音控制ATCMUT16.3 操作类指令指令功能说明ATD ;发起语音呼叫号码后必须加分号ATA接听来电收到RING后执行ATH挂断电话挂断当前通话ATQIACT激活PDP上下文ATQIACT2ATQIDEACT去激活PDP上下文ATQIDEACT26.4 指令使用中的几个经验点关于ATQCFGims的返回格式不同固件版本可能不一样。有的返回两个参数有的返回三个。第一个参数通常是使能状态0或1第二个是注册状态0或1如果有第三个可能是其他信息。你拿到模组之后先跑一遍看看实际返回什么别照搬网上的例子。关于ATD指令号码后面的分号是必须的。没有分号的话模组会当成数据呼叫处理结果就是呼叫失败。这个坑我踩过当时查了半天以为IMS有问题最后发现是分号漏了。关于ATH和ATCHUP的区别两者都是挂断但ATH是标准指令ATCHUP也是标准指令功能基本一样。EC25上两个都能用我习惯用ATH短一点。关于URC的格式EC25的语音呼叫相关URC通常是QIND: voice call, state这种格式。state为0表示空闲1表示拨号中2表示振铃中3表示通话中。不同固件版本可能略有差异以实际为准。7. 写在最后的一些个人体会调EC25的VoLTE说难不难说简单也不简单。核心就是那几条AT指令但实际调试中遇到的问题往往不在指令本身而在环境配置和细节处理上。我自己的经验是先把基础状态查清楚再一步步往上配每配一步就查一次状态确认没问题再继续。这样虽然看起来慢但出问题的时候容易定位。另外别太依赖网上的配置示例。不同固件版本、不同运营商、不同硬件设计都可能需要微调。手册是最好的参考遇到不确定的指令先查手册别瞎试。如果手册也说不清楚找模组厂商的FAE支持他们手里有更详细的文档和调试工具。最后说一个我最近发现的点EC25在IMS注册成功之后如果长时间没有语音业务运营商网络可能会把IMS注册释放掉。这时候你再打电话模组会重新注册第一通电话可能会慢一点。这个行为是正常的不是模组故障。如果你做的是需要随时待命的设备可以考虑定期发一个SIP保活消息但EC25内部应该已经处理了这件事具体行为可以抓log确认。