首页 > 其他分享 >stm32实战之su-03t语音模块固件的制作与烧录

stm32实战之su-03t语音模块固件的制作与烧录

时间:2024-01-04 20:33:02浏览次数:37  
标签:NVIC 烧录 usart USART su stm32 TXpacket GPIO

su-03t简介

SU-03T 是一款低成本、低功耗、小体积的离线语音识别模组,能快速应用于智能家居,各类智能小家电,86 盒,玩具,灯具等需要语音操控的产品,SU-03T也具备强大的软件开发能力,我们可以在“智能公元”平台上实现语音固件的零代码开发,提高工作效率。

管脚定义

stm32实战之su-03t语音模块固件的制作与烧录_su-03t

stm32实战之su-03t语音模块固件的制作与烧录_例程分享_02

stm32实战之su-03t语音模块固件的制作与烧录_su-03t_03

其中需要注意的是UART0的B0、B1是调试器的语音固件烧录口,串口烧录则选择UART1的B6、B7引脚,当固件烧录完成之后则可以使用UART1的B2、B3 引脚和MCU进行通信。

智能公元语音固件制作

创建产品

stm32实战之su-03t语音模块固件的制作与烧录_例程分享_04

stm32实战之su-03t语音模块固件的制作与烧录_语音固件的制作和烧录_05

stm32实战之su-03t语音模块固件的制作与烧录_语音固件的制作和烧录_06

产品配置

创建产品成功后会进入产品配置,在大部分情况下都可以使用默认配置,我们只需要关注以下几个配置即可:

唤醒词自定义

唤醒词自定义可以定义语音模块的唤醒词以及唤醒之后的回复,用于唤醒语音模块,开始使用自定义命令词与模块进行语音交互

stm32实战之su-03t语音模块固件的制作与烧录_su-03t_07

命令词自定义

命令词自定义可以自己定义的关键词来控制语音模块,例如“开灯”、“关灯”等,免唤醒的命令词可以不需要使用唤醒词直接和模块进行交互。

stm32实战之su-03t语音模块固件的制作与烧录_su-03t_08

stm32实战之su-03t语音模块固件的制作与烧录_MCU_09

发音人配置

发音人配置可以用来配置语音模块的音色、音调和语速。

stm32实战之su-03t语音模块固件的制作与烧录_例程分享_10

其他配置

stm32实战之su-03t语音模块固件的制作与烧录_例程分享_11

生成和下载语音固件

stm32实战之su-03t语音模块固件的制作与烧录_例程分享_12

stm32实战之su-03t语音模块固件的制作与烧录_语音固件的制作和烧录_13

固件烧录(串口)

下载SDK固件烧录工具

stm32实战之su-03t语音模块固件的制作与烧录_MCU_14

在SDK固件包的 uni_hb_m_solution-121028-20230920\uni_hb_m_solution\image_demo\Hummingbird-M-Update-Tool 下可以看到以下文件

stm32实战之su-03t语音模块固件的制作与烧录_su-03t_15

UniOneUpdateTool.exe为串口烧录工具

USB_Update_Tool_User_Guide.pdf为烧录指导书,写的很详细,跟着烧录即可

SU-03T驱动分享

#include "su_03t.h"

uint8_t usart_su_RXdata;		//存放接收数据寄存器的值
uint8_t usart_su_RXflag;		//接收数据标志位
uint8_t usart_su_RXpacket[6] = {0};	//hex数据包接收数组
uint8_t usart_su_TXpacket[14] = {0};	//hex数据包接收数组

/**
  * @brief  配置串口 PC10 发送复用推挽    PC11 接收浮空模式  
  * @param  None
  * @retval None
  */
void su_o3t_init(void){
	//初始化GPIO口
	//PA9复用推挽
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  	GPIO_InitTypeDef GPIO_InitStructure;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_Init(GPIOC, &GPIO_InitStructure);
	//PA10浮空
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	  GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	//串口初始化
	//开启串口时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
	//初始化串口
	USART_InitTypeDef USART_InitStruct = {0};
	USART_InitStruct.USART_BaudRate = 115200;	//设置波特率
	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;	//字长选择8位
	USART_Init(UART4, &USART_InitStruct);
	
	//开启串口中断
	USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
	
		//初始化NVIC
		//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  	NVIC_InitTypeDef NVIC_InitStruct;
  	NVIC_InitStruct.NVIC_IRQChannel = UART4_IRQn;
  	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 4;
  	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
  	NVIC_Init(&NVIC_InitStruct);
	
	//使能串口
	USART_Cmd(UART4, ENABLE);
}

/**
  * @brief  串口一中断服务函数,接收一个字节的数据,并将标志位置1
	*       hex数据包		长度  6 		开始标志位 0xAA 
  * @param  None
  * @retval None
  */
void UART4_IRQHandler(void){
	static uint8_t RX_su_State = 0;
	static uint8_t su_pRXpacket = 0;
	//usart_init();
	if(USART_GetITStatus(UART4, USART_IT_RXNE) == SET){
		USART_ClearITPendingBit(UART4, USART_IT_RXNE);
			//usart_send_string("y");

		usart_su_RXdata = USART_ReceiveData(UART4);
		//判断接收的数据包头
		if(RX_su_State == 0){	
			if(usart_su_RXdata == 0XAA){	//接收到的使hex文件
				usart_su_RXpacket[0] = usart_su_RXdata;
				RX_su_State = 1;	
				su_pRXpacket = 1;
			}
		}
			else if(RX_su_State == 1){	//接收hex文件的内容
				usart_su_RXpacket[su_pRXpacket] = usart_su_RXdata;
				su_pRXpacket++;
				if(su_pRXpacket >= 5){		//接收数据包长度位4的数据
					RX_su_State = 2;
				}
			}
			else if(RX_su_State == 2){	//判断hex数据包结束标志位
				if(usart_su_RXdata == 0XAA){
					usart_send_array(USART1, usart_su_RXpacket,6);
					usart_su_RXpacket[su_pRXpacket] = usart_su_RXdata;
					RX_su_State = 0;
					usart_su_RXflag = 1;
				}
				else{
					RX_su_State = 0;
					usart_su_RXflag = 0;
					usart_send_array(USART1, usart_su_RXpacket,6);
					usart_su_RXpacket[su_pRXpacket] = usart_su_RXdata;
					//usart_send_string("$");
				}
			}
	}
}

/**
  * @brief  获取usart_su_flag的值
  * @param  None
  * @retval usart_su_RXflag 串口2接收标志位 
  */
uint8_t usart_get_su_RXflag(void){
	if(usart_su_RXflag == 1){
		usart_su_RXflag = 0;
		return 1;
	}
	return 0;
}
/**
  * @brief  处理su_03t的数据
  * @param  None
  * @retval None
  */
void vioce_analysis(void){
	//usart_send_array(usart_su_RXpacket, 5);

	time_t rawtime;
	struct tm *info = NULL;
	//info = localtime(&rawtime);
	if(usart_get_su_RXflag() == 1){
		//char str[5] = {0};
		switch(usart_su_RXpacket[3]){
			case 0x01: //温度
				usart_su_TXpacket[0] = 0XAA;
				usart_su_TXpacket[1] = 0X55;
				usart_su_TXpacket[3] = dht_data.tmp;
				usart_su_TXpacket[4] = dht_data.tmp_flo;
				usart_su_TXpacket[5] = 0X55;
				usart_su_TXpacket[6] = 0XAA;
				if(dht_data.tmp_flag == 0){	//温度为正
					usart_su_TXpacket[2] = 0x02;
				}
				else{
					usart_su_TXpacket[2] = 0x09;
				}
				usart_send2su_array(usart_su_TXpacket, 6); 
				break;
			case 0x02://湿度
				usart_su_TXpacket[0] = 0XAA;
				usart_su_TXpacket[1] = 0X55;
				usart_su_TXpacket[2] = 0X03;
				usart_su_TXpacket[3] = dht_data.hum;
				usart_su_TXpacket[4] = 0X55;
				usart_su_TXpacket[5] = 0XAA;
				usart_send2su_array(usart_su_TXpacket, 6);
				break;
			case 0x03://空气成分
				
				usart_su_TXpacket[0] = 0XAA;
				usart_su_TXpacket[1] = 0X55;
				usart_su_TXpacket[2] = 0X01;
				usart_su_TXpacket[6] = 0X55;
				usart_su_TXpacket[7] = 0XAA;
				//sprintf(str,"0x%x",(int)(kqm_data.VOC * 100));
				//usart_su_TXpacket[4] = atoi(str);
				usart_su_TXpacket[3] = (uint8_t)(kqm_data.VOC * 100);
			//	printf("%d", usart_su_TXpacket[3]);
				usart_su_TXpacket[4] = (uint8_t)(kqm_data.CHO * 100);
				//printf("%d", usart_su_TXpacket[4]);
				usart_su_TXpacket[5] = kqm_data.CO2;
			//	printf("%d", usart_su_TXpacket[5]);
				usart_send2su_array(usart_su_TXpacket, 8);
			//	usart_send_array(usart_su_TXpacket,8);
				break;
			case 0x04://开灯
				led_enable(LED1);
				break;
			case 0x05://关灯
				led_disable(LED1);
				break;
			case 0x06://甲烷
				usart_su_TXpacket[0] = 0XAA;
				usart_su_TXpacket[1] = 0X55;
				usart_su_TXpacket[3] = (uint8_t)(kqm_data.CHO * 100);
				usart_su_TXpacket[4] = 0X55;
				usart_su_TXpacket[5] = 0XAA;
				if(kqm_data.CHO <0.03){
					usart_su_TXpacket[2] = 0x04;
				}
				else if(kqm_data.CHO >=0.03 && kqm_data.CHO <0.1){
					usart_su_TXpacket[2] = 0x05;
				}
				else{
					usart_su_TXpacket[2] = 0x06;
				}
				usart_send2su_array(usart_su_TXpacket, 6);
				break;
			case 0x07://开启蜂鸣器
				buzzer_enable();
				break;
			case 0x08://关闭蜂鸣器
				buzzer_disable();
				break;
			case 0x9://二氧化碳
				usart_su_TXpacket[0] = 0XAA;
				usart_su_TXpacket[1] = 0X55;
				usart_su_TXpacket[2] = 0x07;
				usart_su_TXpacket[3] = kqm_data.CO2;
				usart_su_TXpacket[4] = 0X55;
				usart_su_TXpacket[5] = 0XAA;
				usart_send2su_array(usart_su_TXpacket, 6);
				break;
			case 0x10://时间
				rawtime = RTC_GetCounter();
				info = localtime(&rawtime);
				
				//info=gmtime(&rawtime);
				usart_su_TXpacket[0] = 0XAA;
				usart_su_TXpacket[1] = 0X55;
				usart_su_TXpacket[2] = 0x08;
				usart_su_TXpacket[3] = (info->tm_year + 1900) / 1000;
				usart_su_TXpacket[4] = ((info->tm_year + 1900) / 100) % 10;
				usart_su_TXpacket[5] = ((info->tm_year + 1900) / 10) % 100;
				usart_su_TXpacket[6] = (info->tm_year + 1900) % 10;
				usart_su_TXpacket[7] = info->tm_mon + 1;
				usart_su_TXpacket[8] = info->tm_mday;
				usart_su_TXpacket[9] = info->tm_hour;
				usart_su_TXpacket[10] = info->tm_min;
				usart_su_TXpacket[11] = info->tm_sec;
				usart_su_TXpacket[12] = 0X55;
				usart_su_TXpacket[13] = 0XAA;
				usart_send_array(USART1, usart_su_TXpacket, 14);
				printf("%d\t%d\t%d\t%d\t", info->tm_year, info->tm_mon, info->tm_mday, info->tm_hour);
				usart_send2su_array(usart_su_TXpacket, 14);
				break;
		}
	}
}

/**
	* @brief  发送一个数组
	* @param  uint8_t *array 需要发送的数组
	* @param	uint16_t len	发送的数组长度
  * @retval None
  */
void usart_send2su_array(uint8_t *array, uint16_t len){
	uint16_t i = 0;
	for(i = 0; i < len; i++){
		usart_send2su_bit(array[i]);
	}
}

/**
  * @brief  发送单个字节
* @param  uint8_t data	需要发送的字节
  * @retval None
  */
void usart_send2su_bit(uint8_t data){
	while(USART_GetFlagStatus(UART4, USART_FLAG_TC) != 1); //等待上一次数据发送完成
	USART_SendData(UART4, data);	//发送数据
}

stm32实战之su-03t语音模块固件的制作与烧录_MCU_16

标签:NVIC,烧录,usart,USART,su,stm32,TXpacket,GPIO
From: https://blog.51cto.com/u_16158769/9104767

相关文章

  • TDengine 荣获 2023 Frost & Sullivan 客户价值领导力奖
    近日,TDengine被国际知名咨询公司沙利文(Frost&Sullivan)评为全球最佳工业数据管理解决方案,赢得了2023年客户价值领导力奖(Frost&Sullivanduoxie),该奖项重点关注引领行业创新和增长的企业。这一奖项的授予也标志着TDengine在工业数据管理解决方案领域的能力获得了国际权威机构......
  • WAVE SUMMIT+ 2023倒计时2天,传文心一言将曝最新进展!
    10句话2分钟,挑战成功说服宿管阿姨开门,这个人群中的“显眼包”是一个接入文心大模型4.0游戏里的NPC,妥妥“工具人”实锤~尝试用AI一键自动识别好坏咖啡豆,看一眼便知好坏,真正“颜值即正义”,让咖啡星人狂喜~借助AI在任何平面上模拟的钢琴,即兴“弹奏”世界名曲,开一场科技感满满的专属演奏......
  • VMware Aria Suite 8.12 - 云管理解决方案 (下载索引)
    VMwareAriaSuite8.12-云管理解决方案(下载索引)作者主页:sysin.org云管理套包VMwareAriaSuite(以前称为vRealizeSuite)和vCloudSuiteVMwareAriaSuite(vRealizeSuite)和vCloudSuite可为VMwareCloud及其他平台提供自助服务使用层、自动化框架和自动驾驶式后续运......
  • VMware vRealize Suite Lifecycle Manager 8.6 下载 - vRealize Suite 生命周期和内容
    使用vRealizeSuiteLifecycleManager管理vRealizeSuitevRealizeSuiteLifecycleManager针对vRealizeSuite产品提供完整的生命周期和内容管理功能。它通过自动执行部署、升级和配置来帮助客户缩短价值实现时间,同时将DevOps原则应用到vRealizeSuite内容管理中。vRea......
  • Windows Subsystem for Android (WSA) 下载:在 Windows 11 上运行 Android 应用
    作者主页:www.sysin.org在Beta频道中为Windows预览体验成员宣布Windows11Preview上的Android™应用程序今天我们宣布的Android™应用程序适用于Windows11的第一个预览版现已在Beta频道在美国的WindowsInsiders可用,如果您还没有读过thisblogpostfromGiorgio......
  • VMware vRealize Suite 8.6 下载 - 多云环境的云计算管理解决方案
    概述VMwarevRealizeSuite是一种多云环境的云计算管理解决方案,为IT组织提供了一个基于DevOps和ML原则的基础架构自动化、一致运维和监管的现代平台。vRealizeSuite如何帮助管理多云环境?应用运维使开发人员能够实时地快速发布基于微服务、分布极广的云计算应用,对其执行故......
  • [ABC271E] Subsequence Path 题解
    [ABC271E]SubsequencePath题解思路解析很好的一道题,很有迷惑性,表面上是一道图论实际上是dp,定义\(f_{i}\)为从\(1\)到\(i\)的最短“好路”。先把每条边对应的起点,终点和边权记录下来,然后输入每个\(e\),由于是子序列顺序不会改变,因此可以顺序进行操作。对于每一个\(e......
  • AI原生应用开发“三板斧”亮相WAVE SUMMIT+2023
    面对AI应用创新的风口跃跃欲试,满脑子idea,却苦于缺乏技术背景,不得不望而却步,这曾是许多开发者的苦恼,如今正在成为过去。12月28日,WAVESUMMIT+深度学习开发者大会2023在北京举办。百度AI技术生态总经理马艳军最新发布飞桨开源框架2.6版本和大模型重构的开发工具链,包括全新发布Comate......
  • Visual Studio 2022 for Mac v17.0 发布,离线安装包下载
    为Mac打造的.NETIDE2022年5月23日,印度微软公布了VisualStudio2022forMacv17.0正式版发布(GA)的消息,并且现在可以下载了。这是迄今为止最快的VisualStudioforMac版本(sysin),具有全新的原生macOSUI,完全在.NET6上运行,并针对AppleSilicon(ARM64)处理......
  • macOS Big Sur 11.6.3 (20G415) 正式版 DMG、ISO、IPSW 下载
    本站提供的macOSBigSur软件包,既可以拖拽到Applications(应用程序)下直接安装,也可以制作启动U盘安装,或者在虚拟机中启动安装。macOSBigSur11.6.3(20G415)也于今天(2022年1月27日)发布,本次同样为安全更新。11.6完整安装包终于在(9月)17日发布,今天更新所有格式。macOS......