使用JQ8400实现数据动态播报

一.了解JQ8400模块

1.管脚说明

引脚标示说明
1ONE LINE一线串口脚
2BUSY忙信号脚,播放时为高,其他为低
3RX芯片串口接收脚,接MCU的TX
4TX芯片串口发送脚,接MCU的RX
5GND芯片数字地
6DC-5V芯片供电脚,3.3-5V
7DAC-RDAC音频输出右声道
8DAC-LDAC音频输出左声道
9SPK-接喇叭
10SPK+

2.一线串口通信协议

SDA为数据发送端口,发送语音地址,先发送低位。

3.一线数据指令

指令(HEX)功能说明
00数字0

数字0-9可以用于需要数字的功能,

比如选曲、设置音量、设置EQ、

设置循环模式、设置通道、设置插播曲目

先发数字后发功能指令。

01数字1
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.一线串口MP3文件命名规则

  (1)文件名需为5位数字,该五位数即为文件的曲目号。

  (2)文件需放在根目录下。

5.一线串口说明和注意事项

  (1)引导码延时要求大于2MS,建议使用4MS延时

  (2)脉冲比例基数在2-5都可以识别

  (3)两个字节之间延时建议在10MS以上

二.模块基本使用

1.下载对应语音

在线免费文字转语音 - TTSMaker官网 | 马克配音

 

2.格式化JQ8400移入语音 

链接typec口

 

 

                                                               注意格式

                                                         必须是按顺序进行 

3.代码实现

jq8400.c

#include "jq8400.h"   

 /*
  * @brief  初始化控制JQ8400的串口2
  */
void USART_Config(void)
{		
		GPIO_InitTypeDef GPIO_InitStructure;
	  USART_InitTypeDef USART_InitStructure;

		RCC_APB2PeriphClockCmd( USART_RX_CLK | USART_TX_CLK , ENABLE);//串口GPIO时钟
	  RCC_APB1PeriphClockCmd( UserPeriph_USARTx ,ENABLE);//串口外设时钟
	
		GPIO_InitStructure.GPIO_Pin = USART_TX_PIN;	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_Init(USART_TX_PORT, &GPIO_InitStructure);
	
	  GPIO_InitStructure.GPIO_Pin = USART_RX_PIN;
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
		GPIO_Init(USART_RX_PORT, &GPIO_InitStructure);	
		
	
	  USART_InitStructure.USART_BaudRate = 9600;
	  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx ;
	  USART_InitStructure.USART_Parity = USART_Parity_No;
	  USART_InitStructure.USART_StopBits = USART_StopBits_1 ;
	  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
		
		USART_Init( UserUSARTx,&USART_InitStructure);
		
		USART_Cmd( UserUSARTx,ENABLE);
		
}

/***************** 发送一个 32 位数 **********************/
void Usart_Send32bit( USART_TypeDef * pUSARTx, uint32_t ch)
{
   uint8_t temp_1, temp_2, temp_3, temp_4; //4个8位

   /* 取出第一八位 */
   temp_1 = (ch&0XFF000000)>>24;
   /* 取出第二八位 */
   temp_2 = (ch&0X00FF0000)>>16;
	 /* 取出第三八位 */
   temp_3 = (ch&0X0000FF00)>>8;
   /* 取出第四八位 */
   temp_4 = (ch&0X000000FF);

   /* 发送第一八位 */
   USART_SendData(pUSARTx,temp_1);
   while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
   /* 发送第二八位 */
   USART_SendData(pUSARTx,temp_2);
   while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
	 /* 发送第三八位 */
   USART_SendData(pUSARTx,temp_3);
   while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
   /* 发送第四八位 */
   USART_SendData(pUSARTx,temp_4);
   while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
 }

/***************** 发送一个 8 位数 **********************/ 
void Usart_Send8bit( USART_TypeDef * pUSARTx, uint8_t eight)
{
   /* 发送一个字节数据到 USART */
   USART_SendData(pUSARTx,eight);

   /* 等待发送数据寄存器为空 */
   while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
 
/***************** 循环模式:单曲停止 **********************/ 
void asong_stop(void)
{
	 Usart_Send32bit( UserUSARTx, 0xAA180102);
	 Usart_Send8bit( UserUSARTx, 0xC5);
}

/***************** 播放模式:指定歌曲(playsong(1):播放00001曲目) **********************/ 
//曲目的文件名需要按指定格式来保存的,使用说明书上有写
/*
指定曲目(07)
指令:AA 07 02 曲目高 曲目低 SM
返回:无
和检验(SM):为之前所有字节之和的低8位,即前面的数据相加后取低8位
例如:  AA 07 02 00 08 BB 指定播放当前盘符第8首(AA+07+02+00+08=BB取低8位,即为BB)
*/
void playsong(u16 i)
{
	Usart_Send32bit( UserUSARTx,0xAA070200);
	Usart_Send8bit( UserUSARTx, 0x00+i);
	Usart_Send8bit( UserUSARTx, 0xB3+i);//控制指令要48位,故拆分开,32位+8位+8位
}

jq8400.h

#ifndef __JQ8400_H
#define	__JQ8400_H


#include "stm32f10x.h"

/*串口2总线*/
#define UserUSARTx USART2
#define UserPeriph_USARTx RCC_APB1Periph_USART2

/*串口2GPIO*/
// RX
#define USART_TX_PORT    	    GPIOA			              /* GPIO端口 */
#define USART_TX_CLK 	        RCC_APB2Periph_GPIOA		/* GPIO端口时钟 */
#define USART_TX_PIN		      GPIO_Pin_2			        /* 连接到SCL时钟线的GPIO */

// TX
#define USART_RX_PORT    	    GPIOA
#define USART_RX_CLK 	        RCC_APB2Periph_GPIOA		
#define USART_RX_PIN		      GPIO_Pin_3			        
  
// BUSY
//#define JQ8400_BUSY    	    GPIOA			              /* GPIO端口 */
//#define JQ8400_BUSY_CLK 	  RCC_APB1Periph_GPIOA		/* GPIO端口时钟 */
//#define JQ8400_BUSY_PIN		  GPIO_Pin_5			        /* 连接到SCL时钟线的GPIO */


void Usart_Send8bit( USART_TypeDef * pUSARTx, uint8_t eight);
void USART_Config(void);
void Usart_Send32bit( USART_TypeDef * pUSARTx, uint32_t ch);
void asong_stop(void);
void playsong(u16 i);
void playsong2(u16 i,u16 a);



#endif /* __JQ8400_H */

main.c

//用于判断数据播报
void numberPlay(int number) {  
    switch (number) {  
        case 1:  
            playsong(1);  
            break;  
        case 2:  
            playsong(2);  
            break;  
        case 3:  
            playsong(3);  
            break;  
        case 4:  
            playsong(4);  
            break;  
        case 5:  
            playsong(5);  
            break;  
        case 6:  
            playsong(6);  
            break;  
        case 7:  
            playsong(7);  
            break;  
        case 8:  
            playsong(8);  
            break;  
        case 9:  
            playsong(9);  
            break;  
        // 可以添加一个默认情况来处理非1-9的数字(可选)  
        default:  
            // 这里可以添加一些代码来处理未知的数字,或者什么都不做  
            break;  
    }  
}


//处理数据播报
u8 Q8400temp;
int integer_part,tens_place,units_place,first_decimal_place,second_decimal_place;
float decimal_part;
void ProcessingDataBroadcast(float res){
    // 整数部分和小数部分的分离  
     integer_part = (int)res;  
     decimal_part = res - integer_part;  
  
  
    // 提取十位  
    tens_place = (integer_part / 10) % 10;  
  
    // 提取个位  
    units_place = integer_part % 10;  

    // 提取小数点后一位  
    decimal_part *= 10;  // 将小数点右移一位  
    first_decimal_place = (int)decimal_part % 10;  
  
    // 提取小数点后二位  
    decimal_part = res - (int)res - first_decimal_place / 10.0;  // 更新小数部分,去掉已处理的一位  
    decimal_part *= 100;  // 将小数点右移两位  
    second_decimal_place = (int)decimal_part % 10;  
	  // 输出最大值100  
    if (res == 100) { 
        delay_ms(600);			
        playsong(1);  
        delay_ms(600);  
        playsong(12);  
    }
    // 输出20-99
		if(res<=99&&res>=20){
			 delay_ms(600);	
		   numberPlay(tens_place);
			 delay_ms(600);	
			 playsong(11);
			 delay_ms(600);	
       numberPlay(units_place);
		}
		//十位数据播报
		if(res>=10&&res<=20){
		   delay_ms(600);
			 playsong(11);
			 delay_ms(600);	
       numberPlay(units_place);
			
		}
		//个位数
		if(res<10){
			 delay_ms(600);	
       numberPlay(units_place);
		}
		//处理小数位
		if(first_decimal_place!=0||second_decimal_place!=0){
		   delay_ms(600);
			 playsong(21);
       delay_ms(600);
       //处理第一位为0的情况
       if(first_decimal_place==0){
			 		delay_ms(600);
			    playsong(10);
				  delay_ms(600);
			 }			
			    playsong(first_decimal_place);
			 		delay_ms(800);
			    playsong(second_decimal_place);
			 		delay_ms(600);
		  
		}
}

//直接调用此函数 在当前函数中修改值
void q8400_out(){
		delay_ms(800);
	  //温度
		playsong(18);
	  delay_ms(800);
   	ProcessingDataBroadcast(wd);
		delay_ms(600);
	  //温度
		playsong(19);
	  delay_ms(800);
   	ProcessingDataBroadcast(zd);
		delay_ms(800);
	  //温度
		playsong(20);
	  delay_ms(1000);
   	ProcessingDataBroadcast(ph);
}

语音编号说明 

编号描述
000011-9
00002-
00003-
00004-
00005-
00006-
00007-
00008-
00009-
000100
00011
00012
00013
00014ph值过高
00015ph值过低
00016浑浊度过高
00017温度过高
00018温度
00019浊度
00020浊度
00021
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值