#include "sound.h"
#include "sys.h"
#include "stdio.h"
#include "delay.h"
#include "stm32f10x_it.h"
#include <string.h>
// 私有变量定义
static volatile TTS_Status tts_status = TTS_READY;
static uint8_t dma_tx_complete = 1;
static uint8_t serial_number = 1;
static uint8_t tts_tx_buffer[512];
// 引脚定义
#define TTS_BUSY_PIN GPIO_Pin_12
#define TTS_BUSY_PORT GPIOA
// USART3定义
#define TTS_USART USART3
#define TTS_DMA_CHANNEL DMA1_Channel2
#define TTS_DMA_FLAG_TC DMA1_FLAG_TC2
// 命令码定义
#define CMD_TTS_SPEAK 0x03E8
#define CMD_TTS_CTRL 0x03E9
#define CMD_VOLUME_CTRL 0x00CC
#define CMD_VOLUME_UP 0x00CD
#define CMD_VOLUME_DOWN 0x00CE
#define CMD_SEND_CACHE 0x03EA
#define CMD_PLAY_CACHE 0x03EB
#define CMD_SLEEP 0x038F
// 私有函数声明
static void GPIO_Configuration(void);
static void USART3_Configuration(void);
static void DMA_Configuration(void);
static void NVIC_Configuration(void);
static void Send_Command_Frame(uint16_t command, const uint8_t* data, uint8_t data_length);
void TTS_Init(void)
{
GPIO_Configuration();
USART3_Configuration();
DMA_Configuration();
NVIC_Configuration();
// tts_status = TTS_READY;
// dma_tx_complete = 1;
// serial_number = 1;
}
static void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
// 配置USART3引脚: PB10(TX), PB11(RX)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置忙检测引脚PA12
GPIO_InitStructure.GPIO_Pin = TTS_BUSY_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TTS_BUSY_PORT, &GPIO_InitStructure);
}
static void USART3_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
// 使能USART3时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// USART3配置
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(TTS_USART, &USART_InitStructure);
USART_Cmd(TTS_USART, ENABLE);
USART_DMACmd(TTS_USART, USART_DMAReq_Tx, ENABLE);
}
static void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
// 使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// DMA1 Channel2配置 (USART3_TX)
DMA_DeInit(TTS_DMA_CHANNEL);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TTS_USART->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tts_tx_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(TTS_DMA_CHANNEL, &DMA_InitStructure);
DMA_ITConfig(TTS_DMA_CHANNEL, DMA_IT_TC, ENABLE);
}
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 配置DMA通道中断
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// DMA传输完成中断处理函数
void DMA1_Channel2_IRQHandler(void)
{
if (DMA_GetITStatus(TTS_DMA_FLAG_TC))
{
// 清除中断标志
DMA_ClearITPendingBit(TTS_DMA_FLAG_TC);
// 禁用DMA
DMA_Cmd(TTS_DMA_CHANNEL, DISABLE);
// 设置传输完成标志
dma_tx_complete = 1;
// 更新状态为忙碌(等待语音播放完成)
tts_status = TTS_BUSY;
}
}
u8 Get_TTS_Status(void)
{
if(GPIO_ReadInputDataBit(TTS_BUSY_PORT, TTS_BUSY_PIN))
return 1;
else
return 0;
}
// ========== 公共API函数实现 ==========
void SpeakText(u8 TTS_data[])
{
u8 data_length_temp = strlen(TTS_data);
int8_t send_code[9+data_length_temp+2];
uint8_t pos = 0;
int8_t zhen_length_high = 0;
int8_t zhen_length_low = 0;
int8_t serial_number = 1;
int8_t sum;
size_t i=0;
while(Get_TTS_Status()==0); // 检查引脚等语音模块空闲
zhen_length_low = 9 + data_length_temp;
sum = zhen_length_low + zhen_length_high + serial_number + 3 + 232 + 3 + data_length_temp;
send_code[pos++] = 0x7e; // 起始位
send_code[pos++] = zhen_length_high; //帧长度高位,指起始码+帧长度+命令码+N 个 KEYID 信息+累加和校验和+结束码的长度
send_code[pos++] = zhen_length_low; //帧长度低位,指起始码+帧长度+命令码+N 个 KEYID 信息+累加和校验和+结束码的长度
send_code[pos++] = serial_number; // 流水号
send_code[pos++] = 0x00; // 应答标志,默认为00
send_code[pos++] = 0x03; //数据帧来源,02 为 TTS 芯片端,03 为 MCU 芯片端;
send_code[pos++] = 0x03; //ID 地址高位
send_code[pos++] = 0xE8; //ID 地址低位
send_code[pos++] = data_length_temp; //数据长度,发送数据长度strlen(TTS data)
for(i=0;i<data_length_temp;i++)
{
send_code[pos++] = TTS_data[i];
sum = sum + TTS_data[i];
}
send_code[pos++] = sum; // 校验和
send_code[pos++] = 0xEF; // 结束码
// 将数据复制到全局缓冲区tts_tx_buffer
if (pos > sizeof(tts_tx_buffer)) {
// 错误处理:数据过长
return;
}
memcpy(tts_tx_buffer, send_code, pos);
// 启动DMA传输
dma_tx_complete = 0;
DMA_SetCurrDataCounter(TTS_DMA_CHANNEL, pos);
DMA_Cmd(TTS_DMA_CHANNEL, ENABLE);
delay_ms(200);
}