实现语音识别系统:手把手教你使用STM32C8T6和LD3320(SPI通信版)实现语音识别

news2024/11/16 23:34:41

        本文实际是对LD3320(SPI通信版)的个人理解,如果单论代码和开发板的资料而言,其实当你购买LD3320的时候,卖家已然提供了很多资料。我在大学期间曾经多次使用LD3320芯片的开发板用于设计系统,我在我的毕业设计作品中也有添加这个系统功能,用于添加整个系统的趣味性。本文的初衷也是为了总结学习内容,供大家参考学习。如果我的理解有误,也希望读者可以在评论中指出,不胜感激。

附上我的工程代码:工程代码

目录

目录

附上我的工程代码:工程代码

关于LD3320的通俗理解     

那么LD3320串口版和SPI版本的有什么区别呢?

LD3320的实现原理

功能实现(demo)

1、实现功能

2、实物图

3、接线图

4、SPI协议的详细介绍和解读 

1)SPI协议的通信过程如下:

2)SPI协议的数据传输方式分为两种模式:模式0和模式3

3)SPI协议有四根线:SCLK、MOSI、MISO、SS

代码层面解析(需要修改)

1)main.c文件

2)LD3320_main.c文件及其头文件(重点)

(1)LD3320_main.c文件

(2)LDchip.h文件(不做过多解释,详细见注释)

3)关于用电器的IO口配置(led.c)


关于LD3320的通俗理解     

        使用LD3320的好处是它直接免去了你训练模型的过程,换言之,它是将已经训练好的一套语音识别系统集成到LD3320芯片上了,我们只需要会“调用”LD3320芯片即可,就像搭积木一样,它已然是个整体模块,我们甚至不需要提供多余的操作,只需要堆上去,它就已经可以使用。那么如何“调用”它,就是我们需要解决的最大难点。

        目前市面上的LD3320有两种型号:其一是SPI版的,如下图所示,这个是我们今天的主角,我们可以将其视为外围电路的一个模块(就是一块积木),需要外接一个单片机去“调用”这个模块从而实现智能语音识别。

      

 其二是串口版本的,如图所示。

那么LD3320串口版和SPI版本的有什么区别呢?

LD3320语音识别芯片的SPI版本和串口版本的区别在于它们的通信接口不同。SPI版本是通过SPI接口进行通信,而串口版本是通过串口接口进行通信。

具体而言,SPI版本可以直接和MCU或其他支持SPI通信的设备进行连接,并通过SPI接口传输数据。而串口版本则需要通过串口与MCU进行通信,通常需要在MCU上编写一定的串口通信协议来实现与芯片的数据交换。

另外,由于通信接口不同,SPI版本和串口版本的应用场景也略有不同。SPI版本的芯片适合于对通信速度有要求、需要高速传输数据的场合,而串口版本则适合于一些通信速度要求不高、需要适应不同串口的应用场合。

通俗而言,就是SPI版本的通信速度快,且可以是视为一个正真独立的模块;而串口版的可以视为一个具有信息处理能力的51MCU。


LD3320的实现原理

LD3320语音识别芯片的实现原理主要可以分为以下几个步骤:

1. 音频采集:LD3320内置一个麦克风放大器,它可以对周围的声音进行采集,并将采集到的音频信号送入芯片内部的语音信号处理器。

2. 信号处理:LD3320内置一个语音信号处理器,它可以对音频信号进行预处理、降噪、滤波等处理,以提高识别的准确率。

3. 特征提取:经过信号处理后,LD3320将音频信号转换成数字信号,并提取出其中的语音特征。LD3320采用了一种叫做Mel频率倒谱系数(Mel-frequency cepstral coefficients, MFCC)的特征提取算法。

4. 模型匹配:LD3320内置了一些语音识别的模型,比如说中文数字、英文数字、中文拼音等。LD3320将提取出的语音特征与这些模型进行匹配,以识别出用户说的话。

5. 输出结果:一旦LD3320识别出了用户的话,它会将识别结果输出到外部的MCU或DSP芯片中,以供后续的应用程序使用。

总的来说,LD3320的实现智能语音识别的原理就是通过内置的麦克风放大器进行音频采集,经过信号处理和特征提取后,将提取出的语音特征与内置的模型进行匹配,从而实现对用户语音指令的识别和理解。LD3320语音识别芯片通过识别语音信号中的特定频率和时域特征来实现语音识别。它使用的是端点检测技术,即在语音信号的开始和结束处检测到信号的存在,并将其传递给后续处理模块进行识别。LD3320芯片可以进行多语言识别,包括中文、英文、日文、韩文等。不过需要注意的是,其语音识别的准确率可能会受到环境噪声等因素的影响。


功能实现(demo)

1、实现功能

语音控制开关卧室、客厅灯;开关风扇等功能

2、实物图

3、接线图

 

4、SPI协议的详细介绍和解读 

SPI(Serial Peripheral Interface)是一种同步的串行通信协议,用于在微控制器或其他数字集成电路(IC)之间传输数据。它是一种全双工、点对点的通信协议,使用四根线进行通信:主机发送数据时,从机收到并返回响应数据。

SPI通信协议使用一个主机和一个或多个从机之间进行数据传输,其中一个设备是主机,其他设备是从机。主机负责协调整个通信过程,从机只有在被主机选择时才会响应。通常情况下,SPI总线上只会有一个主机,但可以同时连接多个从机,每个从机都有一个独立的从机选择信号线。

1)SPI协议的通信过程如下:

1. 主机将从机选择信号线拉低,选中要进行通信的从机。

2. 主机向从机发送一个时钟信号,时钟信号将数据的传输分为若干个时钟周期。

3. 主机通过一个数据线将数据发送给从机,并通过另一个数据线接收从机返回的数据。

4. 在时钟的最后一个周期,主机将从机选择信号线拉高,表示通信结束。

2)SPI协议的数据传输方式分为两种模式:模式0和模式3

模式0的时钟极性(CPOL)和相位(CPHA)都为0,意味着时钟线在空闲状态下为低电平,数据在上升沿进行采样。模式3的时钟极性(CPOL)和相位(CPHA)都为1,意味着时钟线在空闲状态下为高电平,数据在下降沿进行采样。

3)SPI协议有四根线:SCLK、MOSI、MISO、SS

其中,SCLK是时钟线,由主设备控制,用于同步数据传输;MOSI是主设备输出、从设备输入的数据线;MISO是从设备输出、主设备输入的数据线;SS是片选信号线,用于选择与主设备通信的从设备。通信过程中,主设备通过SCLK线向从设备发送时钟信号,同时将数据通过MOSI线发送给从设备,从设备则通过MISO线返回响应的数据。SS线控制从设备的选中与释放,可以支持多从设备的通信。

SPI协议的优点是高速、简单、成本低廉,通信线路简单,但需要额外的从机选择信号线。SPI协议被广泛应用于各种数字集成电路之间的通信,如闪存、EEPROM、数字信号处理器等。总而言之,SPI协议的传输速率快,适合于数据量小、实时性高的应用场合。


代码层面解析(需要修改)

 综上所述,我们不难看出。我们只需要学会“调用”LD3320就行,因为它就是一块“积木”,我们只需要学会使用就行,至于语音识别的难题,芯片已经帮你解决了。在“调用”芯片时需要使用到SPI协议,我们使用STM32C8T6作为控制芯片

1)main.c文件

我们这里只需要注意LD3320_main()函数,至于while中的两个函数,你不要被它唬到了,它其实就是通过定时器和中断来实现开关(客厅和卧室)灯。难点实际在LD3320_main()

int main()
{  	
	
	Systick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	USART1_Init(115200);
	//TIM3_Int_Init(5000-1,72-1);
	TIM4_Int_Init(999,72-1);

	LED_Init();

	//TIM_Cmd(TIM3,ENABLE);
	TIM_Cmd(TIM4,ENABLE);
    printf("初始化完成\r\n");
    LD3320_main();		//LD3320 主函数函数
	while(1)
	{
		TimerTreat();
		ledshow();
       
	}
}

2)LD3320_main.c文件及其头文件(重点)

(1)LD3320_main.c文件

这里主要修改:static void Board_text(uint8 Code_Val)函数,具体操作结合头文件分析即可。注意,头文件也需要修改。这个非常的简单,只需要有基本的C代码阅读能力即可修改,不做过多解释啦


#include "LDchip.h"
#include "Reg_RW.h"
#include "system.h"
#include "SysTick.h"
#include "usart.h"
#include <stdio.h>
#include "led.h"
/*************端口信息********************
 * 接线说明
 LD3320接口 	  STM32接口
 * RST              PB6
 * CS   	        PB8
 * WR/SPIS          PB9
 * P2/SDCK          PB13
 * P1/SDO           PB14
 * P0/SDI           PB15
 * IRQ              PA3
 * A0		        PB7
 * RD               PA0

*****************************************/



/************************************************************************************
//	nAsrStatus 用来在main主程序中表示程序运行的状态,不是LD3320芯片内部的状态寄存器
//	LD_ASR_NONE:		表示没有在作ASR识别
//	LD_ASR_RUNING:		表示LD3320正在作ASR识别中
//	LD_ASR_FOUNDOK:		表示一次识别流程结束后,有一个识别结果
//	LD_ASR_FOUNDZERO:	表示一次识别流程结束后,没有识别结果
//	LD_ASR_ERROR:		表示一次识别流程中LD3320芯片内部出现不正确的状态
*********************************************************************************/

uint8 nAsrStatus=0;	
void LD3320_Init(void);
uint8 RunASR(void);
void ProcessInt0(void);
void LD3320_EXTI_Cfg(void);
void LD3320_Spi_cfg(void);
void LD3320_GPIO_Cfg(void);
void LED_gpio_cfg(void);
static void Board_text(uint8 Code_Val);
extern void PrintComBit(USART_TypeDef* USARTx, uint8_t Data);
/***********************************************************
* 名    称: LD3320_main(void)
* 功    能: 主函数LD3320程序入口
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void  LD3320_main(void)
{
	uint8 nAsrRes=0;
	LD3320_Init();	  

	while(1)
	{
    	switch(nAsrStatus)
		{
			case LD_ASR_RUNING:
			case LD_ASR_ERROR:		
							  break;
			case LD_ASR_NONE:
								nAsrStatus=LD_ASR_RUNING;
								if (RunASR()==0)	//	启动一次ASR识别流程:ASR初始化,ASR添加关键词语,启动ASR运算
								{		
									nAsrStatus = LD_ASR_ERROR;
								}
								break;

			case LD_ASR_FOUNDOK:
								 nAsrRes = LD_GetResult( );	//识别成功自动 获取识别码,识别码在LDChip.h文件中,自行定义的数据										 									
								 PrintComBit(USART1,nAsrRes ); //串口输出识别码								
								 //Board_text(nAsrRes );//开发板测试演示部分---对识别码的进行判断做出动作 (用户亦可以添加自己的功能,例如控制IO口输出,串口数据输出等)		
								 nAsrStatus = LD_ASR_NONE;
								break;
			
			case LD_ASR_FOUNDZERO:
			default: nAsrStatus = LD_ASR_NONE;
					 break;
			}//switch	
        //开发板测试
		Board_text(nAsrRes );
	}// while
}


static void Board_text(uint8 Code_Val)
{																					 
	switch(Code_Val)  //对结果执行相关操作
	{
		case CODE_DD:	//命令“打开客厅灯”
		LED_KT=1;
        printf("打开客厅灯\r\n");
		break;
		
        case CODE_GD:		//命令“关闭客厅灯”
	    LED_KT=0;
        printf("关闭客厅灯\r\n");
        break;
        
        case CODE_QDD:		//命令“打开卧室灯”
	    //打开卧室灯
        LED_WS = 1;
        printf("打开卧室灯\r\n");
        break;
        
        case CODE_DG:		//命令“关闭卧室灯”
	    //关闭卧室灯
        LED_WS = 0;
        printf("关闭卧室灯\r\n");
		break;
        
        case CODE_LSD:		//命令“全部打开”
	    //全部打开
        LED_KT=1;
        LED_WS = 1;
        printf("全部打开\r\n");
		break;
        
        case CODE_SSD:		//命令“全部关闭”
	    //全部关闭
        LED_KT=0;  
        LED_WS = 0;
        printf("全部关闭\r\n");
        break;
        
        case CODE_DDR:		//命令“打开风扇”
	    //打开风扇
        printf("打开风扇\r\n");
        JDY_FS = 0;
		break;
        
        case CODE_RDD:		//命令“关闭风扇”
	    //关闭风扇
        JDY_FS = 1;
        printf("关闭风扇\r\n");
		break;
		default:break;
	}	
}
/***********************************************************
* 名    称:LD3320_Init(void)
* 功    能:模块驱动端口初始配置
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void LD3320_Init(void)
{
	LD3320_GPIO_Cfg();	
	LD3320_EXTI_Cfg();
	LD3320_Spi_cfg();	 
	LD_reset();
	
}
/***********************************************************
* 名    称:	RunASR(void)
* 功    能:	运行ASR
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
uint8 RunASR(void)
{
	uint8 i=0;
	uint8 asrflag=0;
	for (i=0; i<5; i++)			//	防止由于硬件原因导致LD3320芯片工作不正常,所以一共尝试5次启动ASR识别流程
	{
		LD_AsrStart();			//初始化ASR
		LD3320_delay(100);
		if (LD_AsrAddFixed()==0)	//添加关键词语到LD3320芯片中
		{
			LD_reset();			//	LD3320芯片内部出现不正常,立即重启LD3320芯片
			LD3320_delay(50);			//	并从初始化开始重新ASR识别流程
			continue;
		}

		LD3320_delay(10);

		if (LD_AsrRun() == 0)
		{
			LD_reset();			//	LD3320芯片内部出现不正常,立即重启LD3320芯片
			LD3320_delay(50);			//	并从初始化开始重新ASR识别流程
			continue;
		}

		asrflag=1;
		break;					//	ASR流程启动成功,退出当前for循环。开始等待LD3320送出的中断信号
	}

	return asrflag;
}

/***********************************************************
* 名    称: void Delay_( int i)
* 功    能: 短延时
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void Delay_( int i)
 {     
    while( i--)
       {	

        }
 }	
/***********************************************************
* 名    称:	LD3320_delay(unsigned long uldata)
* 功    能:	长延时函数
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
 void  LD3320_delay(unsigned long uldata)
{
	unsigned int j  =  0;
	unsigned int g  =  0;
	for (j=0;j<5;j++)
	{
		for (g=0;g<uldata;g++)
		{
			Delay_(120);
		}
	}
}


/***********************************************************
* 名    称:LD3320_GPIO_Cfg(void)
* 功    能:初始化需要用到的IO口
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void LD3320_GPIO_Cfg(void)
{	
	    GPIO_InitTypeDef GPIO_InitStructure;
		// 配置PA8 输出	 8M 波形	
		//定义RST/A0/CS/WR端口
	 {
	 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB ,ENABLE);
		//LD_CS	/RSET
		GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_Init(GPIOB,&GPIO_InitStructure);
		GPIO_SetBits(GPIOB,GPIO_Pin_7);	/*A0默认拉高*/
	 }
}
/***********************************************************
* 名    称:LD3320_Spi_cfg(void)
* 功    能:配置SPI功能和端口初始化
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void LD3320_Spi_cfg(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  	SPI_InitTypeDef  SPI_InitStructure;

	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能 	
 
	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	LD_CS_H();
	
 	GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		//选择了串行时钟的稳态:时钟悬空高
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	//数据捕获于第二个时钟沿
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;		//定义波特率预分频的值:波特率预分频值为16
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式
	SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(SPI2, ENABLE); //使能SPI外设
}
/***********************************************************
* 名    称: LD3320_EXTI_Cfg(void) 
* 功    能: 外部中断功能配置和相关端口配置
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void LD3320_EXTI_Cfg(void)
{
  EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  //定义IRQ中断引脚配置
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
	//外部中断线配置
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);
  EXTI_InitStructure.EXTI_Line = EXTI_Line3;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
  EXTI_GenerateSWInterrupt(EXTI_Line3);
		
	GPIO_SetBits(GPIOA,GPIO_Pin_3);	 //默认拉高中断引脚

	EXTI_ClearFlag(EXTI_Line3);
	EXTI_ClearITPendingBit(EXTI_Line3);
	//中断嵌套配置
  NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}


/***********************************************************
* 名    称:  EXTI1_IRQHandler(void)
* 功    能: 外部中断函数
* 入口参数:  
* 出口参数:
* 说    明:
* 调用方法: 
**********************************************************/ 
void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3)!= RESET ) 
	{
 		ProcessInt0();
		EXTI_ClearFlag(EXTI_Line3);
		EXTI_ClearITPendingBit(EXTI_Line3);
	}
}

(2)LDchip.h文件(不做过多解释,详细见注释)

#ifndef LD_CHIP_H
#define LD_CHIP_H

#define uint8 unsigned char
#define uint16 unsigned int
#define uint32 unsigned long

//	以下三个状态定义用来记录程序是在运行ASR识别还是在运行MP3播放
#define LD_MODE_IDLE		0x00
#define LD_MODE_ASR_RUN		0x08
#define LD_MODE_MP3		 	0x40


//	以下五个状态定义用来记录程序是在运行ASR识别过程中的哪个状态
#define LD_ASR_NONE				0x00	//	表示没有在作ASR识别
#define LD_ASR_RUNING			0x01	//	表示LD3320正在作ASR识别中
#define LD_ASR_FOUNDOK			0x10	//	表示一次识别流程结束后,有一个识别结果
#define LD_ASR_FOUNDZERO 		0x11	//	表示一次识别流程结束后,没有识别结果
#define LD_ASR_ERROR	 		0x31	//	表示一次识别流程中LD3320芯片内部出现不正确的状态


#define CLK_IN   	22	/* user need modify this value according to clock in */
#define LD_PLL_11			(uint8)((CLK_IN/2.0)-1)
#define LD_PLL_MP3_19		0x0f
#define LD_PLL_MP3_1B		0x18
#define LD_PLL_MP3_1D   	(uint8)(((90.0*((LD_PLL_11)+1))/(CLK_IN))-1)

#define LD_PLL_ASR_19 		(uint8)(CLK_IN*32.0/(LD_PLL_11+1) - 0.51)
#define LD_PLL_ASR_1B 		0x48
#define LD_PLL_ASR_1D 		0x1f

// LD chip fixed values.
#define        RESUM_OF_MUSIC               0x01
#define        CAUSE_MP3_SONG_END           0x20

#define        MASK_INT_SYNC				0x10
#define        MASK_INT_FIFO				0x04
#define    	   MASK_AFIFO_INT				0x01
#define        MASK_FIFO_STATUS_AFULL		0x08



void LD_reset(void);
uint8 RunASR(void);

void LD_Init_Common(void);

void LD_Init_ASR(void);

void LD_ReloadMp3Data(void);
void LD_ReloadMp3Data_2(void);

uint8 LD_ProcessAsr(uint32 RecogAddr);
void LD_AsrStart(void);
uint8 LD_AsrRun(void);
uint8 LD_AsrAddFixed(void);
uint8 LD_GetResult(void);

void LD_ReadMemoryBlock(uint8 dev, uint8 * ptr, uint32 addr, uint8 count);
void LD_WriteMemoryBlock(uint8 dev, uint8 * ptr, uint32 addr, uint8 count);

extern uint8  nLD_Mode;


	//以下为识别码的宏定义无特别意义,0-ff可自行修改值,不分顺序不要重复。
#define CODE_DD       0X01	  /*打开客厅灯*/
#define CODE_GD	  	  0X02	  /*关闭客厅灯*/
#define CODE_QDD 	  0X03    /*打开卧室灯*/
#define CODE_DG		  0X04	  /*关闭卧室灯*/
#define CODE_LSD	  0X05	  /*全部打开*/
#define CODE_SSD	  0X06	  /*全部关闭*/
#define CODE_DDR	  0X07	  /*打开继电器*/
#define CODE_RDD	  0X08	  /*继电器点动*/

//#define CODE_PLAY	  0X09	  /*播放歌曲*/
//#define CODE_NAME	  0X0A    /*你叫什么名字*/
//#define CODE_DO		  0X0B    /*你会做什么*/


void  LD3320_delay(unsigned long uldata);

#define MIC_VOL 0x43    //麦克风灵敏度条件,值越大越灵敏也容易误识别

#endif

3)关于用电器的IO口配置(led.c)

这里的代码的是对用电器引脚口的一个配置

#include "led.h"
#include "timer.h"
 void LED_Init()
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	    
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_0|GPIO_Pin_1;			   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 	 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	 //IO口速度为50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    LED_KT = 0;
    LED_WS = 0;//灯光初始为关闭状态
    JDY_FS = 1;
}


void ledshow(void)
{
	if(g_stTimerTickFlag.bTimer500ms == 1)
	{
		LED_KT = !LED_KT;
        LED_WS = !LED_WS;
	}
}

        代码是不是也非常简单,它就是一个搭积木的过程。总而言之很有趣的一个小系统,用于智能家居等一些场景也是十分不错的。但是目前而言,LD3320语音识别的板子对杂音的过滤十分有限,大概只能做到1m-1.5m的有效识别吧,具体的没测过。感兴趣的同学可以试试哈哈哈哈哈哈哈

哦,对了,需要说明一下,本代码只供学习哦,这代码本身也是我通过商家代码改的。如果想跟我一样,给自己的毕设或者系统添加一点小功能和一些趣味性,代码自取哈!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/887296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统学习Linux-Mariadb高可用MHA

概念 MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换操作。 MHA能在故障切换的过程中最大程度上…

IDEA 找不到项目 ‘org.springframework.boot:spring-boot-starter-parent:3.1.2‘

找不到项目 ‘org.springframework.boot:spring-boot-starter-parent:2.6.7’ 这个问题主要是因为ide的缓存导致的&#xff0c;我们直接清理缓存并重启ide 重启之后ide会对pom文件进行编排索引完成之后问题就没有了

去掉鼠标系列之一: 语雀快捷键使用指南

其实应该是系列之二了&#xff0c;因为前面写了一个关于Interlij IDEA的快捷键了。 为什么要写这个了&#xff0c;主要是觉得一会儿用鼠标&#xff0c;一会儿键盘&#xff0c;一点儿不酷&#xff0c;我希望可以一直用键盘&#xff0c;抛开鼠标。后面陆续记录一下各个软件的快捷…

STM32CubeMx之esp8266的at指令使用

AT //返回ok则为正常 ATCWMODE1//设置为设备模式 ATCWLAP//搜索附近可用wifi ATCWJAP"CMCC-5-7","chb513029"//连接热点 ATCIPMUX0//设置wifi为单连接 ATCIPSTART"TCP","192.168.37.1",1001//连接tcp 这里遇到了重重问题 这里我…

VScode搭建Opencv(C++开发环境)

VScode配置Opencv 一、 软件版本二 、下载软件2.1 MinGw下载2.2 Cmake下载2.3 Opencv下载 三、编译3.1 cmake-gui3.2 make3.3 install 四、 VScode配置4.1 launch.json4.2 c_cpp_properties.json4.3 tasks.json 五、测试 一、 软件版本 cmake :cmake-3.27.2-windows-x86_64 Mi…

Go framework-Beego

一、Beego Beego用于在Go中快速开发企业应用程序&#xff0c;包括RESTful API、web应用程序和后端服务。 Beego 源码地址 Beego 官方站点 Beego 官方说明 Beego的特性 RESTful支持MVC架构模块化自动API文档注释路由命名空间开发工具集合Full stack for Web & API Bee…

iTOP-2K1000开发板固态硬盘分区

固态硬盘分区的目的是把固态硬盘分成一个分区并格式化为 ext2&#xff0c;在 linux 系统下&#xff0c;分区主要使用的命令是 fdisk 命令。接下来我们一起看下分区操作。 U 盘启动成功以后进到文件系统&#xff0c;输入命令 fdisk -l 查看当前开发板的固态硬盘的节点&#xff…

易服客工作室:UberMenu WordPress插件 - 网站超级菜单插件

UberMenu WordPress插件是一个用户友好、高度可定制、响应迅速的 Mega Menu WordPress 插件。它与 WordPress 3 菜单系统一起开箱即用&#xff0c;易于上手&#xff0c;但功能强大&#xff0c;足以创建高度定制化和创意的大型菜单配置。 网址: UberMenu WordPress插件 - 网站超…

RS485、MODBUS通信协议详解

前言 MODBUS协议是Modicon公司发表的一种串行通信协议&#xff0c;属于OSI模型中应用层的协议&#xff0c;现广泛应用于工业控制领域&#xff0c;它的主要特点是免费开放、支持多种电气接口&#xff08;如RS-232、RS-485&#xff09;&#xff0c;传输介质可以是双绞线、光纤、无…

java-JVM内存区域JVM运行时内存

一. JVM 内存区域 JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA 堆、方法区】、直接内存。线程私有数据区域生命周期与线程相同, 依赖用户线程的启动/结束 而 创建/销毁(在 HotspotVM 内, 每个线程都与操作系统的本地线程直接映…

Beats:安装及配置 Metricbeat (一)- 8.x

在我之前的文章&#xff1a; Beats&#xff1a;Beats 入门教程 &#xff08;一&#xff09;Beats&#xff1a;Beats 入门教程 &#xff08;二&#xff09; 我详细描述了如何在 Elastic Stack 7.x 安装及配置 Beats。在那里的安装&#xff0c;它通常不带有安全及 Elasticsearc…

机器视觉基础实验-Panorama Stitching

文章目录 1、实验内容2、实验设计&#xff08;略&#xff09;3、实验环境及实验数据集四、实验过程及结果4.1 Harris角点检测器寻找关键点4.2 构建描述算子来描述图中的每个关键点&#xff0c;比较两幅图像的两组描述子&#xff0c;并进行匹配。4.3 根据一组匹配关键点&#xf…

Nginx的安装及负载均衡搭建

一.Nginx的安装 1&#xff09;准备安装环境 yum install -y make gcc gcc-c pcre-devel pcre zlib zlib-devel openssl openssl-develPERE PCRE(Perl Compatible Regular Expressions)是一个Perl库&#xff0c;包括 perl 兼容的正则表达式库。 nginx的http模块使用pcre来解…

每天一练:SpringBoot连接mq

目录 每天一练:Springboot连接rabbitmq 每天一练:Springboot连接rabbitmq 目录一、部署Rabbitmq&#xff1f;二、增加maven依赖三、连接RabbitMq四、发布和订阅消息总结 一、部署Rabbitmq&#xff1f; 这里rabbitmq采用docker安装部署。 拉取docker镜像 [root192 ~]# docker…

349. 两个数组的交集 题解

题目描述&#xff1a;349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 方法一&#xff1a; 解题思路&#xff1a; 我们可以…

《零基础7天入门Arduino物联网-04》电路基础知识上

配套视频课程&#xff1a;《零基础学Arduino物联网&#xff0c;入门到进阶》 配套课件资料获取&#xff1a;微联实验室 配套学习套件购买&#xff1a;淘宝搜索店铺【微联实验室】 直流电与交流电 直流电&#xff08;DC&#xff09; 是指电流的方向始终保持不变的电流。这意味着…

Hyperledger Fabric的使用及开发

Hyperledger Fabric是Linux基金会发起的一种跨行业的区块链技术&#xff0c;目前在多家大型公司有着应用&#xff0c;这里就不多做HF本身的介绍了&#xff0c;有兴趣可关注其官网。 1. 准备工作&#xff1a; 开始前需要一定的准备工作&#xff0c;安装各类中间件&#xff1a;…

JVM——HotSpot的算法细节实现

一、根节点枚举 固定可作为GC Roots的节点主要在全局性的引用&#xff08;如常量或类静态属性&#xff09;与执行上下文&#xff08;如栈帧中的本地变量表&#xff09;中&#xff0c;尽管目标明确&#xff0c;但查找要做到高效很难。现在java应用越来越庞大&#xff0c;光方法区…

啥是虚拟机

虚拟机这个概念第一次听到还是在我大二学计算机网络做实验的时候听说过&#xff0c;第二次算比较熟练地使用应该是在大三下学期的大数据课程&#xff0c;做实验的时候也算是学到了许多Linux的命令。但到底什么是虚拟机&#xff0c;我还是搞不清楚的&#xff0c;所以&#xff0c…

【八股】2023秋招八股复习笔记1(CSBase+部分WXG题)

文章目录 MYSQL & redis网络 & 系统安全 & C招聘要求&#xff08;x3&#xff09;部分面经和题目&#xff08;WXG-后端&#xff09;&#xff08;x5&#xff09; MYSQL & redis redis&#xff1a;memcached/mysql&#xff0c;线程模型&#xff08;6.0多线程&…