STM32第八课:Su-03t语音识别模块

文章目录

  • 需求
  • 一、SU03T语音识别模块
  • 二、模块配置流程
    • 1.固件烧录
    • 2.配置串口和传输引脚
    • 3.中断函数
    • 4.double类型转换
    • 5 数据发送
    • 6.接收处理
  • 三、该模块完整代码
  • 总结


需求

基于上次完成空气质量传感器,利用SU03T语音识别模块,实现空气质量的语音问答播报。
在这里插入图片描述


一、SU03T语音识别模块

该模块是固件是通过智能公元设计的。
硬件层和协议层以及识别的语音指令也是由固件决定的。
所以使用前需要去该固件的官网进行设计烧录(www.smartpi.cn)

二、模块配置流程

思路:
1.硬件先检测语音指令,将语音指令发送给串口5。(AA 55 XX 55 AA)
2.串口5以10位为一组存到数组中。
3.校验指令是否正确(头尾固定)。
4.提取得到的指令数组中的第三位,进行判断是哪一个指令。
5.根据接收到的指令和外部声明的空气质量数据传输到指令拼接函数中。
6. 制作指令拼接函数,其中要将空气质量的double数据转换为8位16进制的。AA 55 04 00 00 00 00 00 80 37 40 55 AA
7. 将拼接好的数据发送给SU03T语音识别模块,进行播报。

1.固件烧录

1.先去智能公元的官网设计所需的语音指令和接口,本例程选取的以串口5 PC12(TX)和PD2(RX)进行数据的通信。设计完成后会生成一个bin二进制文件。
2.清空板子上的代码,然后利用板子上的ch340进行烧录。
在这里插入图片描述
具体步骤官方也有详细介绍文档,一步一步来就可以。

2.配置串口和传输引脚

该模块的协议层为:
波特率:9600
数据位8位
校验位 0 位
停止位1位

代码如下:

void Su03t_U5Config()//串口5 PC12(TX) PD2(RX)
{
	
		//开时钟U5 PD12(TX) PD2(RX)
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC,ENABLE);
	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
	  //配置PC12(TX)
		GPIO_InitTypeDef GPIO_InitStruct = {0};
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推完输出
		GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
		GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOC,&GPIO_InitStruct);
		//PD2(RX)
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
		GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOD,&GPIO_InitStruct);
		
  	//配置串口5  波特率9600 数据位8,校验位0,停止位1
		USART_InitTypeDef USART_InitStruct = {0};//可以通过结构体类型跳转
		USART_InitStruct.USART_BaudRate = 9600;//波特率
		USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件控制流不开
		USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//打开接收
		USART_InitStruct.USART_Parity = USART_Parity_No;
		USART_InitStruct.USART_StopBits = USART_StopBits_1;
		USART_InitStruct.USART_WordLength = USART_WordLength_8b;
		USART_Init(UART5,&USART_InitStruct);
	  //使能串口
		USART_Cmd(UART5,ENABLE);
   	//配置串口5的中断(采用中断接收)
		USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);//使能串口5	的接收非空中断
		USART_ITConfig(UART5,USART_IT_IDLE,ENABLE);//总线空闲中断
		NVIC_SetPriority(UART5_IRQn,6);//设置优先级0~15
		NVIC_EnableIRQ(UART5_IRQn);//使能中断通道
}

3.中断函数

首先,先创建一个结构体方便之后操作。
里面包含需要发送的10位数组、数组下标和数据类型。

typedef struct{
	uint8_t u5_recv[10];//保存数据数组
	uint8_t  u5_cnt;//数组下标
	uint8_t u5_tflag;
}UART5DATA;//数据类型

然后依旧是去启动文件中找到然后复制。
代码如下:

UART5DATA u5_data={0};
void UART5_IRQHandler()//串口5中断执行
{
		uint8_t data=0;
	//判断接收中断是否发生
	if(USART_GetITStatus(UART5,USART_IT_RXNE)==SET)
	{
		data = UART5->DR;
		//USART1->DR = data;//回显
		u5_data.u5_recv[u5_data.u5_cnt]=data;
		u5_data.u5_cnt++;
		u5_data.u5_cnt%=10;
	}
	//触发空闲中断,表示总线空闲,接收完毕
	if(USART_GetITStatus(UART5,USART_IT_IDLE)==SET)
	{
		data = UART5->SR;//清理空闲中断,先读SR再读DR
		data = UART5->DR;	
		u5_data.u5_tflag=1;
	}
}

该处串口5的中断用来接收数据,并把数据传送给数组里,每十个为一组。
空闲中断用来进行标志位置1,方便之后的程序进行判断。
u5_data.u5_tflag为1时,代表一组数据传输完成。

4.double类型转换

由于该串口接收的空气质量数据为double类型,而传输类型为8字节16进制,所以此时需要进行数据转换。

//将double数据转换成8位类型存放到数组arr中
void DoubleToUint8(double data,uint8_t *arr)
{
	
	uint8_t *p = (uint8_t *)&data;
	uint8_t i=0;
	for(i=0;i<8;i++)
	{
		arr[i]=p[i];
	printf("%02x ",*(p+i));
	}
	printf("\r\n");
	return;
}

5 数据发送

根据该语音模块要求进行数据拼接
在这里插入图片描述

//拼接指令函数 AA 55 04 00 00 00 00 00 80 37 40 55 AA
void Su03tSendMsg(uint8_t cmd,double data)
{
	uint8_t msg[13]={0};//存放要发送的指令
	msg[0]=0xAA;
	msg[1]=0x55;
	msg[2]=cmd;
	DoubleToUint8(data,&msg[3]);
	msg[11]=0x55;
	msg[12]=0xAA;
	//通过串口5发送
	U5_Sendarr(msg,13);
}

cmd为指令,data为数据。
不同的指令对应不同的语音播报数据
在这里插入图片描述
要将整合的数据进行发送,此时还需要构造两个串口5的发送函数

//串口5发送单字节函数
void Uart5Senddata(uint8_t data)
{
	//等待发送完成
	while(USART_GetFlagStatus(UART5,USART_FLAG_TC)==0);
	//如果上次发送完成,就发送
	USART_SendData(UART5,data);
}

//串口5发送数组函数
void U5_Sendarr(uint8_t * data,uint32_t len)
{
	uint32_t i=0;
	for(i=0;i<len;i++){
		Uart5Senddata(*data);
		data++;
	}
}

6.接收处理

将kqm处理后的数据进行外部声明,再判断头尾的固定值,查看是否有误,然后进行数据类型标志位判断,判断收到的指令要播报那个数据,最后记得释放结构体,防止重复播报。

extern float voc;
extern float ch2o;
extern float co2;
int Su03tDealData()
{
	
	if(u5_data.u5_tflag!=1)
	{
		return 1;
	}
	
	if(u5_data.u5_recv[0]!=0xAA||u5_data.u5_recv[1]!=0x55)
	{
		printf("数据帧头出错\r\n");
		return 2;
	}
		if(u5_data.u5_recv[4]!=0xAA||u5_data.u5_recv[3]!=0x55)
	{
		printf("数据帧尾出错\r\n");
		return 3;
	}	
	switch(u5_data.u5_recv[2])
	{
		case 1:printf("接收01,空气质量指令\r\n");
			Su03tSendMsg(1,voc);//voc
		break;
		case 2:	printf(" 接收02,甲醛指令\r\n");
		Su03tSendMsg(2,ch2o);//voc
			break;
		case 3:	printf(" 接收03,Co2指令\r\n");
		Su03tSendMsg(3,co2);//voc
			break;
	}
  memset(&u5_data,0,sizeof(u5_data));
	return 0;	
}

完成后在主函数中调用 :
Kqm_U4Config();//空气质量检测
Su03t_U5Config();//语音播报

在while(1)中调用:
KQM_DealData();//空气质量处理
Su03tDealData();
即可实现

三、该模块完整代码

su03t.c

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"
#include "su03t.h"

typedef struct{
	uint8_t u5_recv[10];//保存数据数组
	uint8_t  u5_cnt;//数组下标
	uint8_t u5_tflag;
}UART5DATA;//数据类型

void Su03t_U5Config()//串口5 PC12(TX) PD2(RX)
{
	
		//开时钟U5 PD12(TX) PD2(RX)
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC,ENABLE);
	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
	  //配置PC12(TX)
		GPIO_InitTypeDef GPIO_InitStruct = {0};
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推完输出
		GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
		GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOC,&GPIO_InitStruct);
		//PD2(RX)
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
		GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOD,&GPIO_InitStruct);
		
  	//配置串口5  波特率9600 数据位8,校验位0,停止位1
		USART_InitTypeDef USART_InitStruct = {0};//可以通过结构体类型跳转
		USART_InitStruct.USART_BaudRate = 9600;//波特率
		USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件控制流不开
		USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//打开接收
		USART_InitStruct.USART_Parity = USART_Parity_No;
		USART_InitStruct.USART_StopBits = USART_StopBits_1;
		USART_InitStruct.USART_WordLength = USART_WordLength_8b;
		USART_Init(UART5,&USART_InitStruct);
	  //使能串口
		USART_Cmd(UART5,ENABLE);
   	//配置串口4的中断(采用中断接收)
		USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);//使能串口4	的接收非空中断
		USART_ITConfig(UART5,USART_IT_IDLE,ENABLE);//总线空闲中断
		NVIC_SetPriority(UART5_IRQn,6);//设置优先级0~15
		NVIC_EnableIRQ(UART5_IRQn);//使能中断通道
}

//串口5发送单字节函数
void Uart5Senddata(uint8_t data)
{
	//等待发送完成
	while(USART_GetFlagStatus(UART5,USART_FLAG_TC)==0);
	//如果上次发送完成,就发送
	USART_SendData(UART5,data);
}

//串口5发送数组函数
void U5_Sendarr(uint8_t * data,uint32_t len)
{
	uint32_t i=0;
	for(i=0;i<len;i++){
		Uart5Senddata(*data);
		data++;
	}
}

UART5DATA u5_data={0};
void UART5_IRQHandler()//串口5中断执行
{
		uint8_t data=0;
	//判断接收中断是否发生
	if(USART_GetITStatus(UART5,USART_IT_RXNE)==SET)
	{
		data = UART5->DR;
		//USART1->DR = data;//回显
		u5_data.u5_recv[u5_data.u5_cnt]=data;
		u5_data.u5_cnt++;
		u5_data.u5_cnt%=10;
	}
	//触发空闲中断,表示总线空闲,接收完毕
	if(USART_GetITStatus(UART5,USART_IT_IDLE)==SET)
	{
		data = UART5->SR;//清理空闲中断,先读SR再读DR
		data = UART5->DR;	
		u5_data.u5_tflag=1;
	}
}

//将double转换成8位类型数组arr
void DoubleToUint8(double data,uint8_t *arr)
{
	
	uint8_t *p = (uint8_t *)&data;
	uint8_t i=0;
	for(i=0;i<8;i++)
	{
		arr[i]=p[i];
	printf("%02x ",*(p+i));
	}
	printf("\r\n");
	return;
}

extern float voc;
extern float ch2o;
extern float co2;
int Su03tDealData()
{
	
	if(u5_data.u5_tflag!=1)
	{
		return 1;
	}
	
	if(u5_data.u5_recv[0]!=0xAA||u5_data.u5_recv[1]!=0x55)
	{
		printf("数据帧头出错\r\n");
		return 2;
	}
		if(u5_data.u5_recv[4]!=0xAA||u5_data.u5_recv[3]!=0x55)
	{
		printf("数据帧尾出错\r\n");
		return 3;
	}	
	switch(u5_data.u5_recv[2])
	{
		case 1:printf("接收01,空气质量指令\r\n");
			Su03tSendMsg(1,voc);//voc
		break;
		case 2:	printf(" 接收02,甲醛指令\r\n");
		Su03tSendMsg(2,ch2o);//voc
			break;
		case 3:	printf(" 接收03,Co2指令\r\n");
		Su03tSendMsg(3,co2);//voc
			break;
	}
  memset(&u5_data,0,sizeof(u5_data));
	return 0;
}

//拼接指令函数 AA 55 04 00 00 00 00 00 80 37 40 55 AA
void Su03tSendMsg(uint8_t cmd,double data)
{
	uint8_t msg[13]={0};//存放要发送的指令
	msg[0]=0xAA;
	msg[1]=0x55;
	msg[2]=cmd;
	DoubleToUint8(data,&msg[3]);
	msg[11]=0x55;
	msg[12]=0xAA;
	//通过串口5发送
	U5_Sendarr(msg,13);
}

su03t.h

#ifndef _SU03T_H_
#define _SU03T_H_
#include "stm32f10x.h"
void Su03t_U5Config();
void Uart5Senddata(uint8_t data);
void U5_Sendarr(uint8_t * data,uint32_t len);
void UART5_IRQHandler();
void DoubleToUint8(double data,uint8_t *arr);
int Su03tDealData();
void Su03tSendMsg(uint8_t cmd,double data);
#endif
		

总结

1.学会了如何配置半成品模块。
2.学会了如何根据需求进行数据处理和类型转换。

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

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

相关文章

代发考生战报:6月25号 南宁 HCIP-Transmission传输 H31-341考试884分通过

代发考生战报&#xff1a;6月25号 南宁 HCIP-Transmission传输 H31-341考试884分通过 &#xff0c;今天我和同事两个人去考的&#xff0c;我考试遇到1个新题&#xff0c;他遇到两个新题&#xff0c;客服提供的题库很稳定&#xff0c;全覆盖了&#xff0c;轻松通过&#xff0c;考…

EBS请求通过一段SQL输出EXCEL文件

一.设计初衷 1.EBS请求输出excel文件常用的有3种模式: 1.1.RTF模板XML数据源 1.2 package输出html格式 1.3 package输出excel对应的xml文本 2.上面三种模式开发起来都比较麻烦&#xff0c;而且输出的是xls的文件&#xff0c;如果导出的数据很多&#xff0c;文件特别大。 3.…

Go-知识测试-单元测试

Go-知识测试-单元测试 1. 定义2. 使用3. testing.common 测试基础数据4. testing.TB 接口5. 单元测试的原理5.1 context 单元测试的调度5.1.1 等待并发执行 testContext.waitParallel5.1.2 并发测试结束 testContext.release 5.2 测试执行 tRunner5.3 启动测试 Run5.4 启动并发…

<电力行业> - 《第9课:输电(二)》

4 输送电能流程 输送电能总共有&#xff1a;发电站→升压变压器→高压输电线→降压变压器→用电单位等五个流程。 电力工业初期&#xff0c;发电厂建在电力用户附近&#xff0c;直接向用户送电&#xff0c;所以那个时候只有发电和用电两个环节。 随着电力生产规模和负荷中心规…

基于MongoDB的电影影评分析

项目源码及资料 项目介绍 1、从豆瓣网爬取Top10的电影数据 爬取网址: https://movie.douban.com/top250 1.1 爬取Top10的影视信息 mv_data [] i 0 for x in soup.select(.item):i 1mv_name re.search(>([^<])<, str(x.select(.info > .hd > a > .tit…

ASP.NET Core 6.0 使用 Action过滤器

Action过滤器 在ASP.NET Core中&#xff0c;Action过滤器用于在执行Action方法之前或之后执行逻辑。你可以创建自定义的Action过滤器来实现这一点。 继承 ActionFilterAttribute 类&#xff1a; [TypeFilter(typeof(CustomAllActionResultFilterAttribute))]public IActionRe…

Pc端多功能视频混剪工具/便携版打开即用

PC便携版 视频批量剪辑大师&#xff0c;全自动剪辑神器&#xff0c;会打字就能做视频 多功能&#xff0c;视频混剪&#xff0c;视频配音&#xff0c;文字生成语音&#xff0c;图片合成视频&#xff0c;自动识别音频并生成字幕等功能 链接&#xff1a;https://pan.baidu.com/…

【原创实现 设计模式】Spring+策略+模版+工厂模式去掉if-else,实现开闭原则,优雅扩展

1 定义与优点 1.1 定义 策略模式&#xff08;Strategy Pattern&#xff09;属于对象的⾏为模式。他主要是用于针对同一个抽象行为&#xff0c;在程序运行时根据客户端不同的参数或者上下文&#xff0c;动态的选择不同的具体实现方式&#xff0c;即类的行为可以在运行时更改。…

代码随想录算法训练营第四十七天| 188.买卖股票的最佳时机IV ,309.最佳买卖股票时机含冷冻期 ,714.买卖股票的最佳时机含手续费

188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09; class Solution {public int maxProfit(int k, int[] prices) {int[][] dp new int[prices.length][2*k];for(int i0;i<2*k;i){if(i%2 0){dp[0][i] -prices[0];}else{dp[0][i] 0;} }for(int i1;i…

C语言 | Leetcode C语言题解之第206题反转链表

题目&#xff1a; 题解&#xff1a; struct ListNode* reverseList(struct ListNode* head) {if (head NULL || head->next NULL) {return head;}struct ListNode* newHead reverseList(head->next);head->next->next head;head->next NULL;return newHea…

使用Java连接数据库并且执行数据库操作和创建用户登录图形化界面(3)专栏里有上两步的源代码

创建用户登录程序&#xff0c;验证用户账号和密码信息是否在数据库student中的用户表tb_account中存在。用户登录界面如下图所示&#xff1a; 当单击“登录”按钮时&#xff0c;处理以下几种情况&#xff1a; &#xff08;1&#xff09;用户名未输入&#xff0c;提示用户名不能…

Apache Ranger 2.4.0 安装部署

1、安装ranger admin 2、源码编译Ranger wget https://www.apache.org/dist/ranger/2.4.0/apache-ranger-2.4.0.tar.gz tar zxvf apache-ranger-2.4.0.tar.gz cd apache-ranger-2.4.0 mvn -Pall clean mvn clean package -DskipTests maven settting可以设置阿里云进行资源下载…

【漏洞复现】金和OA 未授权访问

【产品介绍】 金和OA协同办公管理系统C6软件&#xff08;简称金和OA&#xff09;&#xff0c;本着简单、适用、高效的原则&#xff0c;贴合企事业单位的实际需求&#xff0c;实行通用化、标准化、智能化、人性化的产品设计&#xff0c;充分体现企事业单位规范管理、提高办公效…

fiddler抓包工具

概念 概念&#xff1a; Fiddler是一个http协议调试代理工具&#xff0c;它能够记录并检查所有你的电脑和互联网之间的http通讯。 http&#xff1a;不加密&#xff0c;端口为80 https&#xff1a;加密&#xff0c;端口为443 原理&#xff1a; 其实就在访问服务器时&#xff0…

Python逻辑控制语句 之 判断语句--if语句的基本结构

1.程序执行的三大流程 顺序 分支&#xff08;判断&#xff09; 循环 2.if 语句的介绍 单独的 if 语句,就是 “如果 条件成⽴,做什么事” 3.if 语句的语法 if 判断条件: 判断条件成立&#xff0c;执行的代码…

reactor网络模型的原理与实现

一、rector网络模型 对高并发编程&#xff0c;网络连接上的消息处理&#xff0c;可以分为两个阶段&#xff1a;等待消息准备好、消息处理。当使用默认的阻塞套接字时&#xff0c;往往是把这两个阶段合而为一&#xff0c;这样操作套接字的代码所在的线程就得睡眠来等待消息准备好…

【工具分享】Nuclei

文章目录 NucleiLinux安装方式Kali安装Windows安装 Nuclei Nuclei 是一款注重于可配置性、可扩展性和易用性的基于模板的快速漏洞验证工具。它使用 Go 语言开发&#xff0c;具有强大的可配置性、可扩展性&#xff0c;并且易于使用。Nuclei 的核心是利用模板&#xff08;表示为简…

【文档智能】DLAFormer:端到端的解决版式分析、阅读顺序方法

前言 前面文章介绍到&#xff0c;文档智能中版式分析(DLA)&#xff08;《【文档智能 & RAG】RAG增强之路&#xff1a;增强PDF解析并结构化技术路线方案及思路》&#xff09;、阅读顺序&#xff08;《【文档智能】符合人类阅读顺序的文档模型-LayoutReader及非官方权重开源…

抖音短视频seo矩阵系统源代码开发系统架构及功能解析

一、矩阵运营系统开发背景: 在数字化经营的浪潮中&#xff0c;抖音开放平台以其独特的影响力和广泛覆盖的用户群体&#xff0c;成为了企业不可忽视的数字营销阵地。然而&#xff0c;企业在享受抖音带来的巨大流量红利的同时&#xff0c;也面临着多账号管理运营协同效率低下、数…

Ollama中文版部署

M1部署Ollama Ollama中文网站: Featured - 精选 - Ollama中文网 下载网址: Download Ollama on macOS 安装后运行llma3模型: ollama run llama3:8b 界面使用: GitHub - open-webui/open-webui: User-friendly WebUI for LLMs (Formerly Ollama WebUI) 部署open-webui: do…