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 | 系统睡眠 |
- 音频文件命名需要为5位数字,该5位数字即为曲目号,例如00001.mp3
- 音频文件需要放置在根目录下
- 引导码延时要大于2ms,建议使用4ms
- 高低电平时间比例在2-5都可以识别到
- 发送两个字节,中间空闲状态建议维持10ms以上
三、二线串口操作
(1)串口波特率9600,音频文件命名无要求,复制的顺序即播放的曲目号
(2)常用的几个命令介绍,其余命令可通过查看操作手册设置- 设置音量:AA 13 01 音量0-30 SM校验和
- 播放指定曲目:AA 07 02 曲目高 曲目低 SM校验和
- 停止播放:AA 04 00 AE
- 设置循环模式:AA 18 01 循环模式 SM校验和
四、示例代码
(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); }