若该文为原创文章,转载请注明原文出处。

手上有一个SNR9816模块,测试一下TTS。

在测试过程中,发现使用STM32的很少,所以就自己写驱动了。

一、硬件介绍

1、模块

2、原理图

3、引脚说明

这里的RX和PA9相连接。2脚悬空,波特率115200bps

二、测试

1、协议说明

协议帧格式

字节索引 字段名称 长度(字节) 取值/说明
0 起始标识 1 固定为 0xFD,表示命令帧开始
1-2 数据长度 2 高字节在前(网络字节序),值为 文本数据长度 + 2(即命令字节+参数字节)
3 命令字 1 固定为 0x01,表示播放文本
4 参数 1 本例中固定为 0x01(可能代表音量或其他设置,具体含义取决于设备)
5 ~ 末尾 文本数据 N GB2312 编码的文本内容(N 为文本字节数)

帧长度计算

整个帧的总字节数 = 1(起始标识) + 2(长度字段) + 1(命令) + 1(参数) + N(文本数据) = N + 5

2、数据封装输出测试

#include <stdio.h>
#include <string.h>

/**
 * 模拟发送 TTS 消息,构建数据帧并打印其十六进制内容。
 * 注意:此函数要求输入的字符串已为 GB2312 编码(字节流)。
 * 若实际输入为 UTF-8,需先调用编码转换函数(如 iconv 或自定义转换表)。
 */
void sendTTSMessage(const char *gb2312_str) {
    unsigned int len = strlen(gb2312_str);          // 获取 GB2312 字符串字节数
    unsigned char buffer[len + 6];                   // 预留帧头 + 命令 + 参数 + 数据空间

    // 填充帧头
    buffer[0] = 0xFD;                                 // 命令帧起始标识
    buffer[1] = (len + 2) >> 8;                       // 长度高字节(数据长度 + 命令字节 + 参数字节)
    buffer[2] = (len + 2) & 0xFF;                      // 长度低字节
    buffer[3] = 0x01;                                  // 命令:播放文本
    buffer[4] = 0x01;                                  // 参数:音量等(示例中固定为 0x01)

    // 复制 GB2312 数据
    for (unsigned int i = 0; i < len; i++) {
        buffer[i + 5] = (unsigned char)gb2312_str[i];
    }

    // 打印构建好的数据帧(十六进制)
    printf("TTS 数据帧 (%d 字节): ", len + 5);
    for (unsigned int i = 0; i < len + 5; i++) {
        printf("%02X ", buffer[i]);
    }
    printf("\n");

    // 模拟发送成功消息
    printf("TTS 消息发送成功\n");
}

int main(int argc, char *argv[]) {
    // 测试用例:若未提供命令行参数,使用预定义的 GB2312 字符串 "你好"
    // "你好" 的 GB2312 编码为:C4 E3 BA C3
    const char *test_message = "\xC4\xE3\xBA\xC3";

    if (argc > 1) {
        // 假设用户通过命令行直接输入了 GB2312 编码的字符串(需确保终端/控制台编码一致)
        // 注意:在大多数环境中直接输入汉字会得到 UTF-8 编码,因此本程序仍按 GB2312 处理,可能出错。
        // 建议测试时直接修改 test_message 或从文件读取 GB2312 字节。
        test_message = argv[1];
    }

    printf("输入字符串 (视为 GB2312 字节): ");
    for (size_t i = 0; i < strlen(test_message); i++) {
        printf("%02X ", (unsigned char)test_message[i]);
    }
    printf("\n");

    sendTTSMessage(test_message);

    return 0;
}

把程序放到C语言在线编译器上运行,会打印输出数据。

把数据,通过串口发送给模块,就可以听到TTS语音了。

 FD 00 06 01 01 C4 E3 BA C3

三、STM32代码

1、usart.h

#ifndef __USART1_H
#define	__USART1_H
 
#include "stm32f10x.h"
#include <stdio.h>

 
void USART1_Config(void);
int fputc(int ch, FILE *f);
void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...);
void UART1SendByte(unsigned char SendData);
 
 
#endif /* __USART1_H */

2、usart.c

#include "usart.h"
#include <stdarg.h>

 
void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
 
	/* 使能 USART1 时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 
 
	/* USART1 使用IO端口配置 */    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);    
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA
	  
	/* USART1 工作模式配置 */
	USART_InitStructure.USART_BaudRate = 115200;	//波特率设置:9600
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//数据位数设置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	//停止位设置:1位
	USART_InitStructure.USART_Parity = USART_Parity_No ;  //是否奇偶校验:无
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制模式设置:没有使能
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//接收与发送都使能
	USART_Init(USART1, &USART_InitStructure);  //初始化USART1
	USART_Cmd(USART1, ENABLE);// USART1使能
}
 
 
 /* 描述  :重定向c库函数printf到USART1*/ 
int fputc(int ch, FILE *f)
{
/* 将Printf内容发往串口 */
  USART_SendData(USART1, (unsigned char) ch);
  while (!(USART1->SR & USART_FLAG_TXE));
 
  return (ch);
}
 
 /*发送一个字节数据*/
void UART1SendByte(unsigned char SendData)
{	   
		USART_SendData(USART1,SendData);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	    
} 
 


/*
************************************************************
*	函数名称:	Usart_SendString
*
*	函数功能:	串口数据发送
*
*	入口参数:	USARTx:串口组
*				str:要发送的数据
*				len:数据长度
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{

	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);		//等待发送完成
		delay_us(100);
	}
 
}

 
 

3、main.c

#include "delay.h"
#include "sys.h"
#include "OLED.h"
#include "usart.h"

//C库
#include <string.h>
#include "stdio.h"
#include "math.h"





// 测试用例:若未提供命令行参数,使用预定义的 GB2312 字符串 "布防成功"
// "布防成功" 的 GB2312 编码为:B2BC B7C0 B3C9 B9A6 
const char *test_message = "\xB2\xBC\xB7\xC0\xB3\xC9\xB9\xA6 ";

/**
 * 模拟发送 TTS 消息,构建数据帧并打印其十六进制内容。
 * 注意:此函数要求输入的字符串已为 GB2312 编码(字节流)。
 * 若实际输入为 UTF-8,需先调用编码转换函数(如 iconv 或自定义转换表)。
 */
void sendTTSMessage(const char *gb2312_str) {
    unsigned int len = strlen(gb2312_str);          // 获取 GB2312 字符串字节数
    unsigned char buffer[len + 6];                   // 预留帧头 + 命令 + 参数 + 数据空间

    // 填充帧头
    buffer[0] = 0xFD;                                 // 命令帧起始标识
    buffer[1] = (len + 2) >> 8;                       // 长度高字节(数据长度 + 命令字节 + 参数字节)
    buffer[2] = (len + 2) & 0xFF;                      // 长度低字节
    buffer[3] = 0x01;                                  // 命令:播放文本
    buffer[4] = 0x01;                                  // 参数:音量等(示例中固定为 0x01)

    // 复制 GB2312 数据
    for (unsigned int i = 0; i < len; i++) {
        buffer[i + 5] = (unsigned char)gb2312_str[i];
    }

	Usart_SendString(USART1, buffer, len+5);
}

int main(void)
{   

	
	unsigned char *dataPtr = NULL;	
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置
    delay_init();
    Usart1_Init(115200);

    delay_ms(200);
    sendTTSMessage(test_message);
	
   	while(1)
  	{
       
    }
}

测试正常

ASCII/GBK/GB2312中文汉字区位码,内码,编码在线查询软件

如有侵权,或需要完整代码,请及时联系博主。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐