STM32单片机基本原理与应用(十一)

语音识别实验

此实验采用STM32核心板+ LD3320模块,通过初始化LD3320并写入待识别关键词,对麦克风说出相应关键词,实现实训平台上的流水灯相应变化的效果。
LD3320 是一颗基于非特定人语音识别 (SI-ASR:Speaker-Independent Automatic Speech Recognition)技术的语音识别/声控芯片。提供了真正的单芯片语音识别解决方案。
LD3320 芯片上集成了高精度的 A/D 和 D/A 接口,不再需要外接辅助的Flash 和 RAM,即可以实现语音识别/声控/人机对话功能。并且,识别的关键词语列表是可以动态编辑的。
主要特色功能:
在这里插入图片描述

  • 非特定人语音识别技术:不需要用户进行录音训练。
  • 可动态编辑的识别关键词语列表:只需要把识别的关键词语以字符串的形式传送进芯片,即可以在下次识别中立即生效。
  • 真正单芯片解决方案:不需要任何外接的辅助 Flash 和 RAM,真正降低系统成本。
  • 内置高精度 A/D和D/A通道:不需要外接 AD 芯片,只需要把麦克风接在芯片的AD 引脚上;可以播放声音文件,并提供 550mW 的内置放大器。
  • 高准确度和实用的语音识别效果。
  • 支持用户自由编辑 50 条关键词语条:在同一时刻,最多在 50 条关键词语中进行识别,终端用户可以根据场景需要,随时编辑和更新这 50 条关键词语的内容。

程序代码

1、 LD3320创建语音识别任务,完成关键词的设置。

void   LD3320_Task(void)
{
  uint8_t   i=0;
  uint8_t  LD_ASR_Candi_Num,LD_ASR_EXTI_IFO; //从中断代码拿过来的
	char buf[20];
	uint8_t   j=1;	
	//测试读取寄存器	
	printf("LD3320_Task...\r\n");

	ETH_CS_H();
	VS_CS_H();
	LD_CS_K_H()	; //关掉底板上的LD3320  实训平台对比测试
   LD_WriteReg(0x29,0) ;   /*关闭中断*/
   LD_WriteReg(0x02,0) ;   
		
   //1 空闲状态;2 识别成功状态;3 识别失败状态。
 
  while(1)
  {    
    switch(process)
    { 
      case  0:         /*ld3320处于空闲状态*/
      i++;
      process=LD_Run();  
      if(i==4)
      {
        printf("语音识别模块内部故障,请检查硬件连接 \r\n");
        return;
      }
      break;

      case  1:          /*ld3320语音准备OK*/
	  
	  
      if(flag)          /*中断判断*/  //判断识别是否成功
      {          
        switch(direct)  /*对结果执行相关操作*/         
        {
          case 1:       /*命令“流水灯”*/
          printf(" 流水灯 指令识别成功\r\n");
          break;

          case 2:	      /*命令“闪烁”*/
          printf(" 闪烁 指令识别成功\r\n"); 
          break;

          case 3:	      /*命令“按键触发”*/
          printf(" 开灯/点灯  指令识别成功\r\n"); 
          break;

          case 4:		    /*命令“全灭”*/
          printf(" 全灭 指令识别成功\r\n");
          break;

          default:     
          break;
        } 
        process=flag=0;        
      }
      break;
      
      case  2:         /*ld3320语音识别失败*/
      i=0;
      if(flag)         /*中断判断*/
      {
        printf("未识别到有效信息或没有声音\r\n");
        process=flag=0;            
      } 
      break;      
                     
      default:
      break;  
    }
    
	  if((process==1)&&(LD_ReadReg(0xB2)==0x21) && (LD_ReadReg(0xbf)==0x35))	
	  {
		  printf("进入判断 原中断处理 \r\n");	
		  
		  flag=1;     //!!!!!!
		  
				LD_ASR_Candi_Num = LD_ReadReg(0xba); 
				if(LD_ASR_Candi_Num>0 && LD_ASR_Candi_Num<=4) 
				{ 
					direct = LD_ReadReg(0xc5);					
					process=1;    //识别成功    
					 
					printf("接收到的语音信息 %d \r\n",direct );  
				}else
				process=2;  //识别失败
	  
	  /*完成一次语音识别后重新配置寄存器*/
		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_Test();
   }
}

音乐播放器实验

单片机首先挂载FATS文件系统,接着在加载指定路径下的音频文件,最终通过VS1053解码并输出音频。VS1053采用SPI协议传输音频数据。但其还有两种不同的工作模式一种是串行数据接口的串行协议(SDI),一种是串行命令接口的串行协议(SCI)。所以片选有两个XCS and XDCS。
SCI 串行总线命令接口包含了一个指字节、一个地址字节和一个 16 位的数据字。读写操作可以读写单个寄存器,在 SCK 的上升沿读出数据位,所以主机必须在下降沿刷新数据SCI 的字节数据总是高位在前低位在后的。第一个字节指令字节, 只有 2 个指令,也就是读和写,读为0X03,写为 0X02。
在这里插入图片描述

对于SCI的读时序,是向 VS1053 读取数据,通过先拉低 XCS,然后发送读指令(0X03),再发送一个地址,最后,我们在 SO 线(VS_MISO)上就可以读到输出的数据了。而同时SI(VS_MOSI)上的数据将被忽略。
在这里插入图片描述
对于SCI的写时序,与读时序一样都是先发指令,再发地址。不过写时序中,我们的指令是写指令(0X02),并且数据是通过 SI 写入 VS1053的, SO 则一直维持低电平。在这两个图中,DREQ 信号上都产生了一个短暂的低脉冲,也就是执行时间。我们在写入和读出 VS1053 的数据之后,它需要一些时间来处理内部的事情,这段时间,是不允许外部打断的,所以,我们在 SCI 操作之前,最好判断一下DREQ 是否为高电平,如果不是,则等待 DREQ 变为高。

程序代码

这里我们仅对主函数进行展示:

int main(void)
 {	 
 
	delay_init();	    	 //延时函数初始化	  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
 	LED_Init();		  			//初始化与LED连接的硬件接口
//	 KEY_Init();					//初始化按键
	LCD_Init();			   		//初始化LCD     
//	W25QXX_Init();				//初始化W25Q128
	 

 	VS_Init();	  				//初始化VS1053 
 	my_mem_init(SRAMIN);		//初始化内部内存池
	exfuns_init();				//为fatfs相关变量申请内存  
// 	f_mount(fs[0],"0:",1); 		//挂载SD卡 
// 	f_mount(fs[1],"1:",1); 		//挂载FLASH.
	POINT_COLOR=RED;       
// 	while(font_init()) 				//检查字库
//	{	    
//		LCD_ShowString(30,50,200,16,16,"Font Error!");
//		delay_ms(200);				  
//		LCD_Fill(30,50,240,66,WHITE);//清除显示	     
//	}

	while(SD_Init())			//检测SD卡
		{
			LCD_ShowString(30,70,200,16,16,"SD Card Failed!");
			delay_ms(200);
			LCD_Fill(30,70,200+30,70+16,WHITE);
			delay_ms(200);		    
		}								 						    
		LCD_ShowString(30,70,200,16,16,"SD Card OK");

	 
 	Show_Str(30,50,200,16,"战舰 STM32实训平台",16,0);				    	 
	Show_Str(30,70,200,16,"音乐播放器实验",16,0);				    	 
	Show_Str(30,90,200,16,"正点原子@ALIENTEK",16,0);				    	 
	Show_Str(30,110,200,16,"2015年1月20日",16,0);
	Show_Str(30,130,200,16,"KEY0:NEXT   KEY2:PREV",16,0);
	Show_Str(30,150,200,16,"KEY_UP:VOL+ KEY1:VOL-",16,0);
	

	
	while(1)
	{
  		LED1=0; 	  
		Show_Str(30,170,200,16,"存储器测试...",16,0);
		printf("Ram Test:0X%04X\r\n",VS_Ram_Test());//打印RAM测试结果	    
		Show_Str(30,170,200,16,"正弦波测试...",16,0); 	 	 
 		VS_Sine_Test();	 
		Show_Str(30,170,200,16,"<<音乐播放器>>",16,0); 		 
		LED1=1;
		
		mp3_play();
		
	} 	   										    
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习笔记】优化算法——Adam算法

Adam算法 &#x1f3f7;sec_adam 本章我们已经学习了许多有效优化的技术。 在本节讨论之前&#xff0c;我们先详细回顾一下这些技术&#xff1a; 在 :numref:sec_sgd中&#xff0c;我们学习了&#xff1a;随机梯度下降在解决优化问题时比梯度下降更有效。在 :numref:sec_min…

从element-plus 引入ILoadingInstance 出现类型错误

具体报错如下图所示&#xff1a; 1、引入ILoadingInstance 出现错误&#xff1a; 解决问题如下所示&#xff1a; 可能是因为element-plus 多次升级原因&#xff0c;将原来的内部代码多次改下了&#xff0c;原来是loading.type文件&#xff0c;现在变成loading.js&#xff0c;包…

卷积神经网络必备基础

卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09; 传统的全连接神经网络并不适用于图像处理&#xff0c;这是因为&#xff1a;每个像素点都是一个输入特征&#xff0c;随着层数的增加&#xff0c;参数以指数级增长&#xff0c;而图片的像素点往往非常…

【STM32】HAL库 CubeMX 教程 --- 高级定时器 TIM1 定时

实验目标&#xff1a; 通过CUbeMXHAL&#xff0c;配置TIM1&#xff0c;1s中断一次&#xff0c;闪烁LED。 一、常用型号的TIM时钟频率 1. STM32F103系列&#xff1a; 所有 TIM 的时钟频率都是72MHz&#xff1b;F103C8不带基本定时器&#xff0c;F103RC及以上才带基本定时器。…

2024.3.10 win11系统设置环境变量的方法

2024.3.10 win11系统设置环境变量的方法 win11和其他版本略有区别&#xff0c;以安装maven为例进行操作。 一、鼠标右键点击下拉菜单中选择“个性化” 二、点击个性化中选项后在左侧菜单选择“系统” 三、在右侧系统项目中选择“系统信息” 四、在系统信息中选择“高级系统…

Android将自己写的maven库上传至jitpack(2024靠谱版)

浏览了一堆陈年旧贴&#xff0c;终于实验成功了 第一步 将自建空项目同步至github并保证能正常运行第二步新增一个library类型的modul第三步 在新建的library里面写一些测试用的代码第四步在library的gradle文件增加插件和发布脚本第五步新建一个配置文件第六步 把所有更改push…

面试题:分布式锁用了 Redis 的什么数据结构

在使用 Redis 实现分布式锁时&#xff0c;通常使用 Redis 的字符串&#xff08;String&#xff09;。Redis 的字符串是最基本的数据类型&#xff0c;一个键对应一个值&#xff0c;它能够存储任何形式的字符串&#xff0c;包括二进制数据。字符串类型的值最多可以是 512MB。 Re…

基于java+springboot+vue实现的火车票订票系统(文末源码+Lw)294

摘要 火车票订票系统可以对火车票订票系统信息进行集中管理&#xff0c;可以真正避免传统管理的缺陷。火车票订票系统是一款运用软件开发技术设计实现的应用系统&#xff0c;在信息处理上可以达到快速的目的&#xff0c;不管是针对数据添加&#xff0c;数据维护和统计&#xf…

SaulLM-7B: A pioneering Large Language Model for Law

SaulLM-7B: A pioneering Large Language Model for Law 相关链接&#xff1a;arxiv 关键字&#xff1a;Large Language Model、Legal Domain、SaulLM-7B、Instructional Fine-tuning、Legal Corpora 摘要 本文中&#xff0c;我们介绍了SaulLM-7B&#xff0c;这是为法律领域量…

Keepalived+LVS构建高可用集群

目录 一、Keepalive基础介绍 1. Keepalive与VRRP 2. VRRP相关技术 3. 工作原理 4. 模块 5. 架构 6. 安装 7. Keepalived 相关文件 7.1 配置组成 7.2 全局配置 7.3 VRRP实例配置&#xff08;lvs调度器&#xff09; 7.4 虚拟服务器与真实服务器配置 二、Keepalived…

用*把棱形画出来

输入一个整数n表示棱形的对角半长度&#xff0c;请你用*把这个棱形画出来。 输入&#xff1a;1输出&#xff1a;*输入&#xff1a;3输出&#xff1a;**** *********输入输出格式 输入描述: 输入一个整数n&#xff08;n < 10&#xff09;。 输出描述: 按题目要求输出字符棱…

Jobs Portal求职招聘系统源码v3.5版本

源码介绍: Jobs Portal 求职招聘系统 是为求职者和公司发布职位而开发的交互式求职招聘源码。它使求职者能够发布简历、搜索工作、查看个人工作列表。它将提供各种公司在网站上放置他们的职位空缺资料&#xff0c;并且还可以选择搜索候选人简历。除此之外&#xff0c;还有一个…

Jupyter Notebook使用教程——从Anaconda环境构建到Markdown、LaTex语法介绍

0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见解及成果&#xff0c;但是内容可能存在不准确的地方。如果发现文中错误&#xff0c;希望批评指正&#xff0c;共同进步。 你是否在视频教程或说明文档或Githu…

TC7.0简单编程十六进制跟十进制转化函数

写脚本的时候&#xff0c;没用内存的功能什么的&#xff0c;基本跟十六进制用得都比较少。最近因为易语言的一个代码要转化过来&#xff0c;看到易语言里面有现成的函数 16到10 跟10 到16&#xff0c;就想着TC是否也有这样的函数。找来找去没找到。其实TC也有这样的函数来的。藏…

misc49

下载附件是个txt文件&#xff0c;打开发现是个压缩包的头 后缀改成zip后打开 base解码无果&#xff0c;我们尝试字母解码 然后音符解码得到 ❀✿✼❇❃❆❇✿❁❇✻✿❀✾✿✻❀❊❆❃❀❊✻❅❀❄✼❂❊❊✾❇❁✽✽✼❁❂❀❀❀❉❃❂❀❉❃❂❊❊✾✼✻✻❀❆✻✻❀❀✻✻✿…

C#MQTT编程10--MQTT项目应用--工业数据上云

1、文章回顾 这个系列文章已经完成了9个内容&#xff0c;由浅入深地分析了MQTT协议的报文结构&#xff0c;并且通过一个有效的案例让伙伴们完全理解理论并应用到实际项目中&#xff0c;这节继续上马一个项目应用&#xff0c;作为本系列的结束&#xff0c;奉献给伙伴们&#x…

Visual Studio单步调试中监视窗口变灰的问题

在vs调试中&#xff0c;写了这样一条语句 while((nfread(buf, sizeof(float), N, pf))>0) 然而&#xff0c;在调试中&#xff0c;只要一执行while这条语句&#xff0c;监视窗口中的变量全部变为灰色&#xff0c;不能查看&#xff0c;是程序本身并没有报错&#xff0c;能够继…

简单了解一个数据包在网络的一生

在主题之前&#xff0c;我想先谈谈目前计算机的网络模型&#xff0c;主要谈谈 TCP/IP 模型&#xff1a; 应用层&#xff1a;产生最原始的数据&#xff0c;常见协议如 http、ftp、websocket、DNS、QUIC 传输层&#xff1a;传递应用层的数据给网络层&#xff0c;必要时进行切割&…

[Angular 基础] - 表单:响应式表单

[Angular 基础] - 表单&#xff1a;响应式表单 之前的笔记&#xff1a; [Angular 基础] - routing 路由(下) [Angular 基础] - Observable [Angular 基础] - 表单&#xff1a;模板驱动表单 开始 其实这里的表单和之前 Template-Driven Forms 没差很多&#xff0c;不过 Tem…

从16-bit 到 1.58-bit :大模型内存效率和准确性之间的最佳权衡

通过量化可以减少大型语言模型的大小&#xff0c;但是量化是不准确的&#xff0c;因为它在过程中丢失了信息。通常较大的llm可以在精度损失很小的情况下量化到较低的精度&#xff0c;而较小的llm则很难精确量化。 什么时候使用一个小的LLM比量化一个大的LLM更好? 在本文中&a…