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

需求
基于上次完成空气质量传感器,利用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
		

<think>好的,我需要帮助用户查找与SU-03T语音模块相关的流程图、IT架构图和设计图。首先,我应该回顾已有的引用内容。根据引用[1],SU-03T被用于智能语音垃圾桶项目,提到了连接的硬件如STM32、红外传感器等,但没有直接提到流程图或架构图。引用[2]提到安信可VC系列模组的使用教程,包括接口和二次开发信息,但同样没有具体图表。 接下来,我需要考虑用户可能需要的信息类型。流程图可能涉及语音识别流程,比如从语音输入到指令输出的处理步骤。IT架构图可能展示模块与其他组件的交互,比如与微控制器、传感器和网络的连接。设计图可能涉及硬件连接或软件逻辑。 由于用户提到的资料来自引用[1]的实物、资料和论文,建议他们查阅论文或项目资料,通常这些文档会包含设计图。另外,SU-03T的官方文档或安信可的技术手册可能有架构图和流程图。用户还可以参考引用[2]提到的外设接口,如UART/I2C,来推断模块的集成方式。如果找不到现成的图表,可能需要根据模块的技术参数自行绘制,或联系供应商获取更多资源。</think>关于SU-03T语音模块的流程图、IT架构图及设计图,以下是建议的获取途径和分析: 1. **官方技术文档** SU-03T属于安信可VC系列模组,其[官方技术手册](https://docs.ai-thinker.com/vc)中通常包含模块工作流程图和接口架构图。例如: - **语音识别流程**:麦克风输入→音频预处理→关键词匹配→串口输出指令 - **硬件接口架构**:$$ \text{MCU} \xrightarrow{UART} \text{SU-03T} \xrightarrow{PWM} \text{舵机控制} $$[^2] 2. **项目论文与开源资料** 根据引用[1]提到的智能语音垃圾桶项目,其实物设计中SU-03T的连接逻辑可归纳为: ```plaintext 红外传感器 → STM32SU-03T(语音指令解析) → WIFI模块/舵机控制 ``` 具体硬件设计图建议在项目配套资料中查找GPIO引脚分配表。 3. **第三方开发社区** 在GitHub或电子论坛(如CSDN)搜索“SU-03T block diagram”,可找到开发者分享的以下典型架构: - **软件逻辑图**:语音训练→固件烧录→多指令绑定 - **通信协议流程图**:支持通过AT指令配置词条列表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值