2024年物联网嵌入式最新单片机语音模块JQ8900-16P的几种触发方式与源码配置,29岁vivo员工吐槽

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

配置方式

1,IO口触发播放

2,双线串口

3,单线串口

1,IO口触发播放

请添加图片描述
请添加图片描述

注意音频文件命名与端口触发对照表;

当然端口也可以复用:

按照配置软件配置就行,主要是要实现在端口上的开始/暂停,上一曲/下一曲,这些操作

请添加图片描述

2,双线串口

这种方式也是我们最常用的一种方式,通过TX,RX与单片机通讯,接受单片机串口发送过来的指令进行事先通讯约定的操作:

重点关注的部分我已经用红线标明了:

请添加图片描述

一定一定注意这个和校验,每次修改指令的时候都要将校验码(SM)修改一遍,不然发送指令可能无响应。

请添加图片描述

详细的其他指令:
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

​ 看到这里你大概明白怎么操作了吧,就是调用串口发送函数将这些十六进制指令都发送到单片机,那么为了方便,我们一般呢将一个指令用数组的形式储存起来,然后调用由串口通讯单字节发送函数封装的指定字节发送函数就行。然后还有就是可以调用资料里面的串口软件直接生成相关指令,但是我一点那个软件就卡退。所以这里还是将每一条指令手编的。

我将常用的指令封装成数组,供大家参考:

(复制到keil5里面显示注释,这里md文档用utf-8显示的是乱码)

u8 code Mode0[] = {0xAA, 0x18, 0x01, 0x00, 0xC3};//Ñ­»·²¥·Åģʽ
u8 code Mode1[] = {0xAA, 0x18, 0x01, 0x01, 0xC4};
u8 code Mode2[] = {0xAA, 0x18, 0x01, 0x02, 0xC5};
u8 code Mode3[] = {0xAA, 0x18, 0x01, 0x03, 0xC6};
u8 code Mode4[] = {0xAA, 0x18, 0x01, 0x04, 0xC7};
u8 code Mode5[] = {0xAA, 0x18, 0x01, 0x05, 0xC8};
u8 code Mode6[] = {0xAA, 0x18, 0x01, 0x06, 0xC9};
u8 code Mode7[] = {0xAA, 0x18, 0x01, 0x07, 0xCA};

u8 code PrevFile[] = {0xAA, 0x05, 0x00, 0xAF};//ÉÏÒ»Ê×
u8 code NextFile[] = {0xAA, 0x06, 0x00, 0xB0};//ÏÂÒ»Ê×
u8 code Play[] = {0xAA, 0x02, 0x00, 0xAC};    //²¥·Å
u8 code Stop[] = {0xAA, 0x04, 0x00, 0xAE};    //Í£Ö¹
u8 code Pause[] = {0xAA, 0x03, 0x00, 0xAD};    //Í£Ö¹
u8 code Path[] = {0xAA, 0x08, 0x10, 0x02, 0x2F, 0xB9, 0xE3, 0xB8, 0xE6, 0x2A, 0x2F, 0xD0, 0xA1, 0xC3, 0xD7, 0x2A, 0x4D, 0x50, 0x33, 0x8B, }; // flash /¹ã¸æ\*/СÃ×\*MP3
u8 code Voiceup[] = {0xAA, 0x14, 0x00, 0xBE};  //ÒôÁ¿Ôö
u8 code Voicedown[] = {0xAA, 0x15, 0x00, 0xBF};//ÒôÁ¿¼õ

u8 code Play1[] = {0xAA, 0x07, 0x02, 0x00, 0x01, 0xB4}; //Ö¸¶¨²¥·ÅµÚ1Ê×
u8 code Play2[] = {0xAA, 0x07, 0x02, 0x00, 0x02, 0xB5}; //Ö¸¶¨²¥·ÅµÚ2Ê×
u8 code Play3[] = {0xAA, 0x07, 0x02, 0x00, 0x03, 0xB6}; //Ö¸¶¨²¥·ÅµÚ3Ê×
u8 code Play4[] = {0xAA, 0x07, 0x02, 0x00, 0x04, 0xB7}; //Ö¸¶¨²¥·ÅµÚ4Ê×
u8 code Play5[] = {0xAA, 0x07, 0x02, 0x00, 0x05, 0xB8}; //Ö¸¶¨²¥·ÅµÚ5Ê×
u8 code Play6[] = {0xAA, 0x07, 0x02, 0x00, 0x06, 0xB9}; //Ö¸¶¨²¥·ÅµÚ6Ê×
u8 code Play7[] = {0xAA, 0x07, 0x02, 0x00, 0x07, 0xBA}; //Ö¸¶¨²¥·ÅµÚ7Ê×
u8 code Play8[] = {0xAA, 0x07, 0x02, 0x00, 0x08, 0xBB}; //Ö¸¶¨²¥·ÅµÚ8Ê×
u8 code Play9[] = {0xAA, 0x07, 0x02, 0x00, 0x09, 0xBC}; //Ö¸¶¨²¥·ÅµÚ9Ê×

u8 code Combine[] = {0xAA, 0x1B, 0x04, 0x30, 0x31 ,0X30 ,0X32 ,0x8C}; //×éºÏ²¥·ÅZHÎļþ¼ÐϵÄ01£¬02Îļþ


串口通讯函数

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
¹¦ÄÜÃèÊö£º ´®¿Ú·¢ËÍ×Ö·û´®Êý¾Ý
Èë¿Ú²ÎÊý£º \*DAT£º×Ö·û´®Ö¸Õë
·µ »Ø Öµ£º none
ÆäËû˵Ã÷£º API ¹©ÍⲿʹÓã¬Ö±¹Û£¡
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void UART1\_SendString(u8 \*DAT,u8 Len)
{
    while(Len--)
    {
        UART1\_SendByte(\*DAT);
        DAT++;
    }
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
¹¦ÄÜÃèÊö£º ´®¿Ú·¢ËÍ×Ö½ÚÊý¾Ý
Èë¿Ú²ÎÊý£º \*DAT£º×Ö·û´®Ö¸Õë
·µ »Ø Öµ£º none
ÆäËû˵Ã÷£º API ¹©ÍⲿʹÓã¬Ö±¹Û£¡
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void UART1\_SendByte(u8 value)
{
    ES=0; //¹Ø±Õ´®¿ÚÖжÏ
    TI=0; //Çå·¢ËÍÍê±ÏÖжÏÇëÇó±ê־λ
    SBUF=value; //·¢ËÍ
    while(TI==0); //µÈ´ý·¢ËÍÍê±Ï
    TI=0; //Çå·¢ËÍÍê±ÏÖжÏÇëÇó±ê־λ
    ES=1; //ÔÊÐí´®¿ÚÖжÏ
}


串口初始化函数(11.0592MHz的晶振,9600波特率)

void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//²¨ÌØÂʲ»±¶ËÙ
	SCON = 0x50;		//8λÊý¾Ý,¿É±ä²¨ÌØÂÊ
	TMOD &= 0x0F;		//Çå³ý¶¨Ê±Æ÷1ģʽλ
	TMOD |= 0x20;		//É趨¶¨Ê±Æ÷1Ϊ8λ×Ô¶¯ÖØ×°·½Ê½
	TL1 = 0xFD;		//É趨¶¨Ê±³õÖµ
	TH1 = 0xFD;		//É趨¶¨Ê±Æ÷ÖØ×°Öµ
	ET1 = 0;		//½ûÖ¹¶¨Ê±Æ÷1ÖжÏ
	TR1 = 1;		//Æô¶¯¶¨Ê±Æ÷1
}

另外想插一个便捷控制组合播放的函数:(指令代号1B)

如果按之前的配置方法,那么需要将我们需要组合播放的曲目名换成高低位的十六进制表示,但是因为组合播放要求是mp3文件放在名为“ZH”的文件夹下,而且曲目名只能是两个字节,例如说01,02这样子。

配置方法也很简单就是将十位数字+0x30作为高位,将个位数字+0x30作为低位数字。

下面是示例中配置的组合播放01,02的数组代码,用串口发送字节依次发送即可。

u8 code Combine[] = {0xAA, 0x1B, 0x04, 0x30, 0x31 ,0X30 ,0X32 ,0x8C};

但是每次都要重新编写数组的话不免有些复杂:下面这个函数就是替代了将十位数字+0x30作为高位,将个位数字+0x30作为低位数字,这个操作。

同样的如果我们要组合播放01,02,那么只需要向函数穿入数组 i[1,2] 就行,数组长度Len传入2。

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
¹¦ÄÜÃèÊö£º×éºÏ²¥±¨º¯Êý
Èë¿Ú²ÎÊý£º \*DAT£º×Ö·û´®Ö¸Õë,Len×Ö·û´®³¤¶È
·µ »Ø Öµ£º none
ÆäËû˵Ã÷£º ½«ÐèÒª²¥±¨µÄÎļþÃû·ÅÈëÊý×éÖÐ×÷ΪÐβμ´¿É
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void  JQ\_8x00\_ZuHeBoFang(u8 \*DATA,u8 Len)
{
	u16 CRC_data=0,i = 3;
	u8 Buffer[ZH_MAX] ={0xaa,0x1b};
	Buffer[2] = Len\*2;			//¼ÆËãÊý¾Ý³¤¶È(ÿ¸öÇúÄ¿ÓɸßλÓëµÍλ¹¹³É£¬ËùÒÔ³ËÒÔ2)
	CRC_data = CRC_data + 0xaa + 0x1b + Buffer[2];
	while(Len--)
	{
		Buffer[i] = \*DATA/10+0x30;			//È¡³öʮ룬ºó¼ÓÈë0x30
		CRC_data = CRC_data + Buffer[i];
		i++;
		Buffer[i] = \*DATA%10+0x30;			//È¥³ý¸÷룬ºó¼ÓÈë0x30
		CRC_data = CRC_data + Buffer[i];
		i++;
		DATA++;
	}
	Buffer[i] = CRC_data;//УÑéλ

	UART1\_SendString(Buffer,i+1);
}

下面我想补充一个知识点:

就是我在编写串口连续发送函数的时候:

void UART1\_SendString(u8 \*DAT,u8 Len)
{
    while(Len--)
    {
        UART1\_SendByte(\*DAT);
        DAT++;
    }
}

每次传入的数组还要数有几个元素,再将Len传入函数。是在是复杂。而且这个函数最大的缺点是,如果你数数,数少了。那么不会报错,而且芯片也没有反应。但是多了是没有问题的。

我第一想到构造的函数是这样的:进行数组大小次发送,每次发送完了以后数组的地址+1;

void UART1\_SendData(u8 \*DAT)
{
	unsigned char i;
    for(i=0; i<sizeof(DAT); i++)
    {
        UART1\_SendByte(\*DAT);
		DAT++;
    }
}

但是实际上,传递到函数的数组名是数组的首地址,用sizeof(DAT)并不能求出数组的长度,得到的是指针变量DAT的内存大小,依据操作系统不同而异。

详细如下:

请添加图片描述

所以我用的这个函数:

void UART1\_SendData(u8 \*DAT)
{
	unsigned char i;
    for(i=0; i<6; i++)
    {
        UART1\_SendByte(\*DAT);
		DAT++;
    }
}

因为,常用的指令中,一般都是发送4个,5个,最多6个十六进制数据。而组合播放用之前封装的函数也足够了;

3,单线串口

​ 需要单片机在端口处依照严格的时序通过高低电平持续的时间来表示逻辑0和1,优点就不用多说了,对于51单片机而言,只有P3_1与P3_0处的一个串口。如果使用单线通讯可以将串口节省出来用作蓝牙模块的连接啊什么的。单线通讯的连线是1号引脚口VPP引出的,具体看之前的引脚示意图:

请添加图片描述

这个第三条的脉冲比例基数我没查到词条,但是就我理解的话:

如果脉冲比例基数为4的话,就是示例,即

高定平:低电平=4:1 表示1

高定平:低电平=1:4 表示0

也不知道说的对不对哈,欢迎指正

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

,欢迎指正

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-3nxRd3RN-1715662994765)]
[外链图片转存中…(img-8eRPA4Re-1715662994766)]

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值