欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

程序员文章站 2022-06-24 18:46:13
整理东西整理出了几块RDA5851S模块查了一下相关资料,发现是在车载上用的,还可以进行AT控制看到这里我觉得还好,因为这种可以AT控制的蓝牙模块还是比较常见的,本着试一试的心思,接电源线,想到接功放和喇叭太费事儿,直接连接了一个耳机口,插上耳机,通电蓝牙名称还是很好找的 CAR KIT ,点击蓝牙连接,手机放歌,耳机里传出了声音,一切正常,除了没有蓝牙连接提示音,断开连接提示音。接着用USB转串口接到蓝牙的RX TX上,数据显示乱码,切换波特率,再来。。。....

整理东西整理出了几块RDA5851S模块

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

本着物尽其用的原则,我查了一下相关资料,发现是在车载上用的,还可以进行AT控制

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

看到这里我觉得还好,因为这种可以AT控制的蓝牙模块还是比较常见的,

本着试一试的心思,接电源线,想到接功放和喇叭太费事儿,直接连接了一个耳机口,插上耳机,通电

蓝牙名称还是很好找的  CAR KIT ,点击蓝牙连接,手机放歌,耳机里传出了声音,一切正常,除了没有蓝牙连接提示音,断开连接提示音。

接着用USB转串口接到蓝牙的RX TX上,数据显示乱码,切换波特率,再来。。。

终于,波特率57600情况下,显示正常了,哎等等,怎么还有乱码?

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

换歌再来,还是乱码

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

灵机一动,放个英文歌

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

发现了新大陆

MI1后面就是歌名

MI2后面就是歌手

那么问题来了,汉字歌名怎么不行呢?

看看16进制到底发了什么

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

找个转换工具转一下

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

喜出望外,说明汉字歌曲是可以的,但为什么这里可以显示,串口助手就不行?

换一个支持改编码的串口助手

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

原来如此,模块发送出来是UTF-8编码的数据,英文数字因为编码一样可以正常显示,而汉字编码则为乱码。找到原因就好办了。

因为单片机显示汉字是GBK编码的字库,而现在是UTF-8编码,UTF-8可以转GBK吗?查查查起来。。。

UTF-8不能直接转GBK,但是UTF-8可以转成Unicode,而Unicode经过一个大表可以对应到GBK。

代码实现

/************************************************************************
* 函数名称: StrProcess_UTF8toGBK
* 函数功能: 将网络上 utf8 的字符串转换为 GBK 字符串 使得兼容 原子LCD屏驱动程序
* 函数输入: void input: c_utf8 原utf8 字符串 同时 新的 gbk字符串会将其覆盖
* length 你想要设置的 中间缓存块的大小
* 函数输出: void output:字符总数 (一个中文算两个字节)
* 作者 :
* 文件依存:
* #include “ff.h”
* #include “malloc.h”
* #include “stm32f10x.h”
************************************************************************/
int16_t StrProcess_UTF8toGBK(u8 *c_utf8, u16 length)
{
    char low;
    char high;
    char middle;

    // ff_uni2oem(,FF_CODE_PAGE);
    /* !< 首先 将 utf8 转换成标准 Unicode 然后查表将 Unicode 转化为GBK */
    u16 outputSize = 0; //记录转换后的gbk字符串长度
    u8 *pInput = c_utf8;
    u8 *c_gbk = mymalloc(0, length); /* !< 申请内存,也可以外部传入一个 数据缓存空间 */
    u8 *pOutput = c_gbk;
    u16 *uni = (u16 *)c_gbk;
    u16 gbk;
    /* !< 以下中间代码来自于 CSDN @bladeandmaster88 公开的源码 */
    while (*pInput)
    {
        if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符(英文字母、数字)
        {
            *pOutput = *pInput;
            pOutput += 1;
            *pOutput = 0; //小端法表示,在高地址填补0
        }
        else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符
        {
            high = *pInput;
            pInput += 1;
            low = *pInput;
            if ((low & 0xC0) != 0x80) //检查是否为合法的UTF8字符表示
            {
                return -1; //如果不是则报错
            }

            *pOutput = (high << 6) + (low & 0x3F);
            pOutput++;
            *pOutput = (high >> 2) & 0x07;
        }
        else if (((*pInput) & 0xF0) == 0xE0) //处理三字节UTF8字符
        {
            high = *pInput;
            pInput++;
            middle = *pInput;
            pInput++;
            low = *pInput;
            if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80))
            {
                return -1;
            }
            *pOutput = (middle << 6) + (low & 0x3F);//取出middle的低两位与low的低6位,组合成unicode字符的低8位
            pOutput++;
            *pOutput = (high << 4) + ((middle >> 2) & 0x0F); //取出high的低四位与middle的中间四位,组合成unicode字符的高8位
        }
        else //对于其他字节数的UTF8字符不进行处理
        {
            return -1;
        }
        pInput++;//处理下一个utf8字符
        pOutput++;
    }
    //unicode字符串后面,有两个\0
    *pOutput = 0;
    pOutput++;
    *pOutput = 0;
    /* !< 感谢 @bladeandmaster88 的开源支持 */
    pInput = c_utf8;
    while(*uni != 0)

    {
        gbk = ff_convert((WCHAR) * uni, 0);
        //    gbk = ff_uni2oem(*uni,FF_CODE_PAGE);        /* !< Unicode 向 GBK 转换函数  */
        uni++;
        if(gbk & 0xff00)
        {
            *pInput = ((gbk & 0xff00) >> 8);
            pInput++;
            *pInput = (gbk & 0x00ff);
            pInput++;
            outputSize += 2;
        }
        else
        {
            *pInput = (gbk & 0x00ff);
            pInput++;
            outputSize++;
        }


    }
    *pInput = '\0';         /* !< 加上结束符号 */
    myfree(0, c_gbk);       /* !< 释放内存 */
    return outputSize;
}

蓝牙数据解析

void Data_Analysis()
{
    char *ptr;
    uint8_t lenth = 0;
    uint8_t i = 0;

    ptr = strstr((char *)STR_BUF, "IB");		//已连接
    if(ptr != NULL)
    {
        Connect_Flag = 1;
    }
    else
    {
        ptr = strstr((char *)STR_BUF, "IA");		//断开连接
        if(ptr != NULL)
        {
            Connect_Flag = 0;
        }
    }
    ptr = strstr((char *)STR_BUF, "MB");		//开始播放
    if(ptr != NULL)
    {
        Play_Flag = 1;
    }
    else
    {
        ptr = strstr((char *)STR_BUF, "MA");		//停止播放
        if(ptr != NULL)
        {
            Play_Flag = 0;
        }
    }
    ptr = strstr((char *)STR_BUF, "MI1");		//歌名
    if(ptr != NULL)
    {
        Connect_Flag = 1;
        Play_Flag = 1;
        ptr = ptr + 3;
        lenth = 127;
        i = 0;
        memset(STR_Name , 0 , 127);
        while ((*ptr != 0x0D) && (lenth --))
        {
            STR_Name[i++] = *(ptr++);
        }
    }
    ptr = strstr((char *)STR_BUF, "MI2");		//歌手
    if(ptr != NULL)
    {
        ptr = ptr + 3;
        lenth = 127;
        i = 0;
        memset(STR_Singer , 0 , 127);
        while ((*ptr != 0x0D) && (lenth --))
        {
            STR_Singer[i++] = *(ptr++);
        }
    }
}

接下来就是STM32显示了

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

接着又画了一下PCB,毕竟总是连着线也不太好,带有充电电路,小集成功放,MOS管控制蓝牙电源,状态指示灯等(毕竟这个蓝牙没连接提示音)。

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

焊接调试好没问题。

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

基于stm32和RDA5851S蓝牙模块的歌名歌手同步显示

自动居中显示,如果超长则滚动显示

void Dis_Play()
{
    uint8_t STR_Name_len;
    uint8_t STR_Singer_len;
    int8_t STR_Name_can;
    int8_t STR_Singer_can;
    uint8_t STR_Name_symbol = 0;
    uint8_t STR_Singer_symbol = 0;
    int8_t i , j ;

    if(Play_Flag)
    {
        Lcd_P16x16Ch(88, 0, (uint8_t *)"播放", 0);
        Connect_Flag = 1;
    }
    else
    {
        if(Connect_Flag)
        {
            Lcd_P16x16Ch(88, 0, (uint8_t *)"暂停", 0);
        }

    }
    if(Connect_Flag)
    {
        Lcd_P16x16Ch(8, 0, (uint8_t *)"已连接", 0);
				LED2_ON;
    }
    else
    {
        Lcd_P16x16Ch(8, 0, (uint8_t *)"未连接", 0);
				LED2_OFF;
    }

    Lcd_fill(0, 4, 128, 4, 0);


    if(STR_Name_lenth > 16)	//歌名超长滚动处理
    {
        STR_Name_can = STR_Name_lenth - STR_Name_num ;

        if(STR_Name_can < 0)
        {
            STR_Name_num = 0;
            STR_Name_can = STR_Name_lenth - STR_Name_num ;
        }

        if(STR_Name_can > 16)
        {

            for(i = 0 ; i < 16 ; i ++)
            {
                if(STR_Name [i + STR_Name_num] <= 0x80)
                {
                    STR_Name_symbol ++;
                }
                Dis_STR_Name[i] = STR_Name [i + STR_Name_num] ;
            }

        }
        else
        {
            for(i = 0 ; i < STR_Name_can ; i ++)
            {
                Dis_STR_Name[i] = STR_Name [i + STR_Name_num] ;
            }
            Dis_STR_Name[i ++] = 0x20 ;
            Dis_STR_Name[i ++] = 0x20 ;
            STR_Name_can = STR_Name_can + 2 ;
            j = 0 ;
            for(; i < 16 ; i++)
            {
                Dis_STR_Name[i] = STR_Name [j++] ;
            }

            for(i = 0; i < 16 ; i++)
            {
                if(Dis_STR_Name[i] <= 0x80)
                {
                    STR_Name_symbol ++;
                }
            }

        }


        if(STR_Name_symbol % 2)
        {
            Dis_STR_Name[15] = 0;
        }
        if(Dis_STR_Name[0] <= 0x80)
        {
            STR_Name_num += 1;
        }
        else
        {
            STR_Name_num += 2;
        }

        STR_Name_len = 0;
    }
    else		//歌名自动居中处理
    {
        memset(Dis_STR_Name , 0 , 16);
        for(i = 0 ; i < STR_Name_lenth ; i ++)
        {
            Dis_STR_Name[i] = STR_Name [i] ;
        }
        STR_Name_len = (128 - STR_Name_lenth * 8) / 2;
    }



    if(STR_Singer_lenth > 16)	//歌手超长滚动处理
    {
        STR_Singer_can = STR_Singer_lenth - STR_Singer_num ;

        if(STR_Singer_can < 0)
        {
            STR_Singer_num = 0;
            STR_Singer_can = STR_Singer_lenth - STR_Singer_num ;
        }

        if(STR_Singer_can > 16)
        {

            for(i = 0 ; i < 16 ; i ++)
            {
                if(STR_Singer [i + STR_Singer_num] <= 0x80)
                {
                    STR_Singer_symbol ++;
                }
                Dis_STR_Singer[i] = STR_Singer [i + STR_Singer_num] ;
            }

        }
        else
        {
            for(i = 0 ; i < STR_Singer_can ; i ++)
            {
                Dis_STR_Singer[i] = STR_Singer [i + STR_Singer_num] ;
            }
            Dis_STR_Singer[i ++] = 0x20 ;
            Dis_STR_Singer[i ++] = 0x20 ;
            STR_Singer_can = STR_Singer_can + 2 ;
            j = 0 ;
            for(; i < 16 ; i++)
            {
                Dis_STR_Singer[i] = STR_Singer [j++] ;
            }

            for(i = 0; i < 16 ; i++)
            {
                if(Dis_STR_Singer[i] <= 0x80)
                {
                    STR_Singer_symbol ++;
                }
            }

        }


        if(STR_Singer_symbol % 2)
        {
            Dis_STR_Singer[15] = 0;
        }
        if(Dis_STR_Singer[0] <= 0x80)
        {
            STR_Singer_num += 1;
        }
        else
        {
            STR_Singer_num += 2;
        }

        STR_Singer_len = 0;
    }
    else	//歌手自动居中处理
    {
        memset(Dis_STR_Singer , 0 , 16);
        for(i = 0 ; i < STR_Singer_lenth ; i ++)
        {
            Dis_STR_Singer[i] = STR_Singer [i] ;
        }
        STR_Singer_len = (128 - STR_Singer_lenth * 8) / 2;
    }

    Lcd_P16x16Ch(STR_Name_len, 4, Dis_STR_Name, 0);		//歌名显示
    Lcd_P16x16Ch(STR_Singer_len, 6, Dis_STR_Singer, 0);		//歌手显示

}

 

大功告成,试了一下,几乎所有音乐软件都可以(主流的那几个都试了,包括自带的音乐播放器,还有一些游戏背景音乐也可以)可以同步显示歌名歌手,再也不用为不知道现在放的什么歌而苦恼了,也不用打开手机查看了。

以下就是全部下载资料https://download.csdn.net/download/qq_22848695/13106771

 

后续:因为汉字显示是Unicode通过一个大表可以对应到GBK,而这个表只有基本汉字(意思就是没有一些生僻字和部分特殊符号),即使这样,程序也达到了190K,不过实际使用中影响不大,我切了几十首歌才有一个因为特殊符号乱码的(可能我找的歌也不到位)。

 

 

 

本文地址:https://blog.csdn.net/qq_22848695/article/details/109627255

相关标签: 单片机 蓝牙