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,停止位1USART_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~15NVIC_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再读DRdata = 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);//vocbreak;case 2:	printf(" 接收02,甲醛指令\r\n");Su03tSendMsg(2,ch2o);//vocbreak;case 3:	printf(" 接收03,Co2指令\r\n");Su03tSendMsg(3,co2);//vocbreak;}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,停止位1USART_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~15NVIC_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再读DRdata = 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);//vocbreak;case 2:	printf(" 接收02,甲醛指令\r\n");Su03tSendMsg(2,ch2o);//vocbreak;case 3:	printf(" 接收03,Co2指令\r\n");Su03tSendMsg(3,co2);//vocbreak;}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.学会了如何根据需求进行数据处理和类型转换。

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

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

相关文章

从零开始:如何设计一个现代化聊天系统

写在前面: 此博客内容已经同步到我的博客网站,如需要获得更优的阅读体验请前往https://mainjaylai.github.io/Blog/blog/system/chat-system 在当今数字化时代,聊天系统已成为我们日常生活和工作中不可或缺的一部分。从个人交流到团队协作,从客户服务到社交网络,聊天应用…

HY Lisp 读取宏(reader macro)学习

在学习HY lisp语言的时候HY编程快速入门实践课第三章 HY宏入门-CSDN博客&#xff0c;学习到了读取宏&#xff08;reader macro&#xff09;&#xff0c;尝试将其概念弄明白。 首先&#xff0c;读取宏是Lisp语言中都有的一种概念&#xff0c;所以可以通过任意一种Lisp语言的文档…

免费可视化工具如何提升智慧物流管理效率

在现代智慧物流中&#xff0c;免费可视化工具正扮演着越来越重要的角色。这些工具通过数据的可视化展示&#xff0c;使物流管理更加高效、透明和智能化。免费可视化工具可以将复杂的物流数据转换为直观的图表和图形&#xff0c;帮助管理者实时监控和分析物流运作情况&#xff0…

九浅一深Jemalloc5.3.0 -- ⑥浅*boot

目前市面上有不少分析Jemalloc老版本的博文&#xff0c;但最新版本5.3.0却少之又少。而且5.3.0的架构与5之前的版本有较大不同&#xff0c;本着“与时俱进”、“由浅入深”的宗旨&#xff0c;我将逐步分析最新release版本Jemalloc5.3.0的实现。 另外&#xff0c;单讲实现代码是…

第二证券:可转债基础知识?想玩可转债一定要搞懂的交易规则!

可转债&#xff0c;全称是“可转化公司债券”&#xff0c;是上市公司为了融资&#xff0c;向社会公众所发行的一种债券&#xff0c;具有股票和债券的双重特点&#xff0c;投资者可以选择按照发行时约定的价格将债券转化成公司一般股票&#xff0c;也可作为债券持有到期后收取本…

Load Tensor to local Nvidia GPU

0. 安装Nvidia驱动 ubuntu24.04的安装非常简单&#xff0c;在安装界面&#xff0c;选择为"图形化和其他硬件安装驱动"&#xff0c;重启后即有原版Nvidia驱动(如图Nvidia X xxx) 1.确定电脑上是否有NvidiaGPU且安装好Nvidia驱动 import torch print(torch.version…

机器学习 C++ 的opencv实现SVM图像二分类的训练 (二)【附源码】

本节讲机器学习 C 的opencv实现SVM图像二分类的训练&#xff0c;下节讲测试&#xff1a; 数据集合data内容如下&#xff1a; 下载地址为&#xff1a;https://download.csdn.net/download/hgaohr1021/89506900 #include <stdio.h> #include <time.h> #include…

【Python机器学习系列】建立决策树模型预测小麦品种(案例+源码)

这是我的第314篇原创文章。 一、引言 对于表格数据&#xff0c;一套完整的机器学习建模流程如下&#xff1a; 针对不同的数据集&#xff0c;有些步骤不适用&#xff0c;其中橘红色框为必要步骤&#xff0c;欢迎大家关注翻看我之前的一些相关文章。前面我介绍了机器学习模型的二…

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(六)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

美术馆预约小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;展品信息管理&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;美术馆管理&#xff0c;基础数据管理&#xff0c;论坛管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;美术馆&#xff…

[C/C++] -- gdb调试与coredump

1.gdb调试 GDB&#xff08;GNU 调试器&#xff09;是一个强大的工具&#xff0c;用于调试程序。 安装 1. wget http://ftp.gnu.org/gnu/gdb/gdb-8.1.tar.gz 2. tar -zxvf gdb-8.1.1.tar.gz 3. cd gdb-8.1.1 4. ./configure 5. make 6. make install 基础用法 …

vue3.0(十六)axios详解以及完整封装方法

文章目录 axios简介1. promise2. axios特性3. 安装4. 请求方法5. 请求方法别名6. 浏览器支持情况7. 并发请求 Axios的config的配置信息1.浏览器控制台相关的请求信息&#xff1a;2.配置方法3.默认配置4.配置的优先级5.axios请求响应结果 Axios的拦截器1.请求拦截2.响应拦截3.移…

回流焊常见缺陷

不润湿(Nonwetting)/润湿不良(Poor Wetting) 通常润湿不良是指焊点焊锡合金没有很好的铺展开来,从而无法得到良好的焊点并直接影响到焊点的可靠性。 产生原因: 1. 焊盘或引脚表面的镀层被氧化,氧化层的存在阻挡了焊锡与镀层之间的接触; 2. 镀层厚度不够或是加工不良,很…

常见测试测量接口的比较:PXI、PXIe、PCI、VXI、GPIB、USB

详细比较了六种常见的测试测量接口&#xff1a;PXI、PXIe、PCI、VXI、GPIB、USB。每种接口都有其独特的特点和应用场景。通过比较它们的性能、带宽、模块化程度和应用领域&#xff0c;帮助工程师选择最适合其测试需求的接口类型。 1. PXI&#xff08;PCI eXtensions for Instru…

uboot 编译时传递参数实现条件编译

KCFLAGS make ARCHarm KCFLAGS-DENV_DEBUG CROSS_COMPILEaarch64-linux-gnu-env/sf.c env_sf_save 加入调试信息 # saveenv Saving Environment to SPI Flash... env_sf_save (1) spi_flash_erase (2) spi_flash_write is40000 Erasing SPI flash...Writing to SPI flash.…

试用笔记之-Delphi xe 微信/支付宝支付源代码

首先delphi xe 微信/支付宝支付源代码下载&#xff1a; http://www.htsoft.com.cn/download/DelphiXEWeiXin_ZhiFuBao_ZhiFu.rar 解压后可以看到源代码 直接执行可执行文件&#xff1a;

大模型技术在辅助学习中的应用

大模型技术在辅助学习中的应用场景非常广泛&#xff0c;以下是一些典型示例。大模型技术在辅助学习中具有广阔的应用前景&#xff0c;可以为学生提供更加个性化、智能化和高效的学习体验。随着大模型技术的不断发展&#xff0c;我们可以期待在未来看到更多创新应用。北京木奇移…

【Python】已解决:ERROR: No matching distribution found for JPype1

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ERROR: No matching distribution found for JPype1 一、分析问题背景 在安装Python的第三方库时&#xff0c;有时会遇到“ERROR: No matching distribution fo…

前端技术(说明篇)

Introduction ##编写内容&#xff1a;1.前端概念梳理 2.前端技术种类 3.前端学习方式 ##编写人&#xff1a;贾雯爽 ##最后更新时间&#xff1a;2024/07/01 Overview 最近在广州粤嵌进行实习&#xff0c;项目名称是”基于Node实现多人聊天室“&#xff0c;主要内容是对前端界…