使用STM32控制JQ8400语音播报模块
时间记录:2024/2/7
一、JQ8400引脚介绍
标示 | 说明 |
---|---|
ONE LINE | 一线操作引脚 |
BUSY | 忙信号引脚,正在播放语音时输出高电平 |
RX | 串口两线操作接收引脚 |
TX | 串口两线操作发送引脚 |
GND | 电源地引脚 |
DC-5V | 电源引脚,3.3-5V |
DAC-R | DAC输出右声道引脚 |
DAC-L | DAC输出左声道引脚 |
SPK- | 喇叭-引脚 |
SPK+ | 喇叭+引脚 |
二、一线操作
(1)时序图
(2)时序分析
2.2.1 总线拉低2ms以上产生引导码
2.2.2 发送数据“1”,高电平大于1200us,低电平大于400us,高低电平时间比例3:1
2.2.3 发送数据“0”,高电平大于400us,低电平大于1200us,高低电平时间比例1:3
2.2.4 发送一字节指令和数据时低位先发
(3)控制指令
指令(HEX) | 功能 | 说明 |
---|---|---|
00 | 数字0 | 数字0-9可以用于需要数字的功能,比如选曲、设置音量、设置EQ、设置循环模式、设置通道、设置插播曲目先发数字后发功能指令。 |
01 | 数字0 | |
02 | 数字2 | |
03 | 数字3 | |
04 | 数字4 | |
05 | 数字5 | |
06 | 数字6 | |
07 | 数字7 | |
08 | 数字8 | |
09 | 数字9 | |
0A | 清零数字 | 清除发送的数字 |
0B | 选曲确认 | 配合数字实现 |
0C | 设置音量0-30 | |
0D | 设置EQ | |
0E | 设置循环模式 | |
0F | 设置通道 | |
10 | 设置插播曲目 | |
11 | 播放 | 单字节控制指令,仅需发送一个控制指令即可。 |
12 | 暂停 | |
13 | 停止 | |
14 | 上一曲 | |
15 | 下一曲 | |
16 | 上一目录 | |
17 | 下一目录 | |
18 | 选择SD卡 | |
19 | 选择U盘 | |
1A | 选择FLASH | |
1B | 系统睡眠 |
(4)注意点
三、二线串口操作
(1)串口波特率9600,音频文件命名无要求,复制的顺序即播放的曲目号
(2)常用的几个命令介绍,其余命令可通过查看操作手册设置
四、示例代码
(1)头文件
#ifndef __JQ8400_H__
#define __JQ8400_H__
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#define ONELINERCC RCC_APB2Periph_GPIOB
#define ONELINEGPIO GPIOB
#define ONELINEPIN GPIO_Pin_5
#define ONELINE PBout(5)
void vJq8400Init(u8 mode);//初始化,0:ONELINE操作,1串口操作
void vOnelineVolume(int vol);//设置音量
void vOnelinePlay(int cnt,u8 loop);//播放音频,最大999
void vOnelinePause(u8 mode);//暂停/继续
void vOnelineStop(void);//停止
void vUartVolume(u8 vol);//设置音量
void vUartPlay(int cnt,u8 loop);//播放音频,最大999
void vUartStop(void);//停止
#endif
(2)源文件
#include "jq8400.h"
void vJq8400Init(u8 mode)
{
if(mode==0){//ONELINE操作
//初始化时钟配置端口
RCC_APB2PeriphClockCmd(ONELINERCC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = ONELINEPIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ONELINEGPIO,&GPIO_InitStruct);
Delay_Init();
}else if(mode==1){//串口操作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//发送数据端口,复用推挽输出
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 9600;//波特率
USART_InitStruct.USART_Mode = USART_Mode_Tx;//模式,发模式
USART_InitStruct.USART_WordLength = USART_WordLength_8b;//数据位长度,8位
USART_InitStruct.USART_Parity = USART_Parity_No;//校验位
USART_InitStruct.USART_StopBits = USART_StopBits_1;//一位停止位
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_Init(USART1,&USART_InitStruct);
USART_Cmd(USART1,ENABLE);
}
}
static void vJq8400SendByte(u8 dataOrCmd)
{
ONELINE=1;
Delay_Ms(5);//两个字节发送之间的延时
//发送引导码,大于2ms,建议为4ms
ONELINE=0;
Delay_Ms(4);
for(u8 i=0;i<8;i++){//发送数据
ONELINE=1;
if(dataOrCmd&0x01){//最低位为1,发送位1,高低电平时间3:1表示发送1,脉冲比例基数2-5都可以识别
Delay_Us(1200);
ONELINE=0;
Delay_Us(400);
}else{//发送位0
Delay_Us(400);
ONELINE=0;
Delay_Us(1200);
}
dataOrCmd >>= 1;
}
ONELINE=1;
Delay_Ms(5);//恢复空闲状态
}
static void vUartSendByte(u8 data)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//0表示数据还未转移到移位寄存器,1表示数据已经移动到移位寄存器可以发送数据
USART_SendData(USART1,data);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);//1表示发送完成
}
void vOnelineVolume(int vol)
{
vJq8400SendByte(0x0A);//清除数字
vJq8400SendByte(vol/10);//设置音量
vJq8400SendByte(vol%10);
vJq8400SendByte(0x0C);//设置音量
}
void vOnelinePlay(int cnt,u8 loop)
{
vJq8400SendByte(0x0A);//清除数字
vJq8400SendByte(cnt/100);//设置数字
vJq8400SendByte(cnt/10%10);
vJq8400SendByte(cnt%10);
vJq8400SendByte(0x0B);//确认选曲
vJq8400SendByte(0x0A);//清除数字
vJq8400SendByte(loop);//设置数字
vJq8400SendByte(0x0E);//设置循环模式,0:倒序循环播放音频文件,1:循环播放当前曲目,2:播放1次,3:循环随机播放音频文件
vJq8400SendByte(0x11);//播放选曲
}
void vOnelinePause(u8 mode)
{
if(mode==0)
vJq8400SendByte(0x12);
else if(mode==1)
vJq8400SendByte(0x11);
}
void vOnelineStop(void)
{
vJq8400SendByte(0x13);
}
void vUartVolume(u8 vol)
{
vUartSendByte(0xAA);
vUartSendByte(0x13);
vUartSendByte(0x01);
vUartSendByte(vol);
vUartSendByte((0xAA+0x13+0x01+vol));//SM校验和
}
void vUartPlay(int cnt,u8 loop)
{
//设置循环模式
vUartSendByte(0xAA);
vUartSendByte(0x18);
vUartSendByte(0x01);
if(loop==0){
vUartSendByte(0x02);
vUartSendByte(0xC5);
}else if(loop==1){
vUartSendByte(0x01);
vUartSendByte(0xC4);
}
//播放曲目
vUartSendByte(0xAA);
vUartSendByte(0x07);
vUartSendByte(0x02);
vUartSendByte(cnt/255);
vUartSendByte(cnt%255);
vUartSendByte((0xAA+0x07+0x02+cnt));//SM校验和
}
void vUartStop(void)
{
vUartSendByte(0xAA);
vUartSendByte(0x04);
vUartSendByte(0x00);
vUartSendByte(0xAE);
}
作者:KINO32