加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入

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

03/20 16:37
8113
服务支持:
技术交流群

完成交易后在“购买成功”页面扫码入群,即可与技术大咖们分享疑惑和经验、收获成长和认同、领取优惠和红包等。

虚拟商品不可退

当前内容为数字版权作品,购买后不支持退换且无法转移使用。

加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论
放大
实物图
相关方案
  • 方案介绍
    • 一、模块介绍
    • 二、移植使用(资料代码中没有移植后的代码,需要自行移植)
    • 三、参考
  • 相关文件
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

一、模块介绍

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模型 风险等级 参考价格 更多信息
MK22FX512VMC12 1 NXP Semiconductors RISC MICROCONTROLLER
$9.31 查看
STM32F407IGT6 1 STMicroelectronics High-performance foundation line, Arm Cortex-M4 core with DSP and FPU, 1 Mbyte of Flash memory, 168 MHz CPU, ART Accelerator, Ethernet, FSMC

ECAD模型

下载ECAD模型
$13.79 查看

相关推荐

电子产业图谱

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