MCU開發(fā)接入VOI611指南

本文主要描述了MCU接入VOI611方案的開發(fā)流程,適用于嵌入式開發(fā)工程師及個人開發(fā)者快速入門,了解接入VOI611方案的方法。


1. 方案概述


MCU接入VOI611是快速實現(xiàn)產(chǎn)品語音智能化的常用方法,適用于已內(nèi)置MCU主控的產(chǎn)品。

例如空調(diào)、洗衣機等大、小家電產(chǎn)品,自身MCU已具備復(fù)雜的外設(shè)控制和邏輯,接入VOI611串口協(xié)議即可實現(xiàn)語音交互功能,您只需要關(guān)注產(chǎn)品功能和語音交互(對話)的設(shè)計,復(fù)雜的語音算法和模型訓(xùn)練交由探境科技處理。

mcu_voi611_top_view

圖 - VOI611作為外部輸入輸出設(shè)備

如上圖所示,藍(lán)色部分的VOI611可作為一個外部輸入輸出設(shè)備,主要具備以下兩個功能:

  • 通過 MIC 輸入(語音識別結(jié)果等)
  • 通過 SPK 輸出(提示音等)

在本方案中,語音芯片內(nèi)置寄存器表,產(chǎn)品主控MCU通過UART對VOI611的寄存器表進(jìn)行配置,無需修改VOI611片內(nèi)的軟件代碼,從而實現(xiàn)芯片的參數(shù)設(shè)定。

通常,語音芯片VOI611不維護(hù)產(chǎn)品狀態(tài)(例如電機、燈光等電控設(shè)備由產(chǎn)品主控MCU維護(hù),如上圖綠色部分),這種方式使得VOI611更專注的處理語音的識別/播報,無需針對要實現(xiàn)的產(chǎn)品應(yīng)用(例如空調(diào)、洗衣機邏輯功能)進(jìn)行定制化開發(fā),縮短了開發(fā)周期和聯(lián)調(diào)成本。

同時,主控MCU可以自主定制語音交互的方案,能與產(chǎn)品自身功能結(jié)合的更好,標(biāo)準(zhǔn)化接入方式避免來回修改語音芯片固件和協(xié)議,提升庫存通用性,減小生產(chǎn)和庫存管控成本,便于安裝和使用。

VOI611內(nèi)置寄存器表涵蓋了:設(shè)定喚醒時間、設(shè)定喚醒詞、設(shè)定播放音量、播放指定的提示音、讀取當(dāng)前識別結(jié)果、喚醒狀態(tài)等語音交互相關(guān)的配置參數(shù)。產(chǎn)品完整的語音交互方案設(shè)計均可由MCU進(jìn)行設(shè)定,配合示例代碼、寄存器表格、PC端調(diào)試工具,您可以快速出開發(fā)定制化的語音交互需求。

(如若不滿足您的需求,可以將您的需求提交給探境銷售或者技術(shù)支持人員)


2. 開發(fā)流程


常見的開發(fā)流程主要包括:獲取VOI611硬件和固件、調(diào)試工具驗證、MCU軟件開發(fā)、聯(lián)調(diào)對接等步驟。

mcu_voi611_flow

圖 - 開發(fā)流程說明


3. 通訊接口和協(xié)議


3.1 通訊硬件連接

MCU通過下圖的方式和VOI611進(jìn)行連接:

mcu_voi611_interface

圖 - 通訊硬件連接

  • UART格式:波特率 9600,8位數(shù)據(jù)位,無校驗位,1位停止位。
  • INT(可選):語音芯片識別結(jié)果輸出信號,當(dāng) REG 0x0B 設(shè)置為 0 時使用該引腳,否則不使用該引腳。INT信號的空閑狀態(tài)為高電平,低電平表示 REG 0x0A 中當(dāng)前有非零識別結(jié)果尚未讀取,讀取后恢復(fù)高電平(當(dāng)前無識別結(jié)果)。
  • RST(可選):語音芯片復(fù)位引腳,低電平有效(推薦低脈沖寬度 > 1ms),外部需上拉處理。

VOI611 芯片所有 IO 邏輯電平為 0v / 3.3v。 如果您的 MCU IO 口邏輯電平為其他值,直接與芯片引腳相連時請務(wù)必加入電平轉(zhuǎn)換電路。模組 A/B 板載了電平轉(zhuǎn)換,4pin 串口可以支持 5V 邏輯電平。

3.2 串口數(shù)據(jù)幀格式

數(shù)據(jù)幀采用固定長度,固定標(biāo)記位,小端方式發(fā)送(若有多字節(jié)數(shù)據(jù),低字節(jié)在前),具體格式如下。

mcu_voi611_frame_3

  • STX 表示數(shù)據(jù)幀的起始標(biāo)志,固定為 0xFEA5。
  • LEN 表示有效載荷數(shù)據(jù) PAYLOAD 的字節(jié)長度,固定為 0x0002
  • SEQ 表示數(shù)據(jù)幀序列號,范圍 0 ~ 65535,每發(fā)送完一個消息自增 1。

(調(diào)試測試階段語音芯片不檢查 SEQ,但考慮到協(xié)議標(biāo)準(zhǔn)、問題診斷、后續(xù)升級和協(xié)議擴展等方面,建議自增處理。)

  • SYS 為發(fā)起方,表示發(fā)送的方向。
  • MSG 表示消息類型編號,具體含義見下文。
  • PAYLOAD 表示本條數(shù)據(jù)幀所裝載的消息,固定為 2 個字節(jié),具體含義見下文
  • SUM 為校驗和,將前面 D0 ~ D9 所有字節(jié)相加取低8位。

注意:連續(xù)寫入/讀取數(shù)據(jù)幀時,MCU發(fā)送給語音芯片數(shù)據(jù)幀之間的間隔需 100ms 以上。

3.2.1 寫入寄存器

只需要一個步驟就可以寫入寄存器值到語音芯片,主控 MCU 指定 REG 和 VAL 參數(shù)后,按照如下格式發(fā)送串口幀即可。

mcu_voi611_write

如需校驗寫入結(jié)果是否成功,可以按下面步驟讀取寄存器值進(jìn)行檢查。語音芯片上電后載入默認(rèn)的寄存器值,重啟后需要重新配置,掉電不保存(除特殊說明外)。

3.2.2 讀取寄存器

讀取語音芯片當(dāng)前寄存器的值,需要兩個步驟。首先主控 MCU 將要讀取的 REG 發(fā)送給語音芯片,按如下格式發(fā)出。

mcu_voi611_read_1

語音芯片收到上方消息后,會在 100ms 內(nèi)通過串口消息回復(fù)該 REG 當(dāng)前的 VAL,解析格式如下,此時完成讀取操作。

mcu_voi611_read_2

若超時 150ms 未有回復(fù),視為異常情況,可嘗試重新發(fā)送讀取請求,或另作分析。

mcu_voi611_example_read_reg

圖 - 讀取寄存器流程

讀取過程可以參考上圖。

3.2.3 語音芯片上電通知

語音芯片上電初始化成功后,延遲1秒,發(fā)出以下串口指令。

mcu_voi611_power_on

MCU收到本條串口指令后,可以進(jìn)行寄存器的讀寫操作。

3.2.4 主動上報識別結(jié)果

當(dāng) REG 0x0B 設(shè)置為 1 時,語音芯片識別成功后會直接發(fā)出串口消息,識別結(jié)果不會存入 REG 0x0A。

這種方法適用于 MCU 不需要頻繁讀取語音芯片的場合,MCU 等待接收識別結(jié)果即可。

mcu_voi611_active_upload

INDEX:命令詞索引值,在《方案規(guī)格書》的命令詞表中查詢。

關(guān)于“主動上報 / 不主動上報”、“主動播報 / 被動播報”、“喚醒邏輯”的關(guān)系在 8. 相關(guān)解釋 中描述。

產(chǎn)品的《方案規(guī)格書》中有對于本數(shù)據(jù)幀有專門說明的,則以《方案規(guī)格書》中內(nèi)容為準(zhǔn)。


4. 寄存器


4.1 寄存器描述

4.1.1 [REG 0x00] CHIP_TYPE_L

CHIP_TYPE_低8位,為芯片類型,是一個固定返回值,可用于檢查語音芯片是否上電初始化成功。

  • 默認(rèn)值: 0x63
  • 允許讀寫: R

4.1.2 [REG 0x01] CHIP_TYPE_H

CHIP_TYPE_高8位,為芯片類型,是一個固定返回值,可用于檢查語音芯片是否上電初始化成功。

  • 默認(rèn)值: 0x02
  • 允許讀寫: R

4.1.3 [REG 0x04] 復(fù)位寄存器表

RESET,用于復(fù)位寄存器表,寫入 0x01 使寄存器表中所有值恢復(fù)出廠默認(rèn)設(shè)置,寫入其他值無效。

  • 合法值: 0x01
  • 允許讀寫: W

4.1.4 [REG 0x05] 麥克風(fēng)增益

MIC_GAIN,用于設(shè)定麥克風(fēng)增益,保留,不要修改。

4.1.5 [REG 0x06] 音量調(diào)節(jié)

VOLUME_LEVEL,用于設(shè)置芯片DAC輸出信號的音量等級,這是一個全局參數(shù),數(shù)值越大聲音越大。(寫入后立刻生效)

  • 默認(rèn)值: 0x19
  • 合法值(DEC): 0 表示靜音;
  • 合法值(DEC): 1 ~ 31 數(shù)值越大聲音越大;
  • 允許讀寫: R/W

請注意:電路板上可能搭載了后端的 PA 功放(例如模組B/M7),這部分元器件的放大系數(shù)不在本寄存器控制范圍之內(nèi),通常是硬件參數(shù)決定。本寄存器僅影響語音芯片的DAC輸出。

4.1.6 [REG 0x07] 播放提示音

立即播放索引號提示音,該寄存器值代表《方案規(guī)格書》提示音播報表中索引號,寫入后立即停止正在播放的內(nèi)容,并開始播放新索引號的提示音。開始播放后將索引號裝載到 REG 0x08。

  • 合法值(DEC): 0 ~ 255 提示音索引號;
  • 允許讀寫: W

MCU 可以在寫入這個寄存器后,讀取 REG 0x08 來確認(rèn)語音芯片是否開始播放對應(yīng)的提示音。

每次寫入操作語音芯片只會播放 1 次,未包含在《方案規(guī)格書》提示音播報表的索引號將會忽略。

4.1.7 [REG 0x08] 當(dāng)前提示音

當(dāng)前正在進(jìn)行播放的提示音索引號,該寄存器值代表《方案規(guī)格書》提示音播報表中索引號。

  • 合法值(DEC): 0 表示當(dāng)前沒有正在播放的內(nèi)容(芯片 SPK 引腳無聲音輸出);
  • 合法值(DEC): 1 ~ 255 當(dāng)前正在播放的提示音文件索引號;
  • 允許讀寫: R

4.1.8 [REG 0x09] 語音識別開關(guān)

該寄存器用于控制開始/停止語音識別,寫入后立刻生效。(這是整個語音識別系統(tǒng)開/關(guān),不是控制喚醒狀態(tài)開/關(guān))

  • 默認(rèn)值: 0x01
  • 合法值: 0x01 表示語音芯片處于打開識別狀態(tài),識別成功后會產(chǎn)生識別結(jié)果;
  • 合法值: 0x00 表示語音芯片處于關(guān)閉識別狀態(tài),停止上報任何識別結(jié)果;
  • 允許讀寫: R/W

4.1.9 [REG 0x0A] 當(dāng)前識別結(jié)果

該寄存器僅當(dāng) [REG 0x0B] 設(shè)置為 0x00 時可用,其表示當(dāng)前的識別結(jié)果。

當(dāng)語音芯片識別到《方案規(guī)格書》命令詞列表中的某個詞后,會將該詞的索引號寫入到本寄存器,并等待 MCU 讀取。

  • 合法值(DEC): 0 表示當(dāng)前無識別結(jié)果;
  • 合法值(DEC): 1-255 當(dāng)前識別結(jié)果的詞索引號(不支持非喚醒狀態(tài)下識別非喚醒詞);
  • 允許讀寫: R

當(dāng)本寄存器值為非 0 時,語音芯片的 INT 引腳將輸出低電平。進(jìn)行讀取操作完成后,本寄存器值自動復(fù)位為 0,且語音芯片的 INT 引腳輸出低電平。

當(dāng)有新的識別結(jié)果產(chǎn)生時,會覆蓋之前未讀取的內(nèi)容。

4.1.10 [REG 0x0B] 主動上報開關(guān)

該寄存器用于設(shè)置當(dāng)語音芯片識別到《方案規(guī)格書》命令詞列表中的某個詞后,如何將識別結(jié)果從語音芯片傳遞給主控 MCU。VOI611提供兩種方式:主動上報、不主動上報(由MCU發(fā)起讀?。?。寫入后立刻生效,并在下一個識別結(jié)果產(chǎn)生時得以體現(xiàn)。

  • 默認(rèn)值: 0x01
  • 合法值: 0x01 主動上報,語音芯片識別完成后會直接發(fā)出串口消息,識別結(jié)果不會存入 REG 0x0A;(主動上報格式,參考 2.2.4 主動上報識別結(jié)果。不支持非喚醒狀態(tài)下識別非喚醒詞);
  • 合法值: 0x00 表示不主動上報,識別結(jié)果存入 REG 0x0A,用戶必須從中讀取識別結(jié)果;
  • 允許讀寫: R/W

關(guān)于“主動上報 / 不主動上報”、“主動播報 / 被動播報”、“喚醒邏輯”的關(guān)系在 8. 相關(guān)解釋 中描述。

4.1.11 [REG 0x10] 默認(rèn)喚醒時間_低8位

該寄存器用于存儲默認(rèn)的喚醒時間設(shè)定低 8 位。與 REG 0x11 構(gòu)成默認(rèn)喚醒時間(2 字節(jié)),范圍 0x0000 ~ 0xffff 秒。

當(dāng)“喚醒-事件”發(fā)生后,語音芯片裝載默認(rèn)喚醒時間到 REG 0x12:0x13。

  • 默認(rèn)值(DEC): 20
  • 合法值(DEC): 0 ~ 255 默認(rèn)的喚醒時間,單位為秒;
  • 允許讀寫: R/W

4.1.12 [REG 0x11] 默認(rèn)喚醒時間_高8位

該寄存器用于存儲默認(rèn)的喚醒時間設(shè)定高 8 位。與 REG 0x10 構(gòu)成默認(rèn)喚醒時間(2 字節(jié)),范圍 0x0000 ~ 0xffff 秒。

當(dāng)“喚醒-事件”發(fā)生后,語音芯片裝載默認(rèn)喚醒時間到 REG 0x12:0x13。

  • 默認(rèn)值(DEC): 0
  • 合法值(DEC): 0 ~ 255 默認(rèn)的喚醒時間,單位為 256 秒;
  • 允許讀寫: R/W

4.1.13 [REG 0x12] 當(dāng)前剩余喚醒時間_低8位

該寄存器用于存儲當(dāng)前剩余的喚醒時間值低 8 位。與 REG 0x13 構(gòu)成當(dāng)前剩余喚醒時間(2 字節(jié)),范圍 0x0000 ~ 0xffff 秒。

當(dāng)前剩余喚醒時間相當(dāng)于一個倒計時器,會隨時間遞減,直至為 0 時退出喚醒(REG 0x14 被清零)。

  • 默認(rèn)值(DEC): 0
  • 合法值(DEC): 0 ~ 255 剩余喚醒時間,單位為秒;
  • 允許讀寫: R

4.1.14 [REG 0x13] 當(dāng)前剩余喚醒時間_高8位

該寄存器用于存儲當(dāng)前剩余的喚醒時間值高 8 位。與 REG 0x12 構(gòu)成當(dāng)前剩余喚醒時間(2 字節(jié)),范圍 0x0000 ~ 0xffff 秒。

當(dāng)前剩余喚醒時間相當(dāng)于一個倒計時器,會隨時間遞減,直至為 0 時退出喚醒(REG 0x14 被清零)。

  • 默認(rèn)值(DEC): 0
  • 合法值(DEC): 0 ~ 255 剩余喚醒時間,單位為 256 秒;
  • 允許讀寫: R

4.1.15 [REG 0x14] 喚醒狀態(tài)

該寄存器用于表示當(dāng)前語音芯片的喚醒狀態(tài),寫入 0x00 至本寄存器,將立刻退出喚醒,并把 REG 0x12:0x13 清零;寫入 0x01 至本寄存器,將立刻觸發(fā)“喚醒-事件”(不論當(dāng)前是處于非喚醒狀態(tài) or 喚醒狀態(tài)),載入 REG 0x10:0x11 至 REG 0x12:0x13 并啟動剩余喚醒時間的倒計時;

  • 默認(rèn)值: 0x00
  • 合法值: 0x00,表示當(dāng)前處于非喚醒狀態(tài);
  • 合法值: 0x01,表示當(dāng)前處于喚醒狀態(tài);
  • 允許讀寫: R/W

(寫入后立刻生效。)

關(guān)于“喚醒邏輯”的說明在 8. 相關(guān)解釋 中描述。

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

該寄存器用于設(shè)定語音芯片是否通過喚醒倒計時來退出喚醒,如果打開該功能,語音芯片將長期保持喚醒狀態(tài)。(寫入后立刻生效,若當(dāng)前處于非喚醒狀態(tài),則下一次進(jìn)入喚醒時生效)

  • 默認(rèn)值: 0x00
  • 合法值: 0x00,語音芯片通過 REG 0x12:0x13 超時來決定是否退出喚醒狀態(tài);
  • 合法值: 0x01,語音芯片一旦進(jìn)入喚醒將不會不超時,不會主動退出喚醒狀態(tài)(僅接收主控 MCU 指令退出喚醒);
  • 允許讀寫: R/W

若當(dāng)前語音芯片已處于喚醒狀態(tài)(REG 0x14 為 0x01),且本寄存器值為 0x01,此時寫入 0x00 至本寄存器,會立即退出喚醒(REG 0x14 被清零)。

4.1.17 [REG 0x16] 允許通過喚醒詞進(jìn)入喚醒狀態(tài)

該寄存器用于設(shè)定語音芯片是否通喚醒詞來進(jìn)入喚醒狀態(tài),如果關(guān)閉該功能,語音芯片將無法在識別到喚醒詞后直接產(chǎn)生“喚醒-事件”(進(jìn)入喚醒狀態(tài)),只能通過外部 MCU 的指令進(jìn)入喚醒。(寫入后立刻生效。下一次識別到喚醒詞后得以體現(xiàn))

  • 默認(rèn)值: 0x01
  • 合法值: 0x00,出現(xiàn)識別結(jié)果為喚醒詞,語音芯片不會直接產(chǎn)生“喚醒-事件”(不會直接進(jìn)入喚醒狀態(tài))。此模式下僅接收外部觸發(fā)的“喚醒-事件”,用戶可寫入 REG 0x14 進(jìn)入喚醒。(也就是說“喚醒-事件”完全由主控 MCU 控制);
  • 合法值: 0x01,出現(xiàn)識別結(jié)果為喚醒詞,語音芯片將直接產(chǎn)生“喚醒-事件”(也可由主控 MCU 控制,兩種方法共存);
  • 允許讀寫: R/W

4.1.18 [REG 0x17] 允許通過非喚醒詞延長喚醒時間

語音芯片處于喚醒狀態(tài)時,識別到命令詞后,對于延長喚醒時間處理有常見的 3 種方式:

  • 【單輪對話】識別到命令詞,將當(dāng)前剩余喚醒時間清零,立即退出喚醒。
  • 【多輪對話-延長】識別到命令詞,延長當(dāng)前剩余喚醒時間(通常是重置喚醒倒計時)。
  • 【多輪對話-不延長】識別到命令詞,不對喚醒時間進(jìn)行操作。

本寄存器用于設(shè)定【多輪對話】方式下,識別到命令詞后是否【延長】當(dāng)前剩余喚醒時間(重置喚醒倒計時)。

  • 默認(rèn)值: 0x01
  • 合法值: 0x00,出現(xiàn)識別結(jié)果為非喚醒詞,語音芯片不會調(diào)整剩余喚醒時間,REG 0x12:0x13 維持原規(guī)則動作;
  • 合法值: 0x01,出現(xiàn)識別結(jié)果為非喚醒詞,語音芯片將會將剩余喚醒時間 REG 0x12:0x13 延長至默認(rèn)喚醒時間 REG 0x10:0x11(即重新喚醒計時);
  • 允許讀寫: R/W

4.1.19 [REG 0x20] 當(dāng)前應(yīng)用場景-索引號

該寄存器用于設(shè)置語音芯片的應(yīng)用場景,寫入正確的索引號將立即生效。若場景索引號不存在或無效,將寫入失敗且不會變更本寄存器的值。(寫入后保存到 Flash,掉電不丟失)

用戶可以在執(zhí)行寫入后,讀取本寄存器的值進(jìn)行檢驗。

  • 默認(rèn)值: 詳見《方案規(guī)格書》應(yīng)用場景表
  • 合法值: 0x00,生產(chǎn)測試使用,保留;
  • 合法值: 應(yīng)用場景索引號,用于標(biāo)記《應(yīng)用場景表》中指定的場景,詳見《方案規(guī)格書》應(yīng)用場景表;
  • 允許讀寫: R/W

4.1.20 [REG 0x21] 喚醒詞1-索引號

通常《方案規(guī)格書》命令詞列表列出了模型(weight_iet_upgrade.bin)中所有可以被識別的孤立詞,這部分詞可根據(jù)語音交互邏輯分為兩類:

  • 【喚醒詞】在非喚醒狀態(tài)和喚醒狀態(tài)下均可識別,識別后進(jìn)入喚醒狀態(tài)。
  • 【命令詞】僅在喚醒狀態(tài)下識別,在非喚醒狀態(tài)下不會被識別。

該寄存器用于標(biāo)記《方案規(guī)格書》命令詞列表中【喚醒詞 1】的索引號。當(dāng)該寄存器值為非零時,語音芯片識別到《方案規(guī)格書》命令詞列表中的某個詞后,將該詞索引號與本寄存器值進(jìn)行比較,若相同則視為識別到【喚醒詞 1】;若與 REG 0x21:0x23 均不相同,則視為【命令詞】。

推薦在語音芯片上電后,初始配置階段,將需要啟用的【喚醒詞】索引號填入 REG 0x21:0x23。

  • 默認(rèn)值(DEC): 2
  • 合法值(DEC): 0,表示空,沒有第 1 個喚醒詞;
  • 合法值(DEC): 1 ~ 255,《方案規(guī)格書》命令詞列表中的索引號;
  • 允許讀寫: R/W

4.1.21 [REG 0x22] 喚醒詞2-索引號

該寄存器用于標(biāo)記《方案規(guī)格書》命令詞列表中【喚醒詞 2】的索引號。當(dāng)該寄存器值為非零時,語音芯片識別到《方案規(guī)格書》命令詞列表中的某個詞后,將該詞索引號與本寄存器值進(jìn)行比較,若相同則視為識別到【喚醒詞 2】;若與 REG 0x21:0x23 均不相同,則視為【命令詞】。

推薦在語音芯片上電后,初始配置階段,將需要啟用的【喚醒詞】索引號填入 REG 0x21:0x23。

  • 默認(rèn)值(DEC): 0
  • 合法值(DEC): 0,表示空,沒有第 2 個喚醒詞;
  • 合法值(DEC): 1 ~ 255,《方案規(guī)格書》命令詞列表中的索引號;
  • 允許讀寫: R/W

4.1.22 [REG 0x23] 喚醒詞3-索引號

該寄存器用于標(biāo)記《方案規(guī)格書》命令詞列表中【喚醒詞 3】的索引號。當(dāng)該寄存器值為非零時,語音芯片識別到《方案規(guī)格書》命令詞列表中的某個詞后,將該詞索引號與本寄存器值進(jìn)行比較,若相同則視為識別到【喚醒詞 3】;若與 REG 0x21:0x23 均不相同,則視為【命令詞】。

推薦在語音芯片上電后,初始配置階段,將需要啟用的【喚醒詞】索引號填入 REG 0x21:0x23。

  • 默認(rèn)值(DEC): 0
  • 合法值(DEC): 0,表示空,沒有第 3 個喚醒詞;
  • 合法值(DEC): 1 ~ 255,《方案規(guī)格書》命令詞列表中的索引號;
  • 允許讀寫: R/W


5. 寄存器調(diào)試工具(上位機)


開發(fā)者可以直接在圖形界面,控制VOI611芯片。

voi611_reg_tool_main_window

圖 - voi611_reg_tool 主界面

點擊這里下載:reg_tool_ver2.1_20210408.exe

使用方法:

  1. 將語音模塊通過串口連接到 pc,檢查 com 端口號。
  2. 啟動 voi611_reg_tool 軟件,選擇端口號,波特率設(shè)置為 9600(默認(rèn)),點擊“打開串口”。
  3. 點擊界面右側(cè)“讀取全部”按鈕,觀察讀出寄存器值。
  4. 點擊界面下方的播放提示音按鈕“1”,觀察語音模塊是否正常播報。

常見錯誤:

  • 工具無法啟動:建議在 Windows 10 64bit 系統(tǒng)上運行。
  • 無法打開端口:調(diào)試工具無法訪問串口設(shè)備,可能是 com 端口號設(shè)置錯誤,或者有其他程序占用了該端口。
  • 讀取 / 寫入失敗:可能是串口的 tx / rx 連接錯誤,或芯片固件不支持寄存器協(xié)議,或電源異常。


6. 典型應(yīng)用流程


6.1 識別-播報(INT信號、不主動上報)

具體過程如下圖所示:

mcu_voi611_example_1

本流程需要使用 INT 引腳,可以不使用 MCU 串口中斷功能。主控 MCU 周期性查詢 INT 引腳電平信號,當(dāng)有識別結(jié)果產(chǎn)生時,MCU 發(fā)起查詢 REG 指令獲取當(dāng)前識別結(jié)果,并按產(chǎn)品功能邏輯將要播放的提示音寫入到 VOI611 中,依次完成識別-播報的語音交互。

6.2 識別-播報(無INT信號、輪詢心跳)

本流程省略了對 INT 引腳的判斷,主控 MCU 周期性讀取 REG 0x0A 的值,非零代表識別結(jié)果 ID,為零則表示無識別結(jié)果,兩種回復(fù)都被認(rèn)為讀取操作成功(其他回復(fù)或無回復(fù)被視為異常)。

具體過程如下圖所示:

mcu_voi611_example_2

心跳包是指將自己的狀態(tài)通知對方,表示自己處于正常工作狀態(tài)。考慮到產(chǎn)片端主控 MCU 對心跳周期和狀態(tài)數(shù)據(jù)類目的多樣性,語音芯片的心跳包實現(xiàn)方式為:主控 MCU 對語音芯片的讀操作,若讀取成功,則說明語音芯片當(dāng)前系統(tǒng)處于正常運行狀態(tài)。

對于讀取語音芯片操作的多次失?。ūM管概率很低,但不排除一些外部原因),主控 MCU 可以通過 RST 引腳傳遞復(fù)位信號,控制語音芯片重啟。


7. 示例程序


7.1 十分鐘快速上手

如下是讀寫操作簡單示例。

static uint16_t seq = 0;

uint8_t voi611_reg_write(uint8_t reg, uint8_t val, uint8_t msg)
{
    // 1. 準(zhǔn)備發(fā)送的數(shù)據(jù)幀
    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 串口發(fā)送 api
    uint8_t ret = uart_write(buf, 11);

    return ret;
}

uint8_t voi611_reg_read(uint8_t reg, uint8_t *val)
{
    // 1. 先發(fā)送讀取 REG 指令
    voi611_reg_write(reg, 0x00, 0xF1);

    // 2. 以下為等待 VOI611 回復(fù)(阻塞式),或開發(fā)者自行實現(xiàn)接收,通過 3. 進(jìn)行解析
    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 個字節(jié)超時,失敗退出
    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)
        {
            // 校驗和正確,返回結(jié)果
            *val = buf[9];                            // VAL
            return 0x01;
        }

        // 校驗和錯誤
    }

    // 非法幀
    return 0x00;
}


典型應(yīng)用代碼(最小化)如下。

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);  // 復(fù)位寄存器表
    voi611_reg_write(0x0B, 0x00, 0xF0);  // 設(shè)置為識別結(jié)果不主動上報,MCU 自行查詢
    voi611_reg_write(0x20, 0x05, 0xF0);  // 設(shè)置選擇應(yīng)用場景索引號

    voi611_reg_write(0x07, 0x01, 0xF0);  // 播放上電歡迎語的提示音

    // 3. 讀取并校驗寫入成功
    // ……

    return 0x01;
}


void main()
{
    uint8_t ret, val;

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

    // 2. 主循環(huán)
    while(1)
    {
        // 每隔 200ms,讀取識別結(jié)果,0表示當(dāng)前無識別結(jié)果
        ret = voi611_reg_read(0x0A, &val);

        if (ret == 0x00 || val == 0x00)
        {
            // 超時或者無識別結(jié)果,本次查詢無語音動作
            // continue;
        }
        else
        {
            switch(val)
            {
                case (1):
                    // 打開燈光
                    app_light_on();
                    // 播放提示音:開燈
                    voi611_reg_write(0x07, 0x03, 0xF0);
                    break;

                case (2):
                    // 關(guān)閉燈光
                    app_light_off();
                    // 播放提示音:關(guān)燈
                    voi611_reg_write(0x07, 0x04, 0xF0);
                    break;

                case (3):
                case (4):
                    // 屏蔽這些命令詞3和4,不響應(yīng)識別結(jié)果
                    break;

                default:
                    // 屏蔽其他的識別結(jié)果
                    break;
            }
        }

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


8. 相關(guān)解釋


關(guān)于“主動上報 / 不主動上報”、“主動播報 / 被動播報”、“喚醒邏輯”的關(guān)系:

“主動上報 / 不主動上報”與“喚醒邏輯”并無關(guān)聯(lián),這兩種方式僅區(qū)別于如何將識別結(jié)果從語音芯片傳遞給主控 MCU。

“主動上報 / 不主動上報”的設(shè)定與“主動播報 / 被動播報”并無關(guān)聯(lián),播報方式僅代表語音芯片完成識別后是直接播放提示音(主動),還是由MCU控制播放提示音(被動),通常在應(yīng)用場景號中進(jìn)行選擇。(一般來說,不主動上報識別結(jié)果時,識別-播報的交互邏輯也是交由MCU處理,此時語音模塊應(yīng)選擇為被動播報)

關(guān)于“喚醒邏輯”的說明:

通常情況下語音芯片應(yīng)用的喚醒邏輯有兩種狀態(tài):

  • 非喚醒狀態(tài)(僅監(jiān)聽喚醒詞)
  • 喚醒狀態(tài)(監(jiān)聽喚醒詞、命令詞)

其中,從非喚醒狀態(tài)進(jìn)入喚醒狀態(tài),稱之為“喚醒-事件”,“喚醒-事件”只能通過 2 種方式產(chǎn)生:任何情況下 MCU 寫入 1 至 REG 0x14;或者語音芯片識別到在 REG 0x21:0x23 標(biāo)記為喚醒詞的命令詞 ID,且 REG 0x16 設(shè)置為 1。

喚醒邏輯的設(shè)定,是為了減少誤操作的發(fā)生。例如語音智能燈產(chǎn)品,默認(rèn)(非喚醒狀態(tài))僅監(jiān)聽喚醒詞“你好小白”,進(jìn)入喚醒狀態(tài)后可以識別其他命令詞“打開燈光、調(diào)亮一點”等等。

如果在非喚醒狀態(tài)下識別《命令詞列表》中所有的詞匯并執(zhí)行動作,那么會使誤操作的概率上升,造成用戶困擾(現(xiàn)階段語音識別無法杜絕誤識別,但可以通過此方法減小概率)。

通常,除在 REG 0x21:0x23 中被標(biāo)記為喚醒詞的命令詞以外,剩余《命令詞列表》的詞均為非喚醒詞。