基于STM32的智慧物联网系统板---离线语音模块使用 HLK-V20-SUIT是海凌科电子推出的一款高性能纯离线语音识别模块,专为智能家居、智能小家电及物联网设备设计,凭借其高性价比、灵活定制化和低功耗特性,成为语音控制领域的热门选择。该模块采用32位RSIC架构核心,集成DSP指令集、FPU浮点运算单元及FFT加速器,通过神经网络算法对音频信号进行深度训练,显著提升语音识别准确率,在安静环境下识别率超过95%,即使在办公室或音乐播放等嘈杂场景中,仍能保持75%以上的识别率,误唤醒率低于1次/24小时,确保设备稳定响应。支持150条本地指令存储,用户可通过海凌科语音定制后台系统自由配置唤醒词、命令词及应答语,无需复杂编程即可快速生成专属SDK,满足个性化需求。模块提供UART、GPIO、PWM等丰富接口,可轻松连接动圈扬声器、驻极体麦克风等外围设备,仅需少量外围元件即可实现语音交互功能,开发周期短,成本可控。其工作电压为5V,平均待机功耗仅63mA,工作电流约60mA,适合电池供电场景,如智能门锁、无线音箱等设备。
该模块尺寸紧凑(封装模块设计),便于集成到各类产品中,尤其适用于空间受限的设备。其应用场景广泛,涵盖智能家居(如语音控制风扇、插座、灯泡、空调)、智能小家电(如智能茶壶、故事机、扫地机)、工业控制(如设备语音操作)、医疗监护(如语音呼叫系统)等领域。例如,用户可通过语音指令“打开空调”或“调暗灯光”,无需手动操作,提升生活便捷性;在工业场景中,工人可通过语音控制设备启动或停止,提高作业效率。支持离线识别,无需联网即可使用,避免了网络延迟或断网导致的功能失效问题,同时保护用户隐私数据。此外,模块兼容轻量级RTOS系统,资源占用低,运行稳定,适合资源有限的嵌入式设备。对于开发者而言,海凌科提供详细的技术文档和开发工具,降低开发门槛,加速产品上市。
综合来看,HLK-V20-SUIT以高性能、低功耗、易定制和广适配性为核心优势,为语音控制设备提供了可靠的解决方案。无论是追求性价比的智能家居厂商,还是需要快速迭代的物联网开发者,该模块均能满足需求,助力产品实现智能化升级。
模组实物如下:

HLK-V20-SUIT模组采用串口通讯方式,语音词条响应成功通过串口返回应答信息,其硬件接口设计如下:

该模组采用5V供电,自带功放电路,直接接入扬声器(8Ω1W)即可输出,麦克风输入也无需外置处理电路,直接接入即可,灵敏度为-38DB。硬件实物如图所示:

HLK-V20-SUIT模组支持自定义语音词条,登录海凌科官网,注册账号。海凌科官网地址:[海凌科官网地址](https://www.hlktech.com/)

滑动到最下面可看到语音定制系统。

进行账号注册,登录平台。

选中产品接入,完成产品创建。

选中产品接入,完成产品创建。



1.设置前端信号处理。

2.设置串口通讯参数

3.设置语音唤醒词条

4.设置离线词条信息

5.设置应答返回数据格式

6.发音和音量设置

7.其他设置

8.发布SDK,发布成功即可下载SDK包

1.下载固件烧写工具。下载地址:[固件烧写工具](https://h.hlktech.com/Mobile/download/FDetail/93.html)

2.本系统板已预留固件升级接口,接口电路如下:


在硬件失实物上,C_RX与PA9连接、TX与PA10连接则是给STM32系统板烧写程序;C_RX与H_RX连接、TX与H_TX连接则是给海凌科模组烧写固件。因此本次需要将跳线帽将C_RX与H_RX连接、TX与H_TX连接。
在下载的SDK包中“uni_hb_m_solution-xxxx-xxxx”目录下的uni_app_debug_update.bin 和uni_app_release_update.bin 是用于 usb 升级的固件。usb升级的固件不能有中文路径。
使用Type-C数据线与开发板连接,识别成功将自动识别到COM口。

选中好要烧写的uni_app_release_update.bin 文件。

点击烧录按钮, 如图所示,提示栏显示等待设备。(注意:此时设备不要上电)。

如下图为海凌科模组供电引脚,点击烧录前先拔掉该跳线帽,出现等待设备后再插上该跳线帽。

下载完成如下:

至此,固件烧写完成。
HLK-V20模块采用串口串口2驱动,串口通讯波特率为115200,数据帧格式为1bit起始信号+8bit数据位+1bit停止信号,无校验位。驱动程序如下:
/*
串口初始化
形参:USARTx --要初始化的串口(USART1、USART3、USART2)
buad --要设置的波特率
*/
void USARTx_Init(USART_TypeDef *USARTx,u32 buad)
{
if(USARTx == USART1)
{
//1.开时钟
RCC- >APB2ENR|=1< <2;//PA
RCC- >APB2ENR|=1< <14;//usart1
RCC- >APB2RSTR|=1< <14;//复位时钟
RCC- >APB2RSTR&=~(1< <14);//取消复位
//2.配置GPIO
GPIOA- >CRH&=0xFFFFF00F;
GPIOA- >CRH|=0x000008B0;
USART1- >BRR=72000000/buad;//设置波特率
#ifdef USART1_IRQ
USART1- >CR1|=1< <4;//IDLE空闲帧中断
USART1- >CR1|=1< <5;//串口接收中断使能
STM32_SetNVICPriority(1,1,USART1_IRQn);//设置优先级,使能中断线
#endif
}
else if(USARTx == USART2)
{
/*1.开时钟*/
RCC- >APB2ENR|=1< <2;//PA时钟
RCC- >APB1ENR|=1< <17;//USART2时钟
RCC- >APB1RSTR|=1< <17;//开复位时钟
RCC- >APB1RSTR&=~(1< <17);//取消复位
/*2.配置GPIO口*/
GPIOA- >CRL&=0xFFFF00FF;//清除原来寄存器中的值
GPIOA- >CRL|=0x00008B00;
//3.配置串口3核心功能
USART2- >BRR=36000000/buad;//波特率
#ifdef USART2_IRQ
USART2- >CR1|=1< <5;//串口2接收中断
USART2- >CR1|=1< <4;//空闲帧中断
STM32_SetNVICPriority(1,1,USART2_IRQn);//设置优先级
#endif
}
else if(USARTx == USART3)
{
//1.开时钟
RCC- >APB2ENR|=1< <3;//PB
RCC- >APB1ENR|=1< <18;//USART3
RCC- >APB1RSTR|=1< <18;//复位时钟
RCC- >APB1RSTR&=~(1< <18);//取消复位
//2.配置GPIO
GPIOB- >CRH&=0xFFFF00FF;
GPIOB- >CRH|=0x00008B00;
//3.配置串口3核心功能
USART3- >BRR=36000000/buad;//波特率
#ifdef USART3_IRQ
USART3- >CR1|=1< <4;//IDLE空闲帧中断
USART3- >CR1|=1< <5;//串口接收中断使能
STM32_SetNVICPriority(1,1,USART3_IRQn);//设置优先级,使能中断线
#endif
}
USARTx- >CR1|=1< <3;//使能发送
USARTx- >CR1|=1< <2;//使能接收
USARTx- >CR1|=1< <13;//使能串口
}
u8 usart2_buffer[1024];//串口1接收数据缓冲区
u16 usart2_cnt=0;//保存数组下班
u8 usart2_flag;//接收完成标志符
void USART2_IRQHandler(void)
{
u8 c;
if(USART2- >SR&1< <5)//判断是否接收中断触发
{
c=USART2- >DR;
// USART1- >DR=c;
if(usart2_flag==0)//判断上一次数据是否处理完成
{
if(usart2_cnt< 1024)
{
usart2_buffer[usart2_cnt++]=c;
}
else usart2_flag=1;
}
}
if(USART2- >SR&1< <4)
{
c=USART2- >DR;
c=c;
usart2_flag=1;
}
}
主函数:
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart1.h"
#include "timer.h"
#include "esp8266.h"
#include "oled.h"
#include "rtc.h"
#include < stdio.h >
#include < string.h >
#include < stdlib.h >
int main()
{
LED_Init();//LED
Key_Init();
USARTx_Init(USART1,115200);//一个字符的收发时间:1s/(115200/10)=86us
USARTx_Init(USART2,115200);
USARTx_Init(USART3,115200);
OLED_Init();
OLED_DispalyFont(32,0,16,font_16[0]);
OLED_DispalyFont(32+16,0,16,font_16[1]);
OLED_DispalyFont(32+16*2,0,16,font_16[2]);
OLED_DispalyFont(32+16*3,0,16,font_16[3]);
OLED_Refresh();
RTC_Init();
u16 key=0;
while(1)
{
if(usart2_flag)
{
if(usart2_cnt==3)
{
if(usart2_buffer[0]==0x77 && usart2_buffer[2]==0x0a)
{
switch(usart2_buffer[1])
{
case 1://开灯
LED1=0;
break;
case 7://关灯
LED1=1;
break;
}
}
}
// printf("rx2=%s,%dn",usart2_buffer,usart2_cnt);
usart2_flag=0;
usart2_cnt=0;
}
}
}
全部0条评论
快来发表一下你的评论吧 !