打印
[活动专区]

【N32G430开发板试用】 带中文菜单式MP3音乐播放器

[复制链接]
1786|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 jinglixixi 于 2022-8-20 14:13 编辑

#申请原创#
MP3音频模块是一种可以串口进行控制的器件,在设计中文菜单式MP3播放器时,用该模块可提高MCU处理的并行性,该设计的整体构成如图1所示。
图1 整体构成
图2 模块构成
在运行过程中,其处理流程图3所示。
图3处理流程图
在使用过程中,通过板上的4个按键可进行歌曲的选取及音量调整等。此外,为了能扩展菜单的容量,还增添了边界自动换页的处理功能,其页面形式如图4所示。
图4界面效果
1. TFT显示屏驱动与界面设计
在该设计中,是采用2.2寸TFT彩屏,它采用SPI接口来工作。
1)引脚配置
TFT屏与开发板连接关系为:
BLK-------PB8
CS---------PB7
RS---------PB6
RST-------PB5
SCL------- PB3
SDA------ PB4
为便于控制引脚输出高低电平,其语句定义为:
#define LCD_SCK_Low()   GPIO_Pins_Reset(GPIOB, GPIO_PIN_3)   //CLK
#define LCD_SCK_High()  GPIO_Pins_Set(GPIOB, GPIO_PIN_3)
#define LCD_SDI_Low()   GPIO_Pins_Reset(GPIOB, GPIO_PIN_4)   //DIN
#define LCD_SDI_High()   GPIO_Pins_Set(GPIOB,GPIO_PIN_4)
#define LCD_REST_Low()   GPIO_Pins_Reset(GPIOB, GPIO_PIN_5)   //RES
#define LCD_REST_High()  GPIO_Pins_Set(GPIOB, GPIO_PIN_5)
#define LCD_DC_Low()    GPIO_Pins_Reset(GPIOB, GPIO_PIN_6)   //DC
#define LCD_DC_High()    GPIO_Pins_Set(GPIOB,GPIO_PIN_6)
#define LCD_CS_Low()    GPIO_Pins_Reset(GPIOB, GPIO_PIN_7)   //CS
#define LCD_CS_High()    GPIO_Pins_Set(GPIOB,GPIO_PIN_7)
#define LCD_LED_High()   GPIO_Pins_Set(GPIOB,GPIO_PIN_8)    //BLK
对TFT屏所用引脚的配置函数为:
void app_tft_init(void)
{
         GPIO_InitType GPIO_InitStructure;
         RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
         GPIO_Structure_Initialize(&GPIO_InitStructure);
         GPIO_InitStructure.Pin= GPIO_PIN_5|GPIO_PIN_7;
         GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
         GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
         GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
         RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
         GPIO_Structure_Initialize(&GPIO_InitStructure);
         GPIO_InitStructure.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8;
         GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
         GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
         GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
         LCD_LED_High();
}

2)初始化
为使TFT屏工作,其初始化函数为:
void tft_Init(void)
{
           LCD_REST_Low();
           SysTick_Delay_Ms(20);
           LCD_REST_High();
           SysTick_Delay_Ms(20);
      LCD_CS_Low();
      LCD_WR_REG(0xCB);
      LCD_WR_DATA8(0x39);
      LCD_WR_DATA8(0x2C);
      LCD_WR_DATA8(0x00);
      LCD_WR_DATA8(0x34);
      LCD_WR_DATA8(0x02);
      LCD_WR_REG(0xCF);
      LCD_WR_DATA8(0x00);
      LCD_WR_DATA8(0XC1);
      LCD_WR_DATA8(0X30);
      LCD_WR_REG(0xE8);
      LCD_WR_DATA8(0x85);
      LCD_WR_DATA8(0x00);
      LCD_WR_DATA8(0x78);
      LCD_WR_REG(0xEA);
      LCD_WR_DATA8(0x00);
      LCD_WR_DATA8(0x00);
      LCD_WR_REG(0xED);
      LCD_WR_DATA8(0x64);
      LCD_WR_DATA8(0x03);
      LCD_WR_DATA8(0X12);
      LCD_WR_DATA8(0X81);
      LCD_WR_REG(0xF7);
      LCD_WR_DATA8(0x20);
      LCD_WR_REG(0xC0);
      LCD_WR_DATA8(0x23);
      LCD_WR_REG(0xC1);
      LCD_WR_DATA8(0x10);
      LCD_WR_REG(0xC5);
      LCD_WR_DATA8(0x3e);
      LCD_WR_DATA8(0x28);
      LCD_WR_REG(0xC7);
      LCD_WR_DATA8(0x86);
      LCD_WR_REG(0x36);
      LCD_WR_DATA8(0x48);
      LCD_WR_REG(0x3A);
      LCD_WR_DATA8(0x55);
      LCD_WR_REG(0xB1);
      LCD_WR_DATA8(0x00);
      LCD_WR_DATA8(0x18);
      LCD_WR_REG(0xB6);
      LCD_WR_DATA8(0x08);
      LCD_WR_DATA8(0x82);
      LCD_WR_DATA8(0x27);
      LCD_WR_REG(0xF2);
      LCD_WR_DATA8(0x00);
      LCD_WR_REG(0x26);
      LCD_WR_DATA8(0x01);
      LCD_WR_REG(0xE0);
      LCD_WR_DATA8(0x0F);
      LCD_WR_DATA8(0x31);
      LCD_WR_DATA8(0x2B);
      LCD_WR_DATA8(0x0C);
      LCD_WR_DATA8(0x0E);
      LCD_WR_DATA8(0x08);
      LCD_WR_DATA8(0x4E);
      LCD_WR_DATA8(0xF1);
      LCD_WR_DATA8(0x37);
      LCD_WR_DATA8(0x07);
      LCD_WR_DATA8(0x10);
      LCD_WR_DATA8(0x03);
      LCD_WR_DATA8(0x0E);
      LCD_WR_DATA8(0x09);
      LCD_WR_DATA8(0x00);
      LCD_WR_REG(0XE1);
      LCD_WR_DATA8(0x00);
      LCD_WR_DATA8(0x0E);
      LCD_WR_DATA8(0x14);
      LCD_WR_DATA8(0x03);
      LCD_WR_DATA8(0x11);
      LCD_WR_DATA8(0x07);
      LCD_WR_DATA8(0x31);
      LCD_WR_DATA8(0xC1);
      LCD_WR_DATA8(0x48);
      LCD_WR_DATA8(0x08);
      LCD_WR_DATA8(0x0F);
      LCD_WR_DATA8(0x0C);
      LCD_WR_DATA8(0x31);
      LCD_WR_DATA8(0x36);
      LCD_WR_DATA8(0x0F);
      LCD_WR_REG(0x11);
      SysTick_Delay_Ms(120);
      LCD_WR_REG(0x29);
      LCD_WR_REG(0x2c);
}

3)界面实现
该播放控制器的界面由图案和菜单构成,为便于控制,是按界面结构显示和菜单显示两部分来完成。
实现图案显示的函数为:
void show_tb(unsigned int x,unsigned int y)
{
         unsigned int i,j,k;
         unsigned int da;
         k=0;
         for(i=0;i<50;i++)
         {
                   for(j=0;j<50;j++)
                   {
                            da=gImage_tb[k*2];
                            da<<=8;
                            da|=gImage_tb[k*2+1];
            POINT_COLOR=da;
            LCD_DrawPoint(x-j,y+i);
                            k++;
                   }
         }
}

实现界面结构显示的函数为:
void LCD_JM() 
{
    LCD_Clear(RED);
    LCD_Fill(0,0,239,50,WHITE);
         show_tb(60,0);
         BACK_COLOR=WHITE;
         POINT_COLOR=RED;
         LCD_ShowChar(80,16,'M',1);
         LCD_ShowChar(90,16,'P',1);
         LCD_ShowChar(100,16,'3',1);
         showhanzi16(115,16,32);
         showhanzi16(135,16,33);
         showhanzi16(155,16,34);
         showhanzi16(175,16,35);
         showhanzi16(195,16,36);
         LCD_Fill(0,287,239,319,WHITE);
         BACK_COLOR=WHITE;
         POINT_COLOR=RED;
         LCD_ShowString(60,294,"BY: jinglixixi");
}

2. 中文菜单与选择处理
由于在菜单中是实现中文歌单,故需按菜单内容来构建中文字库。
1)字模提取
使用图5所示的字模提取软件,可辅助完成中文字库的构建,其提取格式见图6所示。
图5字模提取
图6字模格式
相应的字模存储结构为:
unsigned char hanzi16[]=
{
0x80,0x20,0x82,0x20,0xF4,0x17,0x84,0x08,0x80,0x00,0xE1,0x23,0x02,0x20,0xEA,0x13,
0x28,0x0A,0x24,0x42,0xE7,0x43,0x24,0x22,0x44,0x21,0x04,0x17,0xF4,0x08,0x20,0x04,/*"澎",0*/
0x80,0x00,0x84,0x78,0x88,0x48,0xE8,0x4B,0x81,0x48,0x82,0x78,0x82,0x48,0xE8,0x4B,
0x28,0x4A,0x24,0x7A,0x27,0x4A,0xE4,0x4B,0x24,0x4A,0x04,0x44,0x04,0x54,0x00,0x22,/*"湖",1*/
0x80,0x00,0x04,0x01,0xF8,0x3F,0x88,0x04,0xA1,0x14,0x92,0x24,0x02,0x00,0xE8,0x0F,
0x08,0x08,0xE4,0x0F,0x27,0x00,0xE4,0x1F,0x04,0x10,0x04,0x10,0x04,0x0A,0x00,0x04,/*"湾",2*/
...
}

配合上面的字库结构,其汉字显示函数为:
void showhanzi16(unsigned int x,unsigned int y,unsigned char index) 
{
         unsigned char i,j,k;
         const unsigned char *temp=hanzi16;
         temp+=index*32;
         Address_set(x,y,x+16-1,y+16-1);
         for(j=0;j<16;j++)
         {
                   for(k=0;k<2;k++)
                   {
                            for(i=0;i<8;i++)
                            {
                                    if((*temp&(1<<i))!=0)
                                     {
                                               LCD_WR_DATA(POINT_COLOR);
                                     }
                                     else
                                     {
                                               LCD_WR_DATA(BACK_COLOR);
                                     }
                            }
                            temp++;
                   }
          }
}

2)中文菜单
利用中文字库,实现中文菜单显示的函数为:
void LCD_MENU()
{
         BACK_COLOR=RED;
         POINT_COLOR=YELLOW;
         showhanzi16(60,75,0);
         showhanzi16(80,75,1);
         showhanzi16(100,75,2);
         showhanzi16(30,75,37);
         showhanzi16(60,105,3);
         showhanzi16(80,105,4);
         showhanzi16(100,105,5);
         showhanzi16(120,105,6);
         showhanzi16(60,135,7);
         showhanzi16(80,135,8);
         showhanzi16(60,165,9);
         showhanzi16(80,165,10);
         showhanzi16(60,195,11);
         showhanzi16(80,195,12);
         showhanzi16(100,195,13);
         showhanzi16(120,195,14);
         showhanzi16(60,225,15);
         showhanzi16(80,225,16);
         showhanzi16(100,225,17);
         showhanzi16(120,225,18);
         showhanzi16(140,225,19);
         showhanzi16(60,255,20);
         showhanzi16(80,255,21);
         showhanzi16(100,255,22);
         showhanzi16(120,255,23);
         showhanzi16(140,255,24);
         showhanzi16(160,255,25);
         showhanzi16(180,255,26);
}

3)选择处理与指示
在开发板上,共有5个按键,除复位键外,皆可用于程序控制,其原理图见图7所示。
图7  LED与KEY电路
为便于MP3的控制,其中各键的功能分配如下:
S1------PA4----下一首
S2------PA5----上一首
S3------PA6----确认
S6------PA0----音量
此外,为了便于观察还使用D1和D2来指示S1和S2键的操作状态。
在歌曲选择时,是通过星型的光标来指示的,在确认后即可播放选择的歌曲。
实现按键选择及播放的测试程序如下:
void sele()
{
         BACK_COLOR=RED;
         POINT_COLOR=YELLOW;
         h=75;
         i=0;
         while(1)
         {
                 if(GPIO_Input_Pin_Data_Get(GPIOA, GPIO_PIN_4)==0)
                            {
                                     GPIO_Pins_Set(GPIOA, GPIO_PIN_1);
                                     if(i<6)
                                     {
                                               i++;
                                          LCD_Fill(30,h,50,h+20,RED);
                                          h=h+30;
                                          showhanzi16(30,h,37);
                                     }
                            }
            else
                            {
                                     GPIO_Pins_Reset(GPIOA, GPIO_PIN_1);
                            }
                            if(GPIO_Input_Pin_Data_Get(GPIOA, GPIO_PIN_5)==0)
                            {
                                     GPIO_Pins_Set(GPIOA, GPIO_PIN_7);
                if(i>0)
                                     {
                                                i--;
                                          LCD_Fill(30,h,50,h+20,RED);
                                          h=h-30;
                                          showhanzi16(30,h,37);
                                     }
                            }
            else
                            {
                                     GPIO_Pins_Reset(GPIOA, GPIO_PIN_7);
                            }
                            if(GPIO_Input_Pin_Data_Get(GPIOA, GPIO_PIN_6)==0)
                            {
                                     playn(i);
                                     TxCounter=0;
                                     while (TxCounter < 10)
                {
                                                USART_Data_Send(USARTy, cmd3[TxCounter]);
                                     TxCounter++;
                                                while(USART_Flag_Status_Get(USARTy, USART_FLAG_TXDE) == RESET);
                           }
                            }
            SysTick_Delay_Ms(200);
         }
}


3. MP3播放模块控制
MP3播放模块是一款可以串口通信进行控制的器件,其引脚分别如图8所示。
其实,在使用中除电源引脚外,它只占用一个串口输出引脚,即PA9。
此外,由于该模块的通讯波特率为9600bps,故需在此波特率下工作。
图8MP3播放模块
1)串口通信
字节指令发送是控制MP3播放模块的关键,其程序为:
TxCounter=0;
while (TxCounter < 10)
{
           USART_Data_Send(USARTy, cmd[TxCounter]);
           TxCounter++;
           while(USART_Flag_Status_Get(USARTy, USART_FLAG_TXDE) == RESET);
}

2)播放控制
MP3播放指定乐曲是靠指定音乐序号来完成的,其生成相应播放指令的函数为:
void playn(int index)
{
         int i;
         unsigned char checksum = 0;
         cmd3[5] = (unsigned char)(index >> 8);
         cmd3[6] = (unsigned char)(index);
         for (i=2; i<8; i++)
         {
                   checksum += cmd3[i];
         }
         cmd3[8] = (unsigned char)~checksum;
}

3)音量调节
为在播放过程中对音量加以动态调节,是使用s6键,由于只有一个键可用,故其调节模式为先由低到高调整,在跌倒到最低音量开始增大调节。
控制音量调节的函数为:
void setVolume(unsigned char index)
{
         unsigned char checksum = 0;
         int i;
         cmd6[6] = (unsigned char)(index);
         for (i=2; i<8; i++)
         {
                   checksum += cmd6[i];
         }
         cmd6[8] = (unsigned char)~checksum;
}

MP3播放模块的指令测试如图9所示,说明它已能进行播放控制。
图9 指令发送测试
结束语:
尽管N32G430的长项不在于音乐播放,但这不妨碍我们以技术手段来达到我们的目标。
在N32G430开发板上实现语音的播放还是十分具有特色和实用价值的。当然,它也适用于其它进行语音提示等人机交互场合。
视频演示:

使用特权

评论回复
沙发
albertaabbot| | 2022-8-16 22:19 | 只看该作者
支持模块效果吗   

使用特权

评论回复
板凳
jinglixixi|  楼主 | 2022-8-17 08:46 | 只看该作者

使用特权

评论回复
地板
pixhw| | 2022-8-18 18:11 | 只看该作者
这个看着非常棒呢   

使用特权

评论回复
5
jinglixixi|  楼主 | 2022-8-19 08:40 | 只看该作者
pixhw 发表于 2022-8-18 18:11
这个看着非常棒呢

使用特权

评论回复
6
phoenixwhite| | 2022-8-20 12:58 | 只看该作者
这个看着不错。      

使用特权

评论回复
7
adolphcocker| | 2022-8-20 14:08 | 只看该作者
使用gui了吗?   

使用特权

评论回复
8
jinglixixi|  楼主 | 2022-8-20 14:10 | 只看该作者

哦,没有。

使用特权

评论回复
9
10299823| | 2022-8-20 14:42 | 只看该作者
音频模块用的是什么   

使用特权

评论回复
10
chenci2013| | 2022-11-3 21:23 | 只看该作者
中文是自己添加的字库吗?              

使用特权

评论回复
11
abotomson| | 2022-11-3 21:37 | 只看该作者
能不能直接通过N32G430控制音频模块输出?

使用特权

评论回复
12
jinglixixi|  楼主 | 2022-11-3 21:38 | 只看该作者
abotomson 发表于 2022-11-3 21:37
能不能直接通过N32G430控制音频模块输出?

很费事!

使用特权

评论回复
13
jinglixixi|  楼主 | 2022-11-3 21:38 | 只看该作者
chenci2013 发表于 2022-11-3 21:23
中文是自己添加的字库吗?

需要自行添加字库,否则太大。

使用特权

评论回复
14
jinglixixi|  楼主 | 2022-11-3 21:39 | 只看该作者
10299823 发表于 2022-8-20 14:42
音频模块用的是什么

MP3播放模块

使用特权

评论回复
15
louliana| | 2022-11-3 21:57 | 只看该作者
如何解析mp3的并输出到音频模块上?

使用特权

评论回复
16
jinglixixi|  楼主 | 2022-11-3 21:59 | 只看该作者
louliana 发表于 2022-11-3 21:57
如何解析mp3的并输出到音频模块上?

模块内部都解决了,你只需按它的指令来控制。

使用特权

评论回复
17
alvpeg| | 2022-11-5 09:49 | 只看该作者
这个高端了,设计的非常好,N32G430资源都用上了。

使用特权

评论回复
18
jinglixixi|  楼主 | 2022-11-5 10:18 | 只看该作者
alvpeg 发表于 2022-11-5 09:49
这个高端了,设计的非常好,N32G430资源都用上了。

感谢支持!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

451

主题

2747

帖子

38

粉丝