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)时序图
STM32控制JQ8400语音播报模块_第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)注意点
  • 音频文件命名需要为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);
    }
    
    

你可能感兴趣的:(STM32,stm32,嵌入式硬件,单片机)