在线时间376 小时
UID3135871
注册时间2016-10-9
NXP金币97

TA的每日心情 | 怒 2025-5-29 09:38 |
---|
签到天数: 632 天 连续签到: 1 天 [LV.9]以坛为家II
版主
  
- 积分
- 4470

- 最后登录
- 2025-6-10
|
月初,得到日天给的2个语音模块,是深圳海凌科技的。我去下载了些资料,看下说明。觉得还挺好玩的。
自己打样了官方的板子,焊上模块,结果2块都不行。没有耗太多精力去检查。在它们官网买了一个现成的
模块,带喇叭和麦克风及串口USB电路。如图:
官方出厂里面就有默认固件,当然你还可用去官网,直接开发自己的指令。不用写一句代码,就类似填填表格
啥的就能完成了。
HLK-V20/HLK-V20S是海凌科电子针对大量纯离线控制场景和产品最新推出的高性能纯离线
语音识别模块,可广泛且快速的应用于智能家居、各类智能小家电、86盒、玩具、灯具、工业、
医疗、物联网、汽车、安防与照明等需要语音操控的产品。
模块采用32bit RSIC架构内核,并加入了专门针对信号处理和语音识别所需要的DSP指令
集,支持浮点运算的FPU运算单元,以及FFT加速器,通过神经网络对音频信号进行训练学习,
提高语音信号的识别能力。
HLK-V20支持150条本地指令离线识别,HLK-V20S支持50条本地指令离线识别,可自由定制
唤醒词、命令词与应答播报词,具有丰富的外围接口。
模块本身还带有麦克风输入和喇叭输出引脚及7个独立的普通IO,支持SPI,IIC,DAC及PWM输出等~
看起来,性能还是蛮强的。一些简单的应用,甚至都不要另外MCU了,用该模块能直接完成。。
模块引脚定义:
模块整体框图:
默认的一些离线语音指令:
我们本次就不在线上生产新的SDK了,我们直接用框出的指令,开关电风扇指令。
板上上实际对应开关一个LED灯。
我们将PIO1_16-->USART1_RXD,PIO1_17-->USART1_TXD,VCC-->5V,GND-->GND.
本次使用LPC845小板来实验。用到外设Systick,CTIMER,USART0,USART1,GPIO等。
程序使用MDK编写。程序结构:
USART0 用来输出调试信息,USART1来跟模块连接。使用CTIMER来进行判断接收语句的结束,本例设定为大于10ms
未接收到信息即接收结束。
CTIMER 初始化及中断:
- #include "ctime.h"
- /* Single callback functions definition */
- ctimer_callback_t CTIMER0_callback[] = {CTIMER0_IRQn_Match0_callback};
- //prescale时钟分频
- //matchValue 累加事件触发数
- void CTIME0_Init(u32 prescale,u16 matchValue )
- {
- ctimer_config_t CTIMER0_config = {
- .mode = kCTIMER_TimerMode,
- .input = kCTIMER_Capture_0,
- .prescale = prescale-1
- };
- ctimer_match_config_t CTIMER0_Match_0_config = {
- .matchValue = matchValue,
- .enableCounterReset = true,
- .enableCounterStop = false,
- .outControl = kCTIMER_Output_NoAction,
- .outPinInitState = false,
- .enableInterrupt = true
- };
- CTIMER_StopTimer(CTIMER0_PERIPHERAL);
- CTIMER_Deinit(CTIMER0_PERIPHERAL);
- /* CTIMER0 peripheral initialization */
- CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);
- /* Interrupt vector CTIMER0_IRQn priority settings in the NVIC. */
- NVIC_SetPriority(CTIMER0_TIMER_IRQN, CTIMER0_TIMER_IRQ_PRIORITY);
- /* Match channel 0 of CTIMER0 peripheral initialization */
- CTIMER_SetupMatch(CTIMER0_PERIPHERAL, CTIMER0_MATCH_0_CHANNEL, &CTIMER0_Match_0_config);
- CTIMER_RegisterCallBack(CTIMER0_PERIPHERAL, CTIMER0_callback, kCTIMER_SingleCallback);
- /* Start the timer */
- CTIMER_StartTimer(CTIMER0_PERIPHERAL);
-
- CTIMER_StopTimer(CTIMER0_PERIPHERAL);
- }
- #include "led.h"
- #include "usart1.h"
- //设定为每100ms中断一次
- //static u16 mscnt=0;
- void CTIMER0_IRQn_Match0_callback(uint32_t flags)
- {
- USART1_RX_STA|=1<<15; //标记接收完成
- CTIMER_StopTimer(CTIMER0_PERIPHERAL);//关闭SCT0定时器
- }
复制代码 usart1初始化及中断:
- #include "usart1.h"
- #include "stdarg.h"
- #include "stdio.h"
- #include "string.h"
- #include "math.h"
- #include "delay.h"
- #include "ctime.h"
- //串口接收缓存区
- u8 USART1_RX_BUF[USART1_MAX_RECV_LEN]; //接收缓冲,最大USART1_MAX_RECV_LEN个字节.
- u8 USART1_TX_BUF[USART1_MAX_SEND_LEN]; //发送缓冲,最大USART1_MAX_SEND_LEN字节
- //通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
- //如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到
- //任何数据,则表示此次接收完毕.
- //接收到的数据状态
- //[15]:0,没有接收到数据;1,接收到了一批数据.
- //[14:0]:接收到的数据长度
- vu16 USART1_RX_STA=0;
- void USART1_IRQHandler(void)
- {
- /* Place your code here */
- u8 res;
- uint32_t status;
- status = USART1->STAT;
- if((status & USART_STAT_RXRDY_MASK) != RESET)//接收到数据
- {
- res =USART_ReadByte(USART1);
- if((USART1_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据
- {
- if(USART1_RX_STA<USART1_MAX_RECV_LEN) //还可以接收数据
- {
- CTIMER0_PERIPHERAL->TC=0;; //计数器清空
- if(USART1_RX_STA==0) //使能定时器7的中断
- {
- CTIMER_StartTimer(CTIMER0_PERIPHERAL);//使能定时器
- }
- USART1_RX_BUF[USART1_RX_STA++]=res; //记录接收到的值
- }else
- {
- USART1_RX_STA|=1<<15; //强制标记接收完成
- }
- }
- }
- USART_ClearStatusFlags(USART1,status);
- /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
- Store immediate overlapping exception return operation might vector to incorrect interrupt. */
- #if defined __CORTEX_M && (__CORTEX_M == 4U)
- __DSB();
- #endif
- }
- //初始化IO 串口1
- //pclk1:PCLK1时钟频率(Mhz)
- //bound:波特率
- void usart1_init(u32 bound)
- {
- //串口参数定义
- usart_config_t USART1_config = {
- .baudRate_Bps = bound,
- .syncMode = kUSART_SyncModeDisabled,
- .parityMode = kUSART_ParityDisabled,
- .stopBitCount = kUSART_OneStopBit,
- .bitCountPerChar = kUSART_8BitsPerChar,
- .loopback = false,
- .enableRx = true,
- .enableTx = true,
- .clockPolarity = kUSART_RxSampleOnFallingEdge,
- .enableContinuousSCLK = false,
- .enableHardwareFlowControl = false
- };
-
- /* USART0 peripheral initialization */
- USART_Init(USART1_PERIPHERAL, &USART1_config, USART1_CLOCK_SOURCE);
- USART_EnableInterrupts(USART1_PERIPHERAL, kUSART_RxReadyInterruptEnable);
- /* Enable interrupt USART0_IRQn request in the NVIC. */
- EnableIRQ(USART1_USART_IRQN);
-
- USART1_RX_STA=0; //清零
- CTIMER_StopTimer(CTIMER0_PERIPHERAL);//关闭CT0定时器
- }
- //串口1,printf 函数
- //确保一次发送数据不超过USART1_MAX_SEND_LEN字节
- void u1_printf(char* fmt,...)
- {
- u16 i,j;
- va_list ap;
- va_start(ap,fmt);
- vsprintf((char*)USART1_TX_BUF,fmt,ap);
- va_end(ap);
- i=strlen((const char*)USART1_TX_BUF); //此次发送数据的长度
- for(j=0;j<i;j++) //循环发送数据
- {
- while((USART1->STAT & USART_STAT_TXRDY_MASK)==RESET){};//循环发送,直到发送完毕
- USART1->TXDAT = (u8) USART1_TX_BUF[j];
- }
- }
- void u1_sendstr(char* fmt)
- {
- u16 j=0;
- u16 len =strlen(fmt);
-
- for(j=0;j<len;j++) //循环发送数据
- {
- while((USART1->STAT & USART_STAT_TXRDY_MASK)==RESET){};//循环发送,直到发送完毕
- USART1->TXDAT = (u8) USART1_TX_BUF[j];
- }
- }
复制代码 在main函数中进行判断:
由于输出指令只有3字节(如00 01 0A ,00 02 0A),其中2字节为真正的指令,我们判断它即可。
- u16 t;
- u16 len;
- u16 times=0,TrueCmd=0;
- u8 CMD[2]={0,0};
- u8 TmpData[8]={0,0,0,0,0,0,0,0};
- /* Init board hardware. */
- BOARD_InitBootPins();
- BOARD_InitBootClocks();
- BOARD_InitPeripherals();
- delay_init(15000000);//当前设定频率为30M
- uart0_init(115200);
- led_init();
- CTIME0_Init(150000,1);//1500000/150000=100Hz 1CNT=10ms
- usart1_init(115200);
- printf("The MainClock is %d MHz.\r\n",SystemCoreClock/1000000);
- while(1)
- {
- if(USART1_RX_STA&0X8000) //接收到一次数据了
- {
- len=USART1_RX_STA&0X7FFF; //得到数据长度
- USART1_RX_BUF[len]=0; //加入结束符
-
- if(len>=3) //控制DS1检测
- {
- TrueCmd=USART1_RX_BUF[1];
- if(TrueCmd==0X01){LED_RED_L;}//打开LED1
- if(TrueCmd==0X02){LED_RED_H;}//关闭LED1
- }
- //u1_printf("Get word!\r\n");
- u1_printf((char*)USART1_RX_BUF);
- printf("%c %c %c\r\n",
- USART1_RX_BUF[0],USART1_RX_BUF[1],USART1_RX_BUF[2]);
- printf("The CM IS %02x\r\n",TrueCmd);
- USART1_RX_STA=0;
- }
- }
复制代码 编译无误后,进行下载,复位。先唤醒设备,然后语音控制LED开关。
代码太简单,就不上传了。谢谢观看~
|
|