概述*
请阅读 GX8006大模型开发包下载 国芯微离线语音协议_v*.pdf。
1.串口协议解析流程*
-
串口驱动层需要用户根据控制端MCU的开发环境进行移植实现,主要完成以下功能:
- 串口硬件初始化:配置串口基本参数,包括波特率、数据位、停止位、校验位等
- 数据收发管理:实现串口数据的发送和接收功能,确保数据传输的可靠性
- DMA配置:配置DMA通道、传输模式、缓冲区等参数,优化数据传输效率
- 中断处理:实现串口和DMA相关中断的处理,确保数据及时处理
-
协议解析层可参考开发包中的wifi_uart_demo_example_v*.zip进行开发,主要完成以下功能:
- 数据帧解析:解析接收到的数据帧,提取命令类型、数据长度、数据内容等信息
- 响应组装:根据处理结果或用户层相应结果,组装响应数据帧
- 状态管理:维护帧解析状态机,处理异常情况
- 数据校验:实现数据帧的校验功能,确保数据完整性
-
用户控制层处理解析层递交上来的帧结构数据
1.1.通信架构*
- 串口通信的双方分别是:
- 语音芯片(GX8006):作为协议的服务端
- 用户控制MCU:作为协议的客户端
1.2.DMA传输建议*
- 由于通信数据中包含较大的音频数据,强烈建议使用DMA进行串口数据传输,原因如下:
- 减少CPU负载:DMA可以直接在内存和外设之间传输数据,无需CPU干预
- 提高传输效率:DMA传输速度更快,且不会因为CPU处理其他任务而延迟
- 避免数据丢失:DMA可以持续接收数据,不会因为CPU处理不及时导致数据丢失
1.3.不定长数据处理*
由于串口数据包长度不固定,建议采用以下方式处理:
-
帧结构设计
- 帧头:用于标识数据包的开始
- 长度字段:指示后续数据的长度
- 数据负载:实际传输的数据
- 校验字段:用于验证数据完整性
-
数据接收流程
- 使用DMA接收数据到缓冲区
- 通过状态机解析数据帧
- 根据帧头识别数据包开始
- 根据长度字段确定数据包结束位置
- 进行数据校验确保完整性
-
缓冲区管理
- 建议使用环形缓冲区
- 设置合适的缓冲区大小,建议至少能容纳最大数据包的两倍
- 实现缓冲区满/空状态的处理机制
2.串口交互流程*
-
串口通信采用一问一答的交互方式,具体流程如下:
- 发送数据帧后,需要等待语音芯片的回复才能继续发送新的数据帧
- 在等待回复期间,可能会收到语音芯片主动上报的数据帧,包括:
- 音频数据帧:需要及时处理并上报给云端
- 唤醒事件帧:需要及时处理并发送确认帧
- 其他事件帧:根据具体事件类型进行相应处理
-
帧处理机制:
- 通过帧结构中的子命令字段判断当前帧的类型
- 若是对之前下发帧的回复,则:
- 处理回复内容
- 解除发送阻塞,允许发送新的数据帧
- 若是主动上报的数据帧,则:
- 立即处理该帧数据
- 根据帧类型发送相应的确认帧
- 继续等待之前下发帧的回复
-
注意事项:
- 需要维护发送队列,确保数据帧按序发送
- 需要实现超时处理机制,避免永久等待
- 需要正确处理并发情况,确保数据处理的实时性
- 建议使用状态机管理整个交互流程
- 语音芯片端采用前后台系统,使用DMA+Ringbuffer的方式管理接收数据
- 若未等到回复就发送新的数据将导致语音芯片的接收数据被覆盖
3.麦克风增益配置示例:*
麦克风增益配置是语音交互的重要参数,直接影响语音识别的效果。配置时需要注意以下几点:
-
配置参数说明:
- 采样率(sample_rate):仅支持16000Hz,适合语音编码,能完整覆盖人声频率范围
- 采样位深(bit):仅支持16bit,是语音和音乐编码的标准位深
- 通道数(channels):仅支持使用单声道,适合语音通信场景
- 增益值(dB):范围0-32dB,建议使用26dB
- 数据格式(format):仅支持OPUS格式
- 最大接收长度(max_recv_len):根据实际应用场景设置,建议不小于1024字节;语音芯片将连续发送多个80字节的语音帧,直到模组最大可接收数据长度
-
配置流程:
- 发送配置命令帧
- 等待语音芯片返回确认帧
- 验证返回的命令号和返回值,若配置不支持,语音芯片将返回错误
- 释放应答帧内存
static int smartbot_set_mic(void)
{
int status = 0;
/* 存放 GX8006 的应答帧 */
sbot_frame_t *rsp = NULL;
/* 配置麦克风功能的子命令帧结构 */
struct smartbot_mic_config
{
uint8_t cmd; /* 子命令号:SBOT_CMD_SET_MIC_CONFIG */
uint32_t sample_rate; /* 采样率(大端格式传输) */
uint8_t bit; /* 采样位深 */
uint8_t channels; /* 音频通道数量 */
uint8_t dB; /* 麦克风增益,范围 0-32dB */
uint8_t format; /* 传输数据格式 */
uint32_t max_recv_len; /* 单次可以接收的最大数据,单位字节 */
}
__PACKED__ req_data =
{
.cmd = SBOT_CMD_SET_MIC_CONFIG,
.sample_rate = smartbot_le2be_u32(16000),
.bit = 16,
.channels = 1,
.dB = 26,
.format = 2,
.max_recv_len = smartbot_le2be_u32(1024),
};
/* 此处调用会阻塞当前线程,直到收到 GX8006 的应答帧,并将应答帧的地址返回给 rsp */
rsp = smartbot_talk((uint8_t *)&req_data, sizeof(req_data));
if (NULL == rsp)
{
return -1;
}
/* 应答帧结构,对 rsp 的 data 部分进行解析 */
struct smartbot_mic_config_resp
{
uint8_t cmd;
uint8_t retcode;
}
__PACKED__ *rsp_data = (struct smartbot_mic_config_resp *)(rsp->data);
/* 验证是否是正确的应答,验证返回值是否正确 */
status = ((rsp_data->cmd == req_data.cmd) && (rsp_data->retcode == 0x00)) ? 0 : -1;
LOG(LOG_LVL_INFO, "[SBOT] subcmd: %02X retcode: %d\r\n", rsp_data->cmd, rsp_data->retcode);
/* 底层返回的应答帧数据为动态分配,需要释放 */
OS_Free(rsp);
return status;
}
4.交互模式配置说明:*
4.1 功能控制说明*
-
语音上报功能由三级控制组成:
- Mic总开关(0x01):控制麦克风开关
- 0:关闭MIC
- 1:开启MIC
- 唤醒功能(0x03):控制唤醒检测
- 0:关闭唤醒功能
- 1:开启唤醒功能
- Vad功能(0x04):控制语音活动检测
- 0:关闭Vad
- 1:开启Vad,超时时间=1000ms
- 大于1:开启vad,超时时间=配置值*40ms
- Mic总开关(0x01):控制麦克风开关
-
控制优先级(从高到低):
- Mic开关 > 唤醒标志 > Vad标志
-
超时配置:
- Vad超时配置命令(0x07):控制Vad检测的灵敏度
- 唤醒超时配置命令(0x05):控制唤醒状态的持续时间
4.2 典型应用场景*
4.2.1 唤醒持续对话模式*
- 功能描述:唤醒后直接上报音频,持续上报60秒
- 配置步骤:
- 设置最大拾音时间:60秒
- 设置唤醒超时时间:60秒
- 打开Mic总开关
- 关闭Vad功能
- 打开唤醒功能
- 注意事项:唤醒时间应小于拾音时间,否则无法达到最大拾音时间
- 配置命令:
55aa0092000307083cdf # 最大拾音时间60s 55aa0092000307073cde # 唤醒超时时间60s 55aa009200030701019d # 打开Mic总开关 55aa009200030704009f # 关闭Vad功能 55aa009200030703019f # 打开唤醒功能
4.2.2 按键长按对话模式*
- 功能描述:按键长按时上报数据,最长持续60秒
- 配置步骤:
- 设置最大拾音时间:60秒
- 默认关闭所有功能
- 按键按下时打开mic
- 按键松开时关闭mic
- 配置命令:
55aa0092000307083cdf # 设置最大拾音时间60秒 55aa009200030701009c # 关闭mic 55aa009200030703009e # 关闭唤醒 55aa009200030704009f # 关闭vad 55aa009200030701019d # 长按按键时打开mic 55aa009200030701009c # 松开时关闭mic
4.2.3 按键触发对话模式*
- 功能描述:按键触发后,Vad拉起时上报数据,1秒无语音Vad结束,5秒无语音退出唤醒
- 配置步骤:
- 设置唤醒超时:5秒
- 设置Vad间隔:1秒
- 打开所有功能
- 配置按键触发和超时处理
- 配置命令:
55aa00920003070705a7 # 设置唤醒超时5s 55aa00920003070419b8 # 设置Vad间隔1s 55aa009200030701019d # 打开mic 55aa009200030703019f # 打开唤醒 55aa00920003070401a0 # 打开vad 55aa00920003070501a1 # 配置按键触发 55aa00920003070601a2 # 配置超时处理
4.2.4 唤醒触发对话模式*
- 功能描述:每次对话需要唤醒,Vad拉起时上报数据,1秒无语音Vad结束,5秒无语音退出唤醒
- 配置步骤:
- 设置唤醒超时:5秒
- 设置Vad间隔:1秒
- 打开所有功能
- 配置超时处理
- 配置命令:
55aa00920003070705a7 # 设置唤醒超时5s 55aa00920003070419b8 # 设置Vad间隔1s 55aa009200030701019d # 打开mic 55aa009200030703019f # 打开唤醒 55aa00920003070401a0 # 打开vad 55aa00920003070601a2 # 配置超时处理
4.2.5 自由对话模式*
- 功能描述:首次需要唤醒,之后通过Vad控制,1秒无语音Vad结束,30秒无语音退出唤醒
- 配置步骤:
- 设置唤醒超时:30秒
- 设置Vad间隔:1秒
- 打开所有功能
- 配置命令:
55aa0092000307071ec0 # 设置唤醒超时30s 55aa00920003070419b8 # 设置Vad间隔1s 55aa009200030701019d # 打开mic 55aa009200030703019f # 打开唤醒 55aa00920003070401a0 # 打开vad
4.3 Vad灵敏度控制*
- 功能描述:调整Vad检测的灵敏度,默认灵敏度45
- 参数范围:
- 0-100: 默认45,数值越大,灵敏度越低
- 配置命令:
55aa0092000307092dd1 # 设置vad阈值为45
4.4 降噪设置*
- 功能描述:调整降噪等级,默认等级0
- 参数范围:
- 0x00-0x03: 代表降噪等级
- 0xFF: 关闭降噪
- 配置命令:
55aa00920003070A01a6 # 设置降噪等级1
4.4 参考示例*
- 在开发包中的wifi_uart_demo_example_v*.zip包含以下4种模式的切换
- 自由对话模式
- 唤醒对话模式
- 按键对话模式
- 长按对话模式
- 各个模式抽象为如下结构
struct smartbot_mode { /* config */ uint16_t vad; /* VAD(语音活性检测)配置 */ bool mic; /* 麦克开关配置 */ bool awk; /* 唤醒开关配置 */ sbot_audio_res_t res; /* 本地模式播报资源 */ /* function */ void (*on_ui_event)(sbot_mode_event_t); /* 注册到用户接口的事件回调函数,用于处理不同模式下的用户动作,单击长按按键等 */ void (*on_selected)(sbot_mode_t *); /* 当前模式被选中时触发回调 */ void (*on_conv_start)(sbot_mode_t *); /* 语音对话开始时触发回调 */ void (*on_conv_stop)(sbot_mode_t *); /* 语音对话结束时触发回调 */ void (*on_mic_stop)(sbot_mode_t *); /* 麦克上报停止时触发回调 */ };
- 任一模式被选中时,均会进行如下配置
- 配置当前模式默认的麦克开关、唤醒和 VAD 的配置
- 注册当前模式的事件处理函数给按键处理模块
- 固化当前模式
static void on_mode_conv_selected(sbot_mode_t *mode_inst) { smartbot_set_offline_config(SBOT_OFFLINE_SUBCMD_MIC, mode_inst->mic); smartbot_set_offline_config(SBOT_OFFLINE_SUBCMD_WAKEUP, mode_inst->awk); smartbot_set_offline_config(SBOT_OFFLINE_SUBCMD_VAD, mode_inst->vad); ui_button_awk_register_callback(mode_inst->on_ui_event); sysparam_store(SBOT_MODE_KEY, (const void *)&_this_mode_index, sizeof(_this_mode_index)); }
- 长按对话模式的示例
/* 用户接口的事件处理 */ static void on_longpress_conv_ui_event(sbot_mode_event_t event) { switch (event) { case SBOT_MEVT_BTN_DOUBLE_CLICK: { SBOT_MODE_EVT_CALL(SBOT_MEVT_CONV_MODE_SWITCH); /* 双击上报模式切换事件 */ break; } case SBOT_MEVT_BTN_LONGPRESS: { SBOT_MODE_EVT_CALL(SBOT_MEVT_CONV_START); /* 长按上报对话开始事件 */ break; } case SBOT_MEVT_BTN_RELEASE: { SBOT_MODE_EVT_CALL(SBOT_MEVT_CONV_STOP); /* 松开触发对话结束事件 */ break; } default: break; } } /* 对话开始的回调,在 on_longpress_conv_ui_event 上报 SBOT_MEVT_CONV_START 后,上层执行相关处理后调用该回调 */ static void on_longpress_conv_start(sbot_mode_t *mode_inst) { (void)mode_inst; smartbot_set_offline_config(SBOT_OFFLINE_SUBCMD_MIC, 1); /* 开启麦克 */ } /* 对话结束的回调,在 on_longpress_conv_ui_event 上报 SBOT_MEVT_CONV_STOP 后,上层执行相关处理后调用该回调 */ static void on_longpress_conv_stop(sbot_mode_t *mode_inst) { (void)mode_inst; smartbot_set_offline_config(SBOT_OFFLINE_SUBCMD_MIC, 0); /* 开启麦克 */ } /* 长按对话模式实例 */ static sbot_mode_t sbot_mode_longprss_conv = { .vad = 0, /* 默认VAD配置:关闭 */ .awk = 0, /* 默认唤醒配置:关闭 */ .mic = 0, /* 默认麦克配置:关闭 */ .on_ui_event = on_longpress_conv_ui_event, /* 注册当前对话模式的用户事件处理函数 */ .res = SBOT_AUDIO_RES_MODE_LONGPRSS_CONV, /* 注册当前对话模式的本地播报资源 */ .on_selected = on_mode_conv_selected, /* 注册当前对话模式激活的回调函数 */ .on_conv_start = on_longpress_conv_start, /* 注册当前对话模式开始的回调函数 */ .on_conv_stop = on_longpress_conv_stop, /* 注册当前对话模式结束的回调函数 */ };
5.FAQ*
5.1.客户的模组负责播放,如何开启语音芯片的AEC功能?*
- 一般 AEC(声学回声消除)功能需要播报和录音都在语音芯片端,芯片可通过内部回采消除自身喇叭播放的声音
- 如果客户的模组负责播放音频,仅需要语音芯片负责唤醒和录音,但又需要开启 AEC,则需要:
- 硬件上,客户的模组需要将音频播放信号接入语音芯片的回采通道
- 软件上,客户的模组在播放开始和结束时,需要使用【命令:通知 MCU 模组播放状态(0xF6)】告诉语音芯片当前的播放状态
5.2.云端下发的音频是否有格式限制?*
- 语音芯片播报的数据有格式限制
- 语音芯片播报的配置命令格式定义如下:
struct smartbot_spk_config { uint8_t cmd; /* 子命令号:SBOT_CMD_SET_SPK_CONFIG */ uint32_t sample_rate; /* 采样率(大端格式传输) */ uint8_t bit; /* 采样位深 */ uint8_t volume; /* 音量,范围 0-100 */ uint8_t format; /* 传输数据格式 */ uint32_t max_send_len; /* 单次可以接收的最大数据,单位字节 */ }
- 配置参数说明:
- 采样率(sample_rate):仅支持16000Hz,适合语音编码,能完整覆盖人声频率范围
- 采样位深(bit):仅支持16bit,是语音和音乐编码的标准位深
- 音量(volume):仅支持使用单声道,适合语音通信场景
- 数据格式(format):仅支持PCM和OPUS格式
- 最大发送长度(max_send_len):根据实际应用场景设置;若长度超出语音芯片能处理的最大长度,将返回错误及可接受的长度