MCU开发接入VOI611指南

本文主要描述了MCU接入VOI611方案的开发流程,适用于嵌入式开发工程师及个人开发者快速入门,了解接入VOI611方案的方法。


1. 方案概述


MCU接入VOI611是快速实现产品语音智能化的常用方法,适用于已内置MCU主控的产品。

例如空调、洗衣机等大、小家电产品,自身MCU已具备复杂的外设控制和逻辑,接入VOI611串口协议即可实现语音交互功能,您只需要关注产品功能和语音交互(对话)的设计,复杂的语音算法和模型训练交由探境科技处理。

mcu_voi611_top_view

图 - VOI611作为外部输入输出设备

如上图所示,蓝色部分的VOI611可作为一个外部输入输出设备,主要具备以下两个功能:

  • 通过 MIC 输入(语音识别结果等)
  • 通过 SPK 输出(提示音等)

在本方案中,语音芯片内置寄存器表,产品主控MCU通过UART对VOI611的寄存器表进行配置,无需修改VOI611片内的软件代码,从而实现芯片的参数设定。

通常,语音芯片VOI611不维护产品状态(例如电机、灯光等电控设备由产品主控MCU维护,如上图绿色部分),这种方式使得VOI611更专注的处理语音的识别/播报,无需针对要实现的产品应用(例如空调、洗衣机逻辑功能)进行定制化开发,缩短了开发周期和联调成本。

同时,主控MCU可以自主定制语音交互的方案,能与产品自身功能结合的更好,标准化接入方式避免来回修改语音芯片固件和协议,提升库存通用性,减小生产和库存管控成本,便于安装和使用。

VOI611内置寄存器表涵盖了:设定唤醒时间、设定唤醒词、设定播放音量、播放指定的提示音、读取当前识别结果、唤醒状态等语音交互相关的配置参数。产品完整的语音交互方案设计均可由MCU进行设定,配合示例代码、寄存器表格、PC端调试工具,您可以快速出开发定制化的语音交互需求。

(如若不满足您的需求,可以将您的需求提交给探境销售或者技术支持人员)


2. 开发流程


常见的开发流程主要包括:获取VOI611硬件和固件、调试工具验证、MCU软件开发、联调对接等步骤。

mcu_voi611_flow

图 - 开发流程说明


3. 通讯接口和协议


3.1 通讯硬件连接

MCU通过下图的方式和VOI611进行连接:

mcu_voi611_interface

图 - 通讯硬件连接

  • UART格式:波特率 9600,8位数据位,无校验位,1位停止位。
  • INT(可选):语音芯片识别结果输出信号,当 REG 0x0B 设置为 0 时使用该引脚,否则不使用该引脚。INT信号的空闲状态为高电平,低电平表示 REG 0x0A 中当前有非零识别结果尚未读取,读取后恢复高电平(当前无识别结果)。
  • RST(可选):语音芯片复位引脚,低电平有效(推荐低脉冲宽度 > 1ms),外部需上拉处理。

VOI611 芯片所有 IO 逻辑电平为 0v / 3.3v。 如果您的 MCU IO 口逻辑电平为其他值,直接与芯片引脚相连时请务必加入电平转换电路。模组 A/B 板载了电平转换,4pin 串口可以支持 5V 逻辑电平。

3.2 串口数据帧格式

数据帧采用固定长度,固定标记位,小端方式发送(若有多字节数据,低字节在前),具体格式如下。

mcu_voi611_frame_3

  • STX 表示数据帧的起始标志,固定为 0xFEA5
  • LEN 表示有效载荷数据 PAYLOAD 的字节长度,固定为 0x0002
  • SEQ 表示数据帧序列号,范围 0 ~ 65535,每发送完一个消息自增 1。

(调试测试阶段语音芯片不检查 SEQ,但考虑到协议标准、问题诊断、后续升级和协议扩展等方面,建议自增处理。)

  • SYS 为发起方,表示发送的方向。
  • MSG 表示消息类型编号,具体含义见下文
  • PAYLOAD 表示本条数据帧所装载的消息,固定为 2 个字节,具体含义见下文
  • SUM 为校验和,将前面 D0 ~ D9 所有字节相加取低8位。

注意:连续写入/读取数据帧时,MCU发送给语音芯片数据帧之间的间隔需 100ms 以上。

3.2.1 写入寄存器

只需要一个步骤就可以写入寄存器值到语音芯片,主控 MCU 指定 REG 和 VAL 参数后,按照如下格式发送串口帧即可。

mcu_voi611_write

如需校验写入结果是否成功,可以按下面步骤读取寄存器值进行检查。语音芯片上电后载入默认的寄存器值,重启后需要重新配置,掉电不保存(除特殊说明外)。

3.2.2 读取寄存器

读取语音芯片当前寄存器的值,需要两个步骤。首先主控 MCU 将要读取的 REG 发送给语音芯片,按如下格式发出。

mcu_voi611_read_1

语音芯片收到上方消息后,会在 100ms 内通过串口消息回复该 REG 当前的 VAL,解析格式如下,此时完成读取操作。

mcu_voi611_read_2

若超时 150ms 未有回复,视为异常情况,可尝试重新发送读取请求,或另作分析。

mcu_voi611_example_read_reg

图 - 读取寄存器流程

读取过程可以参考上图。

3.2.3 语音芯片上电通知

语音芯片上电初始化成功后,延迟1秒,发出以下串口指令。

mcu_voi611_power_on

MCU收到本条串口指令后,可以进行寄存器的读写操作。

3.2.4 主动上报识别结果

当 REG 0x0B 设置为 1 时,语音芯片识别成功后会直接发出串口消息,识别结果不会存入 REG 0x0A。

这种方法适用于 MCU 不需要频繁读取语音芯片的场合,MCU 等待接收识别结果即可。

mcu_voi611_active_upload

INDEX:命令词索引值,在《方案规格书》的命令词表中查询。

关于“主动上报 / 不主动上报”、“主动播报 / 被动播报”、“唤醒逻辑”的关系在 8. 相关解释 中描述。

产品的《方案规格书》中有对于本数据帧有专门说明的,则以《方案规格书》中内容为准。


4. 寄存器


4.1 寄存器描述

4.1.1 [REG 0x00] CHIP_TYPE_L

CHIP_TYPE_低8位,为芯片类型,是一个固定返回值,可用于检查语音芯片是否上电初始化成功。

  • 默认值: 0x63
  • 允许读写: R

4.1.2 [REG 0x01] CHIP_TYPE_H

CHIP_TYPE_高8位,为芯片类型,是一个固定返回值,可用于检查语音芯片是否上电初始化成功。

  • 默认值: 0x02
  • 允许读写: R

4.1.3 [REG 0x04] 复位寄存器表

RESET,用于复位寄存器表,写入 0x01 使寄存器表中所有值恢复出厂默认设置,写入其他值无效。

  • 合法值: 0x01
  • 允许读写: W

4.1.4 [REG 0x05] 麦克风增益

MIC_GAIN,用于设定麦克风增益,保留,不要修改。

4.1.5 [REG 0x06] 音量调节

VOLUME_LEVEL,用于设置芯片DAC输出信号的音量等级,这是一个全局参数,数值越大声音越大。(写入后立刻生效)

  • 默认值: 0x19
  • 合法值(DEC): 0 表示静音;
  • 合法值(DEC): 1 ~ 31 数值越大声音越大;
  • 允许读写: R/W

请注意:电路板上可能搭载了后端的 PA 功放(例如模组B/M7),这部分元器件的放大系数不在本寄存器控制范围之内,通常是硬件参数决定。本寄存器仅影响语音芯片的DAC输出。

4.1.6 [REG 0x07] 播放提示音

立即播放索引号提示音,该寄存器值代表《方案规格书》提示音播报表中索引号,写入后立即停止正在播放的内容,并开始播放新索引号的提示音。开始播放后将索引号装载到 REG 0x08

  • 合法值(DEC): 0 ~ 255 提示音索引号;
  • 允许读写: W

MCU 可以在写入这个寄存器后,读取 REG 0x08 来确认语音芯片是否开始播放对应的提示音。

每次写入操作语音芯片只会播放 1 次,未包含在《方案规格书》提示音播报表的索引号将会忽略。

4.1.7 [REG 0x08] 当前提示音

当前正在进行播放的提示音索引号,该寄存器值代表《方案规格书》提示音播报表中索引号。

  • 合法值(DEC): 0 表示当前没有正在播放的内容(芯片 SPK 引脚无声音输出);
  • 合法值(DEC): 1 ~ 255 当前正在播放的提示音文件索引号;
  • 允许读写: R

4.1.8 [REG 0x09] 语音识别开关

该寄存器用于控制开始/停止语音识别,写入后立刻生效。(这是整个语音识别系统开/关,不是控制唤醒状态开/关)

  • 默认值: 0x01
  • 合法值: 0x01 表示语音芯片处于打开识别状态,识别成功后会产生识别结果;
  • 合法值: 0x00 表示语音芯片处于关闭识别状态,停止上报任何识别结果;
  • 允许读写: R/W

4.1.9 [REG 0x0A] 当前识别结果

该寄存器仅当 [REG 0x0B] 设置为 0x00 时可用,其表示当前的识别结果。

当语音芯片识别到《方案规格书》命令词列表中的某个词后,会将该词的索引号写入到本寄存器,并等待 MCU 读取。

  • 合法值(DEC): 0 表示当前无识别结果;
  • 合法值(DEC): 1-255 当前识别结果的词索引号(不支持非唤醒状态下识别非唤醒词);
  • 允许读写: R

当本寄存器值为非 0 时,语音芯片的 INT 引脚将输出低电平。进行读取操作完成后,本寄存器值自动复位为 0,且语音芯片的 INT 引脚输出低电平。

当有新的识别结果产生时,会覆盖之前未读取的内容。

4.1.10 [REG 0x0B] 主动上报开关

该寄存器用于设置当语音芯片识别到《方案规格书》命令词列表中的某个词后,如何将识别结果从语音芯片传递给主控 MCU。VOI611提供两种方式:主动上报、不主动上报(由MCU发起读取)。写入后立刻生效,并在下一个识别结果产生时得以体现。

  • 默认值: 0x01
  • 合法值: 0x01 主动上报,语音芯片识别完成后会直接发出串口消息,识别结果不会存入 REG 0x0A;(主动上报格式,参考 2.2.4 主动上报识别结果。不支持非唤醒状态下识别非唤醒词);
  • 合法值: 0x00 表示不主动上报,识别结果存入 REG 0x0A,用户必须从中读取识别结果;
  • 允许读写: R/W

关于“主动上报 / 不主动上报”、“主动播报 / 被动播报”、“唤醒逻辑”的关系在 8. 相关解释 中描述。

4.1.11 [REG 0x10] 默认唤醒时间_低8位

该寄存器用于存储默认的唤醒时间设定低 8 位。与 REG 0x11 构成默认唤醒时间(2 字节),范围 0x0000 ~ 0xffff 秒。

当“唤醒-事件”发生后,语音芯片装载默认唤醒时间到 REG 0x12:0x13。

  • 默认值(DEC): 20
  • 合法值(DEC): 0 ~ 255 默认的唤醒时间,单位为秒;
  • 允许读写: R/W

4.1.12 [REG 0x11] 默认唤醒时间_高8位

该寄存器用于存储默认的唤醒时间设定高 8 位。与 REG 0x10 构成默认唤醒时间(2 字节),范围 0x0000 ~ 0xffff 秒。

当“唤醒-事件”发生后,语音芯片装载默认唤醒时间到 REG 0x12:0x13。

  • 默认值(DEC): 0
  • 合法值(DEC): 0 ~ 255 默认的唤醒时间,单位为 256 秒;
  • 允许读写: R/W

4.1.13 [REG 0x12] 当前剩余唤醒时间_低8位

该寄存器用于存储当前剩余的唤醒时间值低 8 位。与 REG 0x13 构成当前剩余唤醒时间(2 字节),范围 0x0000 ~ 0xffff 秒。

当前剩余唤醒时间相当于一个倒计时器,会随时间递减,直至为 0 时退出唤醒(REG 0x14 被清零)。

  • 默认值(DEC): 0
  • 合法值(DEC): 0 ~ 255 剩余唤醒时间,单位为秒;
  • 允许读写: R

4.1.14 [REG 0x13] 当前剩余唤醒时间_高8位

该寄存器用于存储当前剩余的唤醒时间值高 8 位。与 REG 0x12 构成当前剩余唤醒时间(2 字节),范围 0x0000 ~ 0xffff 秒。

当前剩余唤醒时间相当于一个倒计时器,会随时间递减,直至为 0 时退出唤醒(REG 0x14 被清零)。

  • 默认值(DEC): 0
  • 合法值(DEC): 0 ~ 255 剩余唤醒时间,单位为 256 秒;
  • 允许读写: R

4.1.15 [REG 0x14] 唤醒状态

该寄存器用于表示当前语音芯片的唤醒状态,写入 0x00 至本寄存器,将立刻退出唤醒,并把 REG 0x12:0x13 清零;写入 0x01 至本寄存器,将立刻触发“唤醒-事件”(不论当前是处于非唤醒状态 or 唤醒状态),载入 REG 0x10:0x11 至 REG 0x12:0x13 并启动剩余唤醒时间的倒计时;

  • 默认值: 0x00
  • 合法值: 0x00,表示当前处于非唤醒状态;
  • 合法值: 0x01,表示当前处于唤醒状态;
  • 允许读写: R/W

(写入后立刻生效。)

关于“唤醒逻辑”的说明在 8. 相关解释 中描述。

4.1.16 [REG 0x15] 唤醒保持使能

该寄存器用于设定语音芯片是否通过唤醒倒计时来退出唤醒,如果打开该功能,语音芯片将长期保持唤醒状态。(写入后立刻生效,若当前处于非唤醒状态,则下一次进入唤醒时生效)

  • 默认值: 0x00
  • 合法值: 0x00,语音芯片通过 REG 0x12:0x13 超时来决定是否退出唤醒状态;
  • 合法值: 0x01,语音芯片一旦进入唤醒将不会不超时,不会主动退出唤醒状态(仅接收主控 MCU 指令退出唤醒);
  • 允许读写: R/W

若当前语音芯片已处于唤醒状态(REG 0x14 为 0x01),且本寄存器值为 0x01,此时写入 0x00 至本寄存器,会立即退出唤醒(REG 0x14 被清零)。

4.1.17 [REG 0x16] 允许通过唤醒词进入唤醒状态

该寄存器用于设定语音芯片是否通唤醒词来进入唤醒状态,如果关闭该功能,语音芯片将无法在识别到唤醒词后直接产生“唤醒-事件”(进入唤醒状态),只能通过外部 MCU 的指令进入唤醒。(写入后立刻生效。下一次识别到唤醒词后得以体现)

  • 默认值: 0x01
  • 合法值: 0x00,出现识别结果为唤醒词,语音芯片不会直接产生“唤醒-事件”(不会直接进入唤醒状态)。此模式下仅接收外部触发的“唤醒-事件”,用户可写入 REG 0x14 进入唤醒。(也就是说“唤醒-事件”完全由主控 MCU 控制);
  • 合法值: 0x01,出现识别结果为唤醒词,语音芯片将直接产生“唤醒-事件”(也可由主控 MCU 控制,两种方法共存);
  • 允许读写: R/W

4.1.18 [REG 0x17] 允许通过非唤醒词延长唤醒时间

语音芯片处于唤醒状态时,识别到命令词后,对于延长唤醒时间处理有常见的 3 种方式:

  • 【单轮对话】识别到命令词,将当前剩余唤醒时间清零,立即退出唤醒。
  • 【多轮对话-延长】识别到命令词,延长当前剩余唤醒时间(通常是重置唤醒倒计时)。
  • 【多轮对话-不延长】识别到命令词,不对唤醒时间进行操作。

本寄存器用于设定【多轮对话】方式下,识别到命令词后是否【延长】当前剩余唤醒时间(重置唤醒倒计时)。

  • 默认值: 0x01
  • 合法值: 0x00,出现识别结果为非唤醒词,语音芯片不会调整剩余唤醒时间,REG 0x12:0x13 维持原规则动作;
  • 合法值: 0x01,出现识别结果为非唤醒词,语音芯片将会将剩余唤醒时间 REG 0x12:0x13 延长至默认唤醒时间 REG 0x10:0x11(即重新唤醒计时);
  • 允许读写: R/W

4.1.19 [REG 0x20] 当前应用场景-索引号

该寄存器用于设置语音芯片的应用场景,写入正确的索引号将立即生效。若场景索引号不存在或无效,将写入失败且不会变更本寄存器的值。(写入后保存到 Flash,掉电不丢失)

用户可以在执行写入后,读取本寄存器的值进行检验。

  • 默认值: 详见《方案规格书》应用场景表
  • 合法值: 0x00,生产测试使用,保留;
  • 合法值: 应用场景索引号,用于标记《应用场景表》中指定的场景,详见《方案规格书》应用场景表;
  • 允许读写: R/W

4.1.20 [REG 0x21] 唤醒词1-索引号

通常《方案规格书》命令词列表列出了模型(weight_iet_upgrade.bin)中所有可以被识别的孤立词,这部分词可根据语音交互逻辑分为两类:

  • 【唤醒词】在非唤醒状态和唤醒状态下均可识别,识别后进入唤醒状态。
  • 【命令词】仅在唤醒状态下识别,在非唤醒状态下不会被识别。

该寄存器用于标记《方案规格书》命令词列表中【唤醒词 1】的索引号。当该寄存器值为非零时,语音芯片识别到《方案规格书》命令词列表中的某个词后,将该词索引号与本寄存器值进行比较,若相同则视为识别到【唤醒词 1】;若与 REG 0x21:0x23 均不相同,则视为【命令词】。

推荐在语音芯片上电后,初始配置阶段,将需要启用的【唤醒词】索引号填入 REG 0x21:0x23。

  • 默认值(DEC): 2
  • 合法值(DEC): 0,表示空,没有第 1 个唤醒词;
  • 合法值(DEC): 1 ~ 255,《方案规格书》命令词列表中的索引号;
  • 允许读写: R/W

4.1.21 [REG 0x22] 唤醒词2-索引号

该寄存器用于标记《方案规格书》命令词列表中【唤醒词 2】的索引号。当该寄存器值为非零时,语音芯片识别到《方案规格书》命令词列表中的某个词后,将该词索引号与本寄存器值进行比较,若相同则视为识别到【唤醒词 2】;若与 REG 0x21:0x23 均不相同,则视为【命令词】。

推荐在语音芯片上电后,初始配置阶段,将需要启用的【唤醒词】索引号填入 REG 0x21:0x23。

  • 默认值(DEC): 0
  • 合法值(DEC): 0,表示空,没有第 2 个唤醒词;
  • 合法值(DEC): 1 ~ 255,《方案规格书》命令词列表中的索引号;
  • 允许读写: R/W

4.1.22 [REG 0x23] 唤醒词3-索引号

该寄存器用于标记《方案规格书》命令词列表中【唤醒词 3】的索引号。当该寄存器值为非零时,语音芯片识别到《方案规格书》命令词列表中的某个词后,将该词索引号与本寄存器值进行比较,若相同则视为识别到【唤醒词 3】;若与 REG 0x21:0x23 均不相同,则视为【命令词】。

推荐在语音芯片上电后,初始配置阶段,将需要启用的【唤醒词】索引号填入 REG 0x21:0x23。

  • 默认值(DEC): 0
  • 合法值(DEC): 0,表示空,没有第 3 个唤醒词;
  • 合法值(DEC): 1 ~ 255,《方案规格书》命令词列表中的索引号;
  • 允许读写: R/W


5. 寄存器调试工具(上位机)


开发者可以直接在图形界面,控制VOI611芯片。

voi611_reg_tool_main_window

图 - voi611_reg_tool 主界面

点击这里下载:reg_tool_ver2.1_20210408.exe

使用方法:

  1. 将语音模块通过串口连接到 pc,检查 com 端口号。
  2. 启动 voi611_reg_tool 软件,选择端口号,波特率设置为 9600(默认),点击“打开串口”。
  3. 点击界面右侧“读取全部”按钮,观察读出寄存器值。
  4. 点击界面下方的播放提示音按钮“1”,观察语音模块是否正常播报。

常见错误:

  • 工具无法启动:建议在 Windows 10 64bit 系统上运行。
  • 无法打开端口:调试工具无法访问串口设备,可能是 com 端口号设置错误,或者有其他程序占用了该端口。
  • 读取 / 写入失败:可能是串口的 tx / rx 连接错误,或芯片固件不支持寄存器协议,或电源异常。


6. 典型应用流程


6.1 识别-播报(INT信号、不主动上报)

具体过程如下图所示:

mcu_voi611_example_1

本流程需要使用 INT 引脚,可以不使用 MCU 串口中断功能。主控 MCU 周期性查询 INT 引脚电平信号,当有识别结果产生时,MCU 发起查询 REG 指令获取当前识别结果,并按产品功能逻辑将要播放的提示音写入到 VOI611 中,依次完成识别-播报的语音交互。

6.2 识别-播报(无INT信号、轮询心跳)

本流程省略了对 INT 引脚的判断,主控 MCU 周期性读取 REG 0x0A 的值,非零代表识别结果 ID,为零则表示无识别结果,两种回复都被认为读取操作成功(其他回复或无回复被视为异常)。

具体过程如下图所示:

mcu_voi611_example_2

心跳包是指将自己的状态通知对方,表示自己处于正常工作状态。考虑到产片端主控 MCU 对心跳周期和状态数据类目的多样性,语音芯片的心跳包实现方式为:主控 MCU 对语音芯片的读操作,若读取成功,则说明语音芯片当前系统处于正常运行状态。

对于读取语音芯片操作的多次失败(尽管概率很低,但不排除一些外部原因),主控 MCU 可以通过 RST 引脚传递复位信号,控制语音芯片重启。


7. 示例程序


7.1 十分钟快速上手

如下是读写操作简单示例。

static uint16_t seq = 0;

uint8_t voi611_reg_write(uint8_t reg, uint8_t val, uint8_t msg)
{
    // 1. 准备发送的数据帧
    uint8_t buf[11] = {0}
    buf[0] = 0xA5;                            // STX
    buf[1] = 0xFE;                            // STX
    buf[2] = 0x02;                            // LEN
    buf[3] = 0x00;                            // LEN
    buf[4] = (uint8_t)(0x00ff & seq);         // SEQ
    buf[5] = (uint8_t)(0x00ff & (seq >> 8));  // SEQ
    buf[6] = 0x01;                            // SYS
    buf[7] = msg;                             // MSG
    buf[8] = reg;                             // REG
    buf[9] = val;                             // VAL

    uint8_t i, sum = 0;
    for(i = 0; i < 10; i++)
    {
        sum += buf[i];
    }
    buf[10] = sum;                            // SUM

    seq++;                                    // SEQ 自增

    // 2. 以下为 MCU 串口发送 api
    uint8_t ret = uart_write(buf, 11);

    return ret;
}

uint8_t voi611_reg_read(uint8_t reg, uint8_t *val)
{
    // 1. 先发送读取 REG 指令
    voi611_reg_write(reg, 0x00, 0xF1);

    // 2. 以下为等待 VOI611 回复(阻塞式),或开发者自行实现接收,通过 3. 进行解析
    uint8_t ret, val;
    uint8_t buf[11];
    uint32_t timeout_ms = 150;
    ret = uart_read_with_timeout(buf, 11, timeout_ms);

    // 2.1 读取 11 个字节超时,失败退出
    if (ret == 0x00)
    {
        return 0x00;
    }

    // 3. 读取成功,校验和解析
    if(buf[0] == 0xA5 && buf[1] == 0xFE &&            // STX
       buf[2] == 0x02 && buf[3] == 0x00 &&            // LEN
       buf[6] == 0x00 && buf[7] == 0xFF &&            // SYS, MSG
       buf[8] == reg)                                 // REG
    {
        // 3.1 检查校验和
        uint8_t i, sum = 0;
        for(i = 0; i < 10; i++)
        {
            sum += buf[i];
        }

        if (buf[10] == sum)
        {
            // 校验和正确,返回结果
            *val = buf[9];                            // VAL
            return 0x01;
        }

        // 校验和错误
    }

    // 非法帧
    return 0x00;
}


典型应用代码(最小化)如下。

uint8_t voi611_init_reg()
{
    uint8_t ret, val;

    // 1. 先检查连接是否正常
    ret = voi611_reg_read(0x00, &val);
    if (ret != 0x00 && val == 0x63)
    {
        ; // 读取型号 OK
    }
    else
    {
        return 0x00; // 读取型号失败,可能是硬件连接错误或者型号不对
    }

    ret = voi611_reg_read(0x01, &val);
    if (ret != 0x00 && val == 0x02)
    {
        ; // 读取型号 OK
    }
    else
    {
        return 0x00; // 读取型号失败,可能是硬件连接错误或者型号不对
    }

    // 2. 写入需要配置的寄存器和值
    voi611_reg_write(0x04, 0x01, 0xF0);  // 复位寄存器表
    voi611_reg_write(0x0B, 0x00, 0xF0);  // 设置为识别结果不主动上报,MCU 自行查询
    voi611_reg_write(0x20, 0x05, 0xF0);  // 设置选择应用场景索引号

    voi611_reg_write(0x07, 0x01, 0xF0);  // 播放上电欢迎语的提示音

    // 3. 读取并校验写入成功
    // ……

    return 0x01;
}


void main()
{
    uint8_t ret, val;

    // 1. 初始化VOI611的寄存器
    voi611_init_reg();

    // 2. 主循环
    while(1)
    {
        // 每隔 200ms,读取识别结果,0表示当前无识别结果
        ret = voi611_reg_read(0x0A, &val);

        if (ret == 0x00 || val == 0x00)
        {
            // 超时或者无识别结果,本次查询无语音动作
            // continue;
        }
        else
        {
            switch(val)
            {
                case (1):
                    // 打开灯光
                    app_light_on();
                    // 播放提示音:开灯
                    voi611_reg_write(0x07, 0x03, 0xF0);
                    break;

                case (2):
                    // 关闭灯光
                    app_light_off();
                    // 播放提示音:关灯
                    voi611_reg_write(0x07, 0x04, 0xF0);
                    break;

                case (3):
                case (4):
                    // 屏蔽这些命令词3和4,不响应识别结果
                    break;

                default:
                    // 屏蔽其他的识别结果
                    break;
            }
        }

        // 其他程序
        // ...
    }
}


8. 相关解释


关于“主动上报 / 不主动上报”、“主动播报 / 被动播报”、“唤醒逻辑”的关系:

“主动上报 / 不主动上报”与“唤醒逻辑”并无关联,这两种方式仅区别于如何将识别结果从语音芯片传递给主控 MCU。

“主动上报 / 不主动上报”的设定与“主动播报 / 被动播报”并无关联,播报方式仅代表语音芯片完成识别后是直接播放提示音(主动),还是由MCU控制播放提示音(被动),通常在应用场景号中进行选择。(一般来说,不主动上报识别结果时,识别-播报的交互逻辑也是交由MCU处理,此时语音模块应选择为被动播报)

关于“唤醒逻辑”的说明:

通常情况下语音芯片应用的唤醒逻辑有两种状态:

  • 非唤醒状态(仅监听唤醒词)
  • 唤醒状态(监听唤醒词、命令词)

其中,从非唤醒状态进入唤醒状态,称之为“唤醒-事件”,“唤醒-事件”只能通过 2 种方式产生:任何情况下 MCU 写入 1 至 REG 0x14;或者语音芯片识别到在 REG 0x21:0x23 标记为唤醒词的命令词 ID,且 REG 0x16 设置为 1。

唤醒逻辑的设定,是为了减少误操作的发生。例如语音智能灯产品,默认(非唤醒状态)仅监听唤醒词“你好小白”,进入唤醒状态后可以识别其他命令词“打开灯光、调亮一点”等等。

如果在非唤醒状态下识别《命令词列表》中所有的词汇并执行动作,那么会使误操作的概率上升,造成用户困扰(现阶段语音识别无法杜绝误识别,但可以通过此方法减小概率)。

通常,除在 REG 0x21:0x23 中被标记为唤醒词的命令词以外,剩余《命令词列表》的词均为非唤醒词。