• 方案介绍
    • 一、模块介绍
    • 二、移植使用(资料代码中没有移植后的代码,需要自行移植)
    • 三、参考
  • 附件下载
  • 推荐器件
  • 相关推荐
申请入驻 产业图谱

嵌入式外设集-语音播报模块(JR6001)驱动

2024/03/20
8523
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

联系方式.docx

共1个文件

一、模块介绍

JR6001是一种语音播放模块,具有以下特性:

1. 自带USB接口,可以灵活地替换SPI-flash中的语音内容,无需安装主机电脑来替换传统语音芯片的语音。SPI FLASH直接模拟为U盘,就像复制U盘一样,非常方便。任何计算机系统都可以支持它【7†source】。

2. 支持MP3、WAV高质量音频格式,声音优美。

3. 24位DAC输出,动态范围支持90dB,信号比85dB。

4. 支持两线串口控制,AD控制。

5. USB更新语音文件,无需安装驱动程序,无需安装软件,直接复制,快速方便。支持XP系统,WIN7,WIN8,WIN10系统。

6. 支持上一首歌,下一首歌,播放,暂停,停止,选歌,和其他常见功能控制。 7. 支持自由组合播放。 8. 支持30级音量调整。

9. 支持周期号设置,更多应用,更人性化。

10. 专用BUSY信号输出指示。

11. 成熟的指令和指令分析使应用更稳定。

12. 专用支持主机电脑,快速使用,易于调试,命令自动生成【8†source】。


关注微信公众号--星之援工作室 发送关键字(JR6001)

➡️➡️

使用的注意事项

1.只需要配置一个串口即可,波特率为9600

二、移植使用(资料代码中没有移植后的代码,需要自行移植)

1.串口配置

usart2.c

因为我们使用的JR6001模块是需要使用串口进行通信控制(详情可在获取的资料中查看),我们只需要用到该串口的发送端口即可,不需要处理JR6001回传的数据,所以接收中断中的数据处理可略过 ~~ (引用GPS的串口配置)

#include "delay.h"
#include "usart2.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"

char rxdatabufer;
u16 point1 = 0;

_SaveData Save_Data;

#if EN_USART2_RX // 如果使能了接收
// 串口1中断服务程序
// 注意,读取USARTx->SR能避免莫名其妙的错误
char USART_RX2_BUF[USART2_REC_LEN]; // 接收缓冲,最大USART_REC_LEN个字节.
// 接收状态
// bit15,	接收完成标志
// bit14,	接收到0x0d
// bit13~0,	接收到的有效字节数目
u16 USART2_RX_STA = 0; // 接收状态标记

void Usart2_Init(u32 bound)
{

	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // GPIOB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); // 串口3时钟使能

	USART_DeInit(USART2);					  // 复位串口3
											  // USART3_TX   PB10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // PB10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);			// 初始化PB10

	// USART3_RX	  PB11
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);				  // 初始化PB11

	USART_InitStructure.USART_BaudRate = bound;										// 波特率一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						// 字长为8位数据格式
	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_Rx | USART_Mode_Tx;					// 收发模式

	USART_Init(USART2, &USART_InitStructure); // 初始化串口	3

	USART_Cmd(USART2, ENABLE); // 使能串口

	// 使能接收中断
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 开启中断

	// 设置中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		  // 子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			  // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);							  // 根据指定的参数初始化VIC寄存器

	CLR_Buf(); // 清空缓存
}

void USART2_IRQHandler(void) // 串口1中断服务程序
{
	u8 Res;
#ifdef OS_TICKS_PER_SEC // 如果时钟节拍数定义了,说明要使用ucosII了.
	OSIntEnter();
#endif
	if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
	{
		Res = USART_ReceiveData(USART2); //(USART1->DR);	//读取接收到的数据

		if (Res == '$')
		{
			point1 = 0;
		}

		USART_RX2_BUF[point1++] = Res;

		if (USART_RX2_BUF[0] == '$' && USART_RX2_BUF[4] == 'M' && USART_RX2_BUF[5] == 'C') // 确定是否收到"GPRMC/GNRMC"这一帧数据
		{
			if (Res == 'n')
			{
				memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length);	 // 清空
				memcpy(Save_Data.GPS_Buffer, USART_RX2_BUF, point1); // 保存数据
				Save_Data.isGetData = true;
				point1 = 0;
				memset(USART_RX2_BUF, 0, USART2_REC_LEN); // 清空
			}
		}

		if (point1 >= USART2_REC_LEN)
		{
			point1 = USART2_REC_LEN;
		}
	}
#ifdef OS_TICKS_PER_SEC // 如果时钟节拍数定义了,说明要使用ucosII了.
	OSIntExit();
#endif
}

u8 Hand(char *a) // 串口命令识别函数
{
	if (strstr(USART_RX2_BUF, a) != NULL)
		return 1;
	else
		return 0;
}

void CLR_Buf(void) // 串口缓存清理
{
	memset(USART_RX2_BUF, 0, USART2_REC_LEN); // 清空
	point1 = 0;
}

void clrStruct()
{
	Save_Data.isGetData = false;
	Save_Data.isParseData = false;
	Save_Data.isUsefull = false;
	memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); // 清空
	memset(Save_Data.UTCTime, 0, UTCTime_Length);
	memset(Save_Data.latitude, 0, latitude_Length);
	memset(Save_Data.N_S, 0, N_S_Length);
	memset(Save_Data.longitude, 0, longitude_Length);
	memset(Save_Data.E_W, 0, E_W_Length);
}

#endif

usart2.h

功能函数的定义(引用GPS的串口配置)

#ifndef __USART2_H
#define __USART2_H
#include "stdio.h"	
#include "sys.h"
#include "string.h"

//V1.3修改说明 
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
#define USART2_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART2_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern char  USART_RX2_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART2_RX_STA;         		//接收状态标记	



#define false 0
#define true 1

//定义数组长度
#define GPS_Buffer_Length 80
#define UTCTime_Length 11
#define latitude_Length 11
#define N_S_Length 2
#define longitude_Length 12
#define E_W_Length 2 

typedef struct SaveData 
{
	char GPS_Buffer[GPS_Buffer_Length];
	char isGetData;		//是否获取到GPS数据
	char isParseData;	//是否解析完成
	char UTCTime[UTCTime_Length];		//UTC时间
	char latitude[latitude_Length];		//纬度
	char N_S[N_S_Length];		//N/S
	char longitude[longitude_Length];		//经度
	char E_W[E_W_Length];		//E/W
	char isUsefull;		//定位信息是否有效
} _SaveData;




void Usart2_Init(u32 bound);
extern char rxdatabufer;
extern u16 point1;
extern _SaveData Save_Data;

void CLR_Buf(void);
u8 Hand(char *a);
void clrStruct(void);
#endif


2.JR6001的功能代码编写

1. 配置完串口后,我们需要开始编写我们的控制函数,包括模块的读忙,发送相关的功能控制函数等基础功能

JR6001.c

功能函数的编写

#include "JR6001.h"

#include "usart.h"
#include "delay.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
// 延时函数重定义 JR6001延时函数定义,用户自行更改为自己的延时函数
#define JR6001_ms(ms) delay_ms(ms)
#define JR6001_us(us) delay_us(us)

void JR6001_Volumecontrol(u8 num);

void JR6001_Init(void)
{
	// GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;

#ifdef JR6001_BUSY // 查忙引脚配置

	RCC_APB2PeriphClockCmd(JR6001_BUSY_GPIO_CLK, ENABLE); // 使能POR时钟
	GPIO_InitStructure.GPIO_Pin = JR6001_BUSY_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = JR6001_BUSY_GPIO_Mode;
	GPIO_Init(JR6001_BUSY_GPIO_PORT, &GPIO_InitStructure);

#endif
	JR6001_Volumecontrol(31); // 设置音量
	JR6001_ms(100);
}

// 串口发送数据
void JR6001_SendCode(u8 *str, u8 busy)
{
	u16 len, i;
	len = strlen((char *)str);
	printf("%sn", str);

	if (busy == 1 && JR6001_BUSY_IO == 0)
	{
		for (i = 0; i <= len; i++) // 循环发送数据
		{
			while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
				; // 循环发送,直到发送完毕
			USART_SendData(USART2, str[i]);
		}
	}
	else if (busy == 0)
	{
		for (i = 0; i <= len; i++) // 循环发送数据
		{
			while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
				; // 循环发送,直到发送完毕
			USART_SendData(USART2, str[i]);
		}
	}
	JR6001_ms(10);
}
// 基础指令发送
void JR6001_Instruction(u8 *str, u8 busy)
{
	u8 JR6001_Buff[20];
	sprintf((char *)JR6001_Buff, "%srn", str);
	JR6001_SendCode(JR6001_Buff, busy);
}
// 曲目选择
void JR6001_SongControl(u8 num, u8 busy)
{
	u8 JR6001_Buff[20];
	if (num < 10)
	{
		sprintf((char *)JR6001_Buff, "A7:0000%drn", num);
		JR6001_SendCode(JR6001_Buff, busy);
	}
	else if (num < 100)
	{
		sprintf((char *)JR6001_Buff, "A7:000%drn", num);
		JR6001_SendCode(JR6001_Buff, busy);
	}
	else
	{
		sprintf((char *)JR6001_Buff, "A7:00%drn", num);
		JR6001_SendCode(JR6001_Buff, busy);
	}
}
// 音量选择
void JR6001_Volumecontrol(u8 num)
{
	u8 JR6001_Buff[20];
	sprintf((char *)JR6001_Buff, "AF:%drn", num);
	JR6001_SendCode(JR6001_Buff, 0);
}

/*
	JR6001_Init();
	JR6001_SongControl(5,0);

*/

JR6001.h

功能函数的定义

#ifndef __JR6001_H
#define __JR6001_H

#include "sys.h"

// 查忙使能
#define JR6001_BUSY 0 // 0.失能 1.使能

// JR6001查忙引脚配置 高电平忙
#define JR6001_BUSY_GPIO_CLK RCC_APB2Periph_GPIOA
#define JR6001_BUSY_GPIO_PORT GPIOA
#define JR6001_BUSY_GPIO_PIN GPIO_Pin_6
#define JR6001_BUSY_GPIO_Mode GPIO_Mode_IPD

#define JR6001_BUSY_IO GPIO_ReadInputDataBit(JR6001_BUSY_GPIO_PORT, JR6001_BUSY_GPIO_PIN) // 读取查忙引脚

// JR6001串口命令[播放 暂停 上一曲 下一曲 音量加 音量减]
#define Play "A2"
#define Suspend "A3"
#define On_Song "A5"
#define Next_Song "A6"
#define Volumeadd "B0"
#define Volumesub "B1"

void JR6001_Init(void);
// 串口发送数据
void JR6001_SendCode(u8 *str, u8 busy);
// 基础指令发送
void JR6001_Instruction(u8 *str, u8 busy);
// 曲目选择
void JR6001_SongControl(u8 num, u8 busy);
// 音量选择
void JR6001_Volumecontrol(u8 num);
#endif

三、参考

【STM32】 JR6001语音播放icon-default.png?t=N7T8https://blog.csdn.net/m0_56051805/article/details/125116764?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170200319216800184185082%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170200319216800184185082&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-125116764-null-null.142^v96^pc_search_result_base7&utm_term=stm32JR6001&spm=1018.2226.3001.4187


完整代码请关注卫星公众号进行获取和咨询


联系方式 微信号:13648103287

  • 联系方式.docx
    下载

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
MCF5282CVM66J 1 Freescale Semiconductor IC,MICROCONTROLLER,32-BIT,COLDFIRE CPU,CMOS,BGA,256PIN,PLASTIC
暂无数据 查看
STM32F103RCT6TR 1 STMicroelectronics Mainstream Performance line, Arm Cortex-M3 MCU with 256 Kbytes of Flash memory, 72 MHz CPU, motor control, USB and CAN

ECAD模型

下载ECAD模型
$9.98 查看
STM32H743XIH6TR 1 STMicroelectronics High-performance and DSP with DP-FPU, Arm Cortex-M7 MCU with 2MBytes of Flash memory, 1MB RAM, 480 MHz CPU, Art Accelerator, L1 cache, external memory interface, large set of peripherals

ECAD模型

下载ECAD模型
暂无数据 查看
点赞
收藏
评论
分享
加入交流群
举报

相关推荐

方案定制

去合作
方案开发定制化,2000+方案商即时响应!

方案定制,程序设计方案、单片机程序设计与讲解、APP定制开发。本公众号致力于向读者传递关于程序设计和开发的相关知识,并分享一些关于软件开发的最佳实践。如果您有什么问题或建议,请随时联系我们。我们将竭诚为您服务