【STM32+HAL】语音识别模块LD3320(SPI版)

这篇具有很好参考价值的文章主要介绍了【STM32+HAL】语音识别模块LD3320(SPI版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、准备工作:

有关CUBEMX的初始化配置,参见我的另一篇blog:【STM32+HAL】CUBEMX初始化配置

二、所用工具:

1、芯片: STM32F103C6T6(同C8T6)

2、STM32CubeMx软件

3、语言识别模块:LD3320(SPI版)

ld3320 spi,stm32,嵌入式硬件,单片机

三、实现功能:

实现串口打印语音输入

四、HAL配置步骤:

1、SPI功能开启

ld3320 spi,stm32,嵌入式硬件,单片机

2、IO口配置

ld3320 spi,stm32,嵌入式硬件,单片机

3、中断配置

ld3320 spi,stm32,嵌入式硬件,单片机

至此,HAL库配置完成

五、硬件连接:

接线:
LD3320:
LD3320_CS_Pin 			GPIO_PIN_A2
LD3320_SCK_Pin 			GPIO_PIN_A5
LD_MI_Pin 				GPIO_PIN_A6
LD3320_MOSI_Pin 			GPIO_PIN_A7
LD3320_IRQ_Pin 			GPIO_PIN_B1
LD3320_WR_Pin 			GND
LD3320_RST_Pin 			GPIO_PIN_B10


调试器:
3V3 -> 3V3
GND -> GND
TMS -> SWIO
TCK -> SWCLK

串口:
U_RX -> PA9
U_TX -> PA10

六、KEIL填写代码:

1、LD3320.C

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

#define USE_HAL_LIB//使用HAL库
uint8_t nAsrStatus=0;
uint8_t nAsrRes=0;
uint8_t flag=0;
///用户修改
extern uint8_t nAsrStatus;
uint8_t  nLD_Mode=LD_MODE_IDLE;
uint8_t  ucRegVal;

#define LD3320_SPI	hspi1

/*硬件SPI读写*/
uint8_t SPI_RreadWrite_Data(uint8_t *tx_data, uint8_t len)
{
	uint8_t rx_data[len];
	HAL_SPI_TransmitReceive(&LD3320_SPI,tx_data,rx_data,len,0XFFFF);
	return rx_data[len-1];
}

void LD3320_main(void)
{
	nAsrStatus = LD_ASR_NONE;		//	初始状态:没有在作ASR
	//CS_LOW;
	printf("运行程序\r\n");
	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: /*	一次ASR识别流程结束,去取ASR识别结果*/
			{
				nAsrRes = LD_GetResult();		/*获取结果*/												
				User_Modification(nAsrRes);
				nAsrStatus = LD_ASR_NONE;
				break;
			}
			case LD_ASR_FOUNDZERO:
			default:
			{
				nAsrStatus = LD_ASR_NONE;
				break;
			}
		} 
	}
	
}

uint8_t LD3320_Init(void)
{
//	GPIO_InitTypeDef  GPIO_InitStructure;
//	__HAL_RCC_GPIOA_CLK_ENABLE();
//	__HAL_RCC_GPIOB_CLK_ENABLE();
//	
 	RCC_APB2PeriphClockCmd(LD3320_SDCK_GPIO_CLK|LD3320_SDO_GPIO_CLK|LD3320_SDI_GPIO_CLK|\
	LD3320_SCS_GPIO_CLK|LD3320_RSTB_GPIO_CLK|LD3320_IRQ_GPIO_CLK,ENABLE);	 //使能PA端口时钟  | RCC_APB2Periph_AFIO
	//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//要先开时钟,再重映射;关闭jtag,保留swd。
//	
//	
// 	GPIO_InitStructure.Pin = GPIO_PIN_5;				//端口配置
// 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 		  //推挽输出
// 	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
//	
//	GPIO_InitStructure.Pin = GPIO_PIN_7;				//端口配置
// 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 		  //推挽输出
// 	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
//	
//	GPIO_InitStructure.Pin = GPIO_PIN_4;				//端口配置
// 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 		  //推挽输出
// 	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
//	
//	GPIO_InitStructure.Pin = GPIO_PIN_15;				//端口配置
// 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 		  //推挽输出
// 	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
//	
//	GPIO_InitStructure.Pin = GPIO_PIN_6;				//端口配置
// 	GPIO_InitStructure.Mode = GPIO_MODE_INPUT; 		  //推挽输出
// 	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
//		
//	GPIO_InitStructure.Pin = GPIO_PIN_13;				//端口配置
// 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 		  //推挽输出
// 	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
//	
//	HAL_GPIO_WritePin(LD3320_WR_GPIO_Port,LD3320_WR_Pin,GPIO_PIN_RESET);//拉低WR引脚

//	/* GPIO Ports Clock Enable */
//	__HAL_RCC_GPIOB_CLK_ENABLE();
//	  /*Configure GPIO pin : PB12 */
//  GPIO_InitStructure.Pin = GPIO_PIN_12;
//  GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
//  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
//	
//	  /* EXTI interrupt init*/
//  HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,0);
//  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
	HAL_Delay(500);
	HAL_GPIO_WritePin(LD3320_RST_GPIO_Port,LD3320_RST_Pin,GPIO_PIN_SET);//拉低WR引脚
	HAL_GPIO_WritePin(LD3320_CS_GPIO_Port,LD3320_CS_Pin,GPIO_PIN_SET);//拉低WR引脚
	HAL_GPIO_WritePin(LD3320_WR_GPIO_Port,LD3320_WR_Pin,GPIO_PIN_RESET);//拉低WR引脚
	return LD3320_Check();
}

/***********************************************************
* 名    称:用户执行函数 
* 功    能:识别成功后,执行动作可在此进行修改 
* 入口参数: 无 
* 出口参数:无
* 说    明: 					 
**********************************************************/
void User_Modification(uint8_t dat)
{
	if(dat)
	{
		switch(nAsrRes)		   /*对结果执行相关操作,客户修改*/
		{
			case CODE_DMCS:			/*命令“代码测试”*/
					printf(" 代码测试 识别成功\r\n"); /*text.....*/
												break;
			case CODE_CSWB:			/*命令“测试完毕”*/
					printf(" 测试完毕 识别成功\r\n"); /*text.....*/
												break;
			
			case CODE_1KL1:	 /*命令“北京”*/
					printf(" 北京 识别成功\r\n"); /*text.....*/
												break;
			case CODE_1KL2:		/*命令“上海”*/
		
					printf(" 上海 识别成功\r\n"); /*text.....*/
												break;
			case CODE_1KL3:	 /*命令“开灯”*/
					printf(" 开灯 识别成功\r\n"); /*text.....*/
												break;
			case CODE_1KL4:		/*命令“关灯”*/				
					printf(" 关灯 识别成功\r\n"); /*text.....*/
												break;
			
			case CODE_2KL1:	 /*命令“....”*/
					printf(" 广州 识别成功\r\n"); /*text.....*/
												break;
			case CODE_2KL2:	 /*命令“....”*/
					printf(" 深圳 识别成功\r\n"); /*text.....*/
												break;
			case CODE_2KL3:	 /*命令“....”*/
					printf(" 向左转 识别成功\r\n"); /*text.....*/
												break;
			case CODE_2KL4:	 /*命令“....”*/
					printf(" 向右转 识别成功\r\n"); /*text.....*/
															break;
						
			case CODE_3KL1:	 /*命令“....”*/
					printf(" 打开空调 识别成功\r\n"); /*text.....*/
												break;
			case CODE_3KL2:	 /*命令“....”*/
					printf(" 关闭空调 识别成功\r\n"); /*text.....*/
												break;
			case CODE_5KL1:	 /*命令“....”*/
					printf(" 后退 识别成功"); /*text.....*/
												break;
//		case CODE_3KL4:	 /*命令“....”*/
//				printf("\"代码测试\"识别成功"); /*text.....*/
//											break;
//					
//					case CODE_4KL1:	 /*命令“....”*/
//							printf("O"); /*text.....*/
//														break;
//					case CODE_4KL2:	 /*命令“....”*/
//							printf("P"); /*text.....*/
//														break;
//					case CODE_4KL3:	 /*命令“....”*/
//							printf("Q"); /*text.....*/
//														break;
//					case CODE_4KL4:	 /*命令“....”*/
//							printf("R"); /*text.....*/
//														break;
			
			default:break;
		}
	}
	
}
/************************************************************************
功能描述: 	 复位LD模块
入口参数:	 none
返 回 值: 	 none
其他说明:	 none
**************************************************************************/
void LD_Reset(void)
{
	RST_HIGH;
	HAL_Delay(5);
	RST_LOW;
	HAL_Delay(5);
	RST_HIGH;
	
	HAL_Delay(5);
	CS_LOW;
	HAL_Delay(5);
	CS_HIGH;
	HAL_Delay(5);
}
/************************************************************************
功能描述: LD模块命令初始化
入口参数: none
返 回 值: none
其他说明: 该函数为出厂配置,一般不需要修改;
					 有兴趣的客户可对照开发手册根据需要自行修改。
**************************************************************************/
void LD_Init_Common(void)
{
	LD_ReadReg(0x06);  
	LD_WriteReg(0x17, 0x35);

	HAL_Delay(5);
	LD_ReadReg(0x06);  

	LD_WriteReg(0x89, 0x03); 
	HAL_Delay(5);
	LD_WriteReg(0xCF, 0x43);
	HAL_Delay(5);
	LD_WriteReg(0xCB, 0x02);
	
	/*PLL setting*/
	LD_WriteReg(0x11, LD_PLL_11);
	if (nLD_Mode == LD_MODE_MP3)
	{
		LD_WriteReg(0x1E,0x00);
		LD_WriteReg(0x19, LD_PLL_MP3_19); 
		LD_WriteReg(0x1B, LD_PLL_MP3_1B);		
		LD_WriteReg(0x1D, LD_PLL_MP3_1D);
	}
	else
	{
		LD_WriteReg(0x1E,0x00);
		LD_WriteReg(0x19, LD_PLL_ASR_19); 
		LD_WriteReg(0x1B, LD_PLL_ASR_1B);
	  LD_WriteReg(0x1D, LD_PLL_ASR_1D);
	}	
	HAL_Delay(5);
	
	LD_WriteReg(0xCD, 0x04);
	LD_WriteReg(0x17, 0x4c);
	HAL_Delay(5);
	LD_WriteReg(0xB9, 0x00);
	LD_WriteReg(0xCF, 0x4F);
	LD_WriteReg(0x6F, 0xFF);
}

/************************************************************************
功能描述: 	 LD模块 ASR功能初始化
入口参数:	 none
返 回 值: 	 none
其他说明:	 该函数为出厂配置,一般不需要修改;
					 有兴趣的客户可对照开发手册根据需要自行修改。
**************************************************************************/
void LD_Init_ASR(void)
{
	nLD_Mode=LD_MODE_ASR_RUN;
	LD_Init_Common();

	LD_WriteReg(0xBD, 0x00);
	LD_WriteReg(0x17, 0x48);
	HAL_Delay(5);

	LD_WriteReg(0x3C, 0x80);
	LD_WriteReg(0x3E, 0x07);
	LD_WriteReg(0x38, 0xff); 
	LD_WriteReg(0x3A, 0x07);
	
	LD_WriteReg(0x40, 0);
	LD_WriteReg(0x42, 8);
	LD_WriteReg(0x44, 0); 
	LD_WriteReg(0x46, 8);
	HAL_Delay(5);
}

/************************************************************************
功能描述: 	中断处理函数
入口参数:	 none
返 回 值: 	 none
其他说明:	当LD模块接收到音频信号时,将进入该函数,
						判断识别是否有结果,如果没有从新配置寄
            存器准备下一次的识别。
**************************************************************************/
void ProcessInt(void)
{
	uint8_t nAsrResCount=0;

	ucRegVal = LD_ReadReg(0x2B);
	LD_WriteReg(0x29,0) ;
	LD_WriteReg(0x02,0) ;
	if((ucRegVal & 0x10)&&LD_ReadReg(0xb2)==0x21&&LD_ReadReg(0xbf)==0x35)			/*识别成功*/
	{	
		nAsrResCount = LD_ReadReg(0xba);
		if(nAsrResCount>0 && nAsrResCount<=4) 
		{
			nAsrStatus=LD_ASR_FOUNDOK;
		}
		else
	  {
			nAsrStatus=LD_ASR_FOUNDZERO;
		}	
	}															 /*没有识别结果*/
	else
	{	 
		nAsrStatus=LD_ASR_FOUNDZERO;
	}
		
  LD_WriteReg(0x2b, 0);
  LD_WriteReg(0x1C,0);/*写0:ADC不可用*/
	LD_WriteReg(0x29,0);
	LD_WriteReg(0x02,0);
	LD_WriteReg(0x2B,0);
	LD_WriteReg(0xBA,0);	
	LD_WriteReg(0xBC,0);	
	LD_WriteReg(0x08,1);	 /*清除FIFO_DATA*/
	LD_WriteReg(0x08,0);	/*清除FIFO_DATA后 再次写0*/
}

/************************************************************************
功能描述:  检测LD模块是否空闲
入口参数:	none
返 回 值: 	flag:1-> 空闲
其他说明:	none
**************************************************************************/
uint8_t LD_Check_ASRBusyFlag_b2(void)
{
	uint8_t j,i;
	uint8_t flag = 0;
	for (j=0; j<5; j++)
	{
		i=LD_ReadReg(0xb2);
		if ( i== 0x21)
		{
			flag = 1;						
			break;
		}
		HAL_Delay(20);		
	}
	return flag;
}
/************************************************************************
功能描述: 	启动ASR
入口参数:	none
返 回 值: 	none
其他说明:	none
**************************************************************************/
void LD_AsrStart(void)
{
	LD_Init_ASR();
}
/************************************************************************
功能描述: 	运行ASR
入口参数:	none
返 回 值: 	1:启动成功
其他说明:	none
**************************************************************************/
uint8_t LD_AsrRun(void)
{
	LD_WriteReg(0x35, MIC_VOL);
	LD_WriteReg(0x1C, 0x09);
	LD_WriteReg(0xBD, 0x20);
	LD_WriteReg(0x08, 0x01);
	HAL_Delay(5);
	LD_WriteReg(0x08, 0x00);
	HAL_Delay(5);

	if(LD_Check_ASRBusyFlag_b2() == 0)
	{
		return 0;
	}

	LD_WriteReg(0xB2, 0xff);
	LD_WriteReg(0x37, 0x06);
	HAL_Delay(5);
    LD_WriteReg(0x37, 0x06);
	HAL_Delay(5);
	LD_WriteReg(0x1C, 0x0b);
	LD_WriteReg(0x29, 0x10);	
	LD_WriteReg(0xBD, 0x00);
	return 1;
}
/************************************************************************
功能描述: 向LD模块添加关键词
入口参数: none
返 回 值: flag:1->添加成功
其他说明: 用户修改.
					 1、根据如下格式添加拼音关键词,同时注意修改sRecog 和pCode 数组的长度
					 和对应变了k的循环置。拼音串和识别码是一一对应的。
					 2、开发者可以学习"语音识别芯片LD3320高阶秘籍.pdf"中
           关于垃圾词语吸收错误的用法,来提供识别效果。
**************************************************************************/
uint8_t LD_AsrAddFixed(void)
{
	uint8_t k, flag;
	uint8_t nAsrAddLength;
	
	#define DATE_A 14   //数组二维数值
	#define DATE_B 20		//数组一维数值
	
	
	uint8_t sRecog[DATE_A][DATE_B] = {
																		"xiao jie",\
																		"dai ma ce shi",\
																		"ce shi wan bi",\
		
																		"bei jing",\
																		"shang hai",\
																		"kai deng",\
																		"guan deng",\
		
																		"guang zhou",\
																		"shen zhen",\
																		"xiang zuo zhuan",\
																		"xiang you zhuan",\
		
																		"da kai kong tiao",\
																		"guan bi kong tiao",\
																		"hou tui",\
																 };	/*添加关键词,用户修改*/
	uint8_t pCode[DATE_A] = {
													CODE_CMD,\
													CODE_DMCS,\
													CODE_CSWB,\
												
													CODE_1KL1,\
		                      CODE_1KL2,\
		                      CODE_1KL3,\
		                      CODE_1KL4,\
		
													CODE_2KL1,\
		                      CODE_2KL2,\
		                      CODE_2KL3,\
		                      CODE_2KL4,\
		
													CODE_3KL1,\
		                      CODE_3KL2,\
													CODE_5KL1,
												};	/*添加识别码,用户修改*/	
	flag = 1;
	for (k=0; k<DATE_A; k++)
	{
			
		if(LD_Check_ASRBusyFlag_b2() == 0)
		{
			flag = 0;
			break;
		}
		
		LD_WriteReg(0xc1, pCode[k] );
		LD_WriteReg(0xc3, 0 );
		LD_WriteReg(0x08, 0x04);
		HAL_Delay(1);
		LD_WriteReg(0x08, 0x00);
		HAL_Delay(1);

		for (nAsrAddLength=0; nAsrAddLength<DATE_B; nAsrAddLength++)
		{
			if (sRecog[k][nAsrAddLength] == 0)
				break;
			LD_WriteReg(0x5, sRecog[k][nAsrAddLength]);
		}
		LD_WriteReg(0xb9, nAsrAddLength);
		LD_WriteReg(0xb2, 0xff);
		LD_WriteReg(0x37, 0x04);
	}
    return flag;
}

/************************************************************************
功能描述: 	运行ASR识别流程
入口参数:	none
返 回 值:  asrflag:1->启动成功, 0—>启动失败
其他说明:	识别顺序如下:
						1、RunASR()函数实现了一次完整的ASR语音识别流程
						2、LD_AsrStart() 函数实现了ASR初始化
						3、LD_AsrAddFixed() 函数实现了添加关键词语到LD3320芯片中
						4、LD_AsrRun()	函数启动了一次ASR语音识别流程					
						任何一次ASR识别流程,都需要按照这个顺序,从初始化开始
**************************************************************************/
uint8_t RunASR(void)
{
	uint8_t i=0;
	uint8_t asrflag=0;
	for (i=0; i<5; i++)			//	防止由于硬件原因导致LD3320芯片工作不正常,所以一共尝试5次启动ASR识别流程
	{
		LD_AsrStart();
		HAL_Delay(5);
		if (LD_AsrAddFixed()==0)
		{
			LD_Reset();			//	LD3320芯片内部出现不正常,立即重启LD3320芯片
			HAL_Delay(5);			//	并从初始化开始重新ASR识别流程
			continue;
		}
		delay_us(5);
		if (LD_AsrRun() == 0)
		{
			LD_Reset();			//	LD3320芯片内部出现不正常,立即重启LD3320芯片
			HAL_Delay(5);			//	并从初始化开始重新ASR识别流程
			continue;
		}	
		asrflag=1;
		break;					//	ASR流程启动成功,退出当前for循环。开始等待LD3320送出的中断信号
	}
	return asrflag;
}

/************************************************************************
功能描述: 	获取识别结果
入口参数:	none
返 回 值: 	LD_ReadReg(0xc5 );  读取内部寄存器返回识别码。
其他说明:	none
**************************************************************************/
uint8_t LD_GetResult(void)
{	
	return LD_ReadReg(0xc5 );
}

/*写寄存器*/
void LD_WriteReg(uint8_t address,uint8_t dataout)
{
	#ifndef USE_HAL_LIB
	uint8_t i = 0;
	uint8_t command=0x04;
	SCS = 0;
	delay_us(1);

	//write command
	for (i=0;i < 8; i++)
	{
		if (command & 0x80) 
			SDI = 1;
		else
			SDI = 0;
		
		delay_us(1);
		SDCK = 0;
		command = (command << 1);  
		delay_us(1);
		SDCK = 1;  
	}
	//write address
	for (i=0;i < 8; i++)
	{
		if (address & 0x80) 
			SDI = 1;
		else
			SDI = 0;
		delay_us(1);
		SDCK = 0;
		address = (address << 1); 
		delay_us(1);
		SDCK = 1;  
	}
	//write data
	for (i=0;i < 8; i++)
	{
		if (dataout & 0x80) 
			SDI = 1;
		else
			SDI = 0;
		delay_us(1);
		SDCK = 0;
		dataout = (dataout << 1); 
		delay_us(1);
		SDCK = 1;  
	}
	delay_us(1);
	SCS = 1;
	#else
	uint8_t tx_data[3];
	CS_LOW;
	delay_us(1);
	tx_data[0] = 0x04;
	tx_data[1] = address;
	tx_data[2] = dataout;
	SPI_RreadWrite_Data(tx_data,3);
	delay_us(1);
	CS_HIGH;
	#endif
}
/*读寄存器*/
uint8_t LD_ReadReg(uint8_t address)
{
	#ifndef USE_HAL_LIB
	uint8_t i = 0; 
	uint8_t datain =0 ;
	uint8_t temp = 0; 
	uint8_t command=0x05;
	SCS = 0;
	delay_us(1);

	//write command
	for (i=0;i < 8; i++)
	{
		if (command & 0x80) 
			SDI = 1;
		else
			SDI = 0;
		delay_us(1);
		SDCK = 0;
		command = (command << 1);  
		delay_us(1);
		SDCK = 1;  
	}

	//write address
	for (i=0;i < 8; i++)
	{
		if (address & 0x80) 
			SDI = 1;
		else
			SDI = 0;
		delay_us(1);
		SDCK = 0;
		address = (address << 1); 
		delay_us(1);
		SDCK = 1;  
	}
	delay_us(1);

	//Read
	for (i=0;i < 8; i++)
	{
		datain = (datain << 1);
		temp = SDO;
		delay_us(1);
		SDCK = 0;  
		if (temp == 1)  
			datain |= 0x01; 
		delay_us(1);
		SDCK = 1;  
	}

	delay_us(1);
	SCS = 1;
	return datain;
	#else
	uint8_t rx_data;
	uint8_t tx_data[3];

  CS_LOW;
	delay_us(1);
	tx_data[0] = 0x05;
	tx_data[1] = address;
	tx_data[2] = 0x00;
	rx_data = SPI_RreadWrite_Data(tx_data,3);
	delay_us(1);
	CS_HIGH;
	return rx_data;
	#endif
}

/************************************************************************
功能描述: 模块检测(检查寄存器的读写是否正确)
入口参数:	none
返 回 值:成功返回 0 ,失败返回1
其他说明:	none
**************************************************************************/
uint8_t LD3320_Check(void)
{
	uint8_t flag = 1;
	LD_Reset();//语音复位
	LD_ReadReg(0x6);
	LD_WriteReg(0x35, 0x33);
	LD_WriteReg(0x1b, 0x55);
	LD_WriteReg(0xb3, 0xaa);

	if(LD_ReadReg(0x35) == 0x33 && LD_ReadReg(0x1b) == 0x55 && LD_ReadReg(0xb3) == 0xaa)
	{
		flag = 0;
	}
	return flag;
}

/*中断回调函数*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == LD3320_IRQ_Pin)
	{
		if(HAL_GPIO_ReadPin(LD3320_IRQ_GPIO_Port,LD3320_IRQ_Pin) == GPIO_PIN_RESET)
		{
			ProcessInt(); 
			printf("SH\r\n");	
		}
	}
}

2、LD3320.H

#ifndef LD3320_H__
#define LD3320_H__

//#include "stm32f1xx_hal.h"
#include "main.h"

//	以下三个状态定义用来记录程序是在运行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   				24	/* 用户注意修改输入的晶振时钟大小 */
#define LD_PLL_11				(uint8_t)((CLK_IN/2.0)-1)
#define LD_PLL_MP3_19		0x0f
#define LD_PLL_MP3_1B		0x18
#define LD_PLL_MP3_1D   (uint8_t)(((90.0*((LD_PLL_11)+1))/(CLK_IN))-1)

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

#define MIC_VOL 0x43	 //咪头增益



//识别码客户修改处
#define CODE_CMD   0x00   //该命令码0x00用户不可进行修改。
#define CODE_DMCS  0x01		//代码测试
#define CODE_CSWB  0x02	  //测试完毕

#define CODE_1KL1 0x03
#define CODE_1KL2 0x04
#define CODE_1KL3 0x05
#define CODE_1KL4 0x06
                  
#define CODE_2KL1 0x18
#define CODE_2KL2 0x19
#define CODE_2KL3 0x1A
#define CODE_2KL4 0x1B
                  
#define CODE_3KL1 0x1C
#define CODE_3KL2 0x1D
#define CODE_3KL3 0x1E
#define CODE_3KL4 0x1F
                  
#define CODE_4KL1 0x20
#define CODE_4KL2 0x21
#define CODE_4KL3 0x22
#define CODE_4KL4 0x23

#define CODE_5KL1 0x24

#define RST_HIGH			HAL_GPIO_WritePin(LD3320_RST_GPIO_Port,LD3320_RST_Pin,GPIO_PIN_SET)
#define RST_LOW				HAL_GPIO_WritePin(LD3320_RST_GPIO_Port,LD3320_RST_Pin,GPIO_PIN_RESET)

#define SCK_HIGH			HAL_GPIO_WritePin(LD3320_SCK_GPIO_Port,LD3320_SCK_Pin,GPIO_PIN_SET)
#define SCK_LOW				HAL_GPIO_WritePin(LD3320_SCK_GPIO_Port,LD3320_SCK_Pin,GPIO_PIN_RESET)

#define MOSI_HIGH			HAL_GPIO_WritePin(LD3320_MOSI_GPIO_Port,LD3320_MOSI_Pin,GPIO_PIN_SET)
#define MOSI_LOW			HAL_GPIO_WritePin(LD3320_MOSI_GPIO_Port,LD3320_MOSI_Pin,GPIO_PIN_RESET)

#define IRQ_HIGH			HAL_GPIO_WritePin(LD3320_IRQ_GPIO_Port,LD3320_IRQ_Pin,GPIO_PIN_SET)
#define IRQ_LOW				HAL_GPIO_WritePin(LD3320_IRQ_GPIO_Port,LD3320_IRQ_Pin,GPIO_PIN_RESET)

#define CS_HIGH				HAL_GPIO_WritePin(LD3320_CS_GPIO_Port,LD3320_CS_Pin,GPIO_PIN_SET)
#define CS_LOW				HAL_GPIO_WritePin(LD3320_CS_GPIO_Port,LD3320_CS_Pin,GPIO_PIN_RESET)
void LD3320_main(void);

void User_Modification(uint8_t dat);
//函数声明
void LD_Reset(void);
void LD_Init_Common(void);
void LD_Init_ASR(void);
void ProcessInt(void);
void LD_AsrStart(void);
uint8_t LD_AsrRun(void);
uint8_t LD_AsrAddFixed(void);
uint8_t RunASR(void);
uint8_t LD_GetResult(void);

uint8_t LD3320_Init(void);
void LD_WriteReg(uint8_t address,uint8_t dataout);
uint8_t LD_ReadReg(uint8_t address);
uint8_t LD3320_Check(void);

#endif

3、主函数

  /* USER CODE BEGIN 2 */

  	printf("LD3320 START TEST\r\n");
	if(!LD3320_Init())
		printf("LD3320 init succ\r\n");
	else 
		printf("LD3320 init failed\r\n");
  
	HAL_GPIO_WritePin(GPIOC,LED_Pin,GPIO_PIN_RESET);
	HAL_Delay(200);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		LD3320_main();	  
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

若要更改语音输入关键词,可在LD3320.c中的LD_AsrAddFixed函数中增加拼音,并在文件最下面的回调函数中增添代码

七、原理讲解

【STM32】HAL库 STM32CubeMX教程十四---SPI

手把手教你使用STM32C8T6和LD3320(SPI通信版)

STM32CubeMX系列教程9:LD3320语音识别模块使用

八、源码提供:

【STM32+HAL】语音识别模块LD3320文章来源地址https://www.toymoban.com/news/detail-827695.html

到了这里,关于【STM32+HAL】语音识别模块LD3320(SPI版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32单片机与LD3320语音模块的交互方法

    在嵌入式系统中,STM32单片机广泛应用于各种应用领域。而LD3320语音模块是一种常用的语音识别与合成模块。本文将介绍如何在STM32单片机上与LD3320语音模块进行交互,并提供相应的源代码。 硬件连接 首先,我们需要将STM32单片机与LD3320语音模块进行正确的硬件连接。以下是

    2024年03月13日
    浏览(47)
  • 基于STM32和LD3320的智能语音识别柔光台灯设计

    毕业设计: (源程序+原理图+PCB+设计说明书+PPT) 原理图:Altium Designer 程序编译器:keil4/keil 5 编程语言:C语言 设计编号:Y001 资料下载链接 课题主要研究语音识别、按键识别、PWM波调节亮度、OLED屏幕显示四个模块,目前市面上语音识别的台灯大多仅是控制灯的亮灭,采用

    2023年04月10日
    浏览(32)
  • LD3320语音识别模块分析

       LD3320是非特定人语音识别芯片,即语音声控芯片。最多可以识别50条预先内置的指令。 识别原理  声音分帧:   声音是一种波,常见的mp3等格式都是压缩格式,必须转为非压缩的纯波形文件来处理,比如Windows PCM文件,也就是wav文件。wav文件李存储的除了一个文件头

    2024年02月05日
    浏览(81)
  • 单片机设计_语音识别分类智能垃圾桶(STM32 ESP8266 LD3320)

    想要更多项目私wo!!!         离线语音识别识别垃圾种类并且垃圾桶自动翻盖: 说出唤醒词“垃圾桶”后,再说一句垃圾名称,语音识别模块端识别到相应,便会将结果通过串口发送到STM32端,STM32端接着会发送打开相应垃圾桶盖的指令,6s后,垃圾桶盖自动关闭。

    2024年02月06日
    浏览(44)
  • 毕业设计 单片机语音识别分类智能垃圾桶(STM32 ESP8266 LD3320)

    离线语音识别识别垃圾种类并且垃圾桶自动翻盖: 说出唤醒词“垃圾桶”后,再说一句垃圾名称,语音识别模块端识别到相应,便会将结果通过串口发送到STM32端,STM32端接着会发送打开相应垃圾桶盖的指令,6s后,垃圾桶盖自动关闭。其中翻盖功能是通过STM32端控制舵

    2024年04月26日
    浏览(51)
  • 基于 STM32 的语音识别智能家居控制系统的设计(LD3320语音识别芯片+ESP8266 WIFI模块+DHT11温湿度采集+MQ系列 烟雾及可燃气体+蜂鸣器+步进电机模拟窗帘+OLED液晶显示+

    ## **基于 STM32 的语音识别智能家居控制系统的设计(LD3320语音识别芯片+ESP8266 WIFI模块(阿里云 或ONENET或局域网)+DHT11温湿度采集+MQ系列 烟雾及可燃气体+蜂鸣器+步进电机模拟窗帘+OLED液晶显示+手机APP)** 本文采用LD3320语音识别芯片+ESP8266 WIFI模块+DHT11温湿度采集+MQ系列 烟雾及可

    2024年02月04日
    浏览(37)
  • 基于LD3320的51智能遥控语音小车

    小车实物图  本实验基于51单片机和LD3320语音识别模块 小车能够实现遥控器直接控制,语音控制以及自动避障 涉及到的知识有:I/O口的配置(点亮led),定时器(循迹),串口通信(两个板子的连接),SPI同步通信(遥控器),中断(定时器中断和串口中断),PWM(循迹)

    2024年02月06日
    浏览(34)
  • STM32 HAL库 STM32CubeMX -- SPI

    SPI (Serial Peripheral Interface)协议,即串行外围设备接口,是一种高速全双工的通信总线。 它被广泛地使用在ADC、LCD 等设备与MCU 间,要求通讯速率较高的场合。 SPI 通讯使用3 条总线及片选线, 3 条总线分别为SCK、MOSI、MISO,片选线为SS(CS) ,它们的作用介绍如下: (1) SS( Slav

    2024年02月13日
    浏览(44)
  • STM32的HAL库SPI操作(master 模式)-根据时序图配置SPI

    SPI基本概念请自行百度,参考:百度百科SPI简介.我们讲重点和要注意的地方。 接线一一对应 也就是说主控的MISO,MOSI,SCLK,[CSn]分别和设备的MISO,MOSI,SCLK,[CSn]一一对应相连,不交叉,不交叉,不交叉…(重要的事情说三遍)。 这是无线模块CC2500的SPI接口时序,这里可以看到,从

    2024年02月06日
    浏览(35)
  • STM32 HAL库 SPI主从双机通信

    最近因为项目需求,需要在一块板子内实现一个主机和五个从机的通信; 主机平台选用的是STM32F407VGT6,从机平台选用的是STM32F103C8T6;通信总线选用的是SPI总线。在构想是觉得采用SPI进行主从通信会很简单,但在实际开发的过程中,各种坑,通信时而正常时而混乱。不过在不

    2024年01月17日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包