跳转至

Volte

一、演示功能概述

VoLTE(Voice over LTE)是通过 LTE 网络实现的高清语音通话技术,基于 IMS(IP 多媒体子系统)架构,支持语音与数据并发传输,提供更低时延、更高清晰度的通话体验。

本章节将使用 Air780EHV 核心板,外接 AirAUDIO_1000 音频扩展板,演示 VOLTE 通话功能的使用方法。实现拨打接听电话的功能,接听电话是在回调中响铃两声后自动接听;拨打电话是板子上电,volte 初始化好后 5 秒钟拨打一个电话,测试的时候拨打的手机号注意修改成自己的,拨打电话此段代码默认是注释掉状态。

二、准备硬件环境

参考:Air780EHV 硬件环境清单,准备好硬件环境,本篇文档使用的是 AirEHV 核心板和 AirAUDIO_1000 音频扩展板,如下图所示:

连接图:

780EHV 核心板 连接 AirAUDIO_1000

3/MIC+ ———————— MIC+

4/MIC- ———————— MIC-

5/SPK+ ————————SPK+

6/SPK- ———————— SPK-

20/GPIO22 ————————PA_EN

3V3————————VCC

GND ————————GND

三、准备软件环境

烧录工具:Luatools 工具

Air780EHV 烧录需要的固件和脚本文件:

LuatOS 运行所需要的 lib 文件:

使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件

四、软硬件资料

4.1 API 接口介绍

audio

cc

五、代码示例介绍

5.1 代码介绍

-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "ccdemo"
VERSION = "1.0.0"
log.style(1)
--[[]
运行环境:Air780EHV核心板+AirAUDIO_1000配件板
最后修改时间:2025-6-17
使用了如下IO口:
[3, "MIC+", " PIN3脚, 用于麦克风正极"],
[4, "MIC-", " PIN4脚, 用于麦克风负极"],
[5, "spk+", " PIN5脚, 用于喇叭正极"],
[6, "spk-", " PIN6脚, 用于喇叭负极"],
[20, "AudioPA_EN", " PIN20脚, 用于PA使能脚"],
3.3V
GND
执行逻辑为:
设置i2s和音频参数,读取文件qianzw.txt里面的内容,然后播放出来
]]

-- sys库是标配
sys = require("sys")

local up1 = zbuff.create(6400,0)
local up2 = zbuff.create(6400,0)
local down1 = zbuff.create(6400,0)
local down2 = zbuff.create(6400,0)
local cnt = 0

local function record(is_dl, point)
    if is_dl then
        log.info("下行数据,位于缓存", point+1, "缓存1数据量", down1:used(), "缓存2数据量", down2:used())
    else
        log.info("上行数据,位于缓存", point+1, "缓存1数据量", up1:used(), "缓存2数据量", up2:used())
    end
    log.info("通话质量", cc.quality())
    -- 可以在初始化串口后,通过uart.tx来发送走对应的zbuff即可
end

sys.subscribe("CC_IND", function(state)
    log.info("cc状态", state)
    if state == "READY" then
        sys.publish("CC_READY")
    elseif state == "INCOMINGCALL" then
        cnt = cnt + 1
        if cnt > 1 then
            cc.accept(0)
        end
    elseif state == "HANGUP_CALL_DONE" or state == "MAKE_CALL_FAILED" or state == "DISCONNECTED" then
        audio.pm(0,audio.STANDBY)
        -- audio.pm(0,audio.SHUTDOWN)   --低功耗可以选择SHUTDOWN或者POWEROFF,如果codec无法断电用SHUTDOWN
    end
end)

sys.taskInit(function()
    cc.on("record", record)
    cc.record(true, up1, up2, down1, down2)
    local multimedia_id = 0
 local i2c_id = 0 -- i2c_id 0

    local pa_pin = gpio.AUDIOPA_EN -- 喇叭pa功放脚
    local power_pin = 20 -- es8311电源脚

    local i2s_id = 0 -- i2s_id 0
    local i2s_mode = 0 -- i2s模式 0 主机 1 从机
    local i2s_sample_rate = 16000 -- 采样率
    local i2s_bits_per_sample = 16 -- 数据位数
    local i2s_channel_format = i2s.MONO_R -- 声道, 0 左声道, 1 右声道, 2 立体声
    local i2s_communication_format = i2s.MODE_LSB -- 格式, 可选MODE_I2S, MODE_LSB, MODE_MSB
    local i2s_channel_bits = 16 -- 声道的BCLK数量

    local multimedia_id = 0 -- 音频通道 0
    local pa_on_level = 1 -- PA打开电平 1 高电平 0 低电平
    local power_delay = 3 -- 在DAC启动前插入的冗余时间,单位100ms
    local pa_delay = 100 -- 在DAC启动后,延迟多长时间打开PA,单位1ms
    local power_on_level = 1 -- 电源控制IO的电平,默认拉高
    local power_time_delay = 100 -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms

    local voice_vol = 70 -- 喇叭音量
    local mic_vol = 80 -- 麦克风音量
    gpio.setup(power_pin, 1, gpio.PULLUP)
    gpio.setup(pa_pin, 1, gpio.PULLUP)

    sys.wait(200)

    i2c.setup(i2c_id, i2c.FAST) -- 设置i2c
    i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,
        i2s_channel_bits) -- 设置i2s

    audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
    audio.setBus(multimedia_id, audio.BUS_I2S, {
        chip = "es8311",
        i2cid = i2c_id,
        i2sid = i2s_id,
    }) -- 通道0的硬件输出通道设置为I2S

    audio.vol(multimedia_id, voice_vol)
    audio.micVol(multimedia_id, mic_vol)

    cc.init(multimedia_id)
    audio.pm(0,audio.STANDBY)
    sys.waitUntil("CC_READY")
    log.info("一切就绪,5S后准备打电话")
    sys.wait(5000)   
    -- cc.dial(0,"12345678910) --拨打电话

end)

-- sys.taskInit(function()
--     while 1 do
--         -- 打印内存状态, 调试用
--         sys.wait(1000)
--         log.info("lua", rtos.meminfo())
--         log.info("sys", rtos.meminfo("sys"))
--     end
-- end)

-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!

5.2 功能测试

5.2.1 接听电话情况:

可以通过日志看到模组响两声后成功接听,并打印上下行通话数据,双 buff 缓冲区交替接收打印:

5.2.2 拨打电话情况:

此功能在代码中默认是注释掉的,测试的时候需要打开并修改手机号,VOLTE 初始化成功后延时 5s 拨打电话:

六、总结

至此,我们已经用 Air780EHV 核心板外接 AirAUDIO_1000 音频扩展板演示了 VOLTE 功能,演示了接听电话和拨打电话两种方式。

七、常见问题与注意事项

打不了电话

  • 确认 sim 卡是否开通 VOLTE 功能,sim 卡有没有欠费
  • 由于现在运营商监管比较严,sim 卡频繁入网,换设备被检测到异常通信可能会导致被封,这点在测试的时候需要注意。

日志中 LUAT_MOBILE_EVENT_CC status 返回的数字都代表什么意思

0 : 通话准备完成,可以拨打电话了
1 : 有来电
2 : 有来电号码
3 : 已接通电话号码
4 : 电话已经接通
5 : 电话被对方挂断
6 : 通话开始
7 : 拨打电话请求成功
8 : 拨打电话请求失败
9 : 接听电话请求完成
10 : 挂断电话请求完成
11 : 电话列表,未实现
12 : 电话功能相关音频控制