一、模块介绍
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语音播放https://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