[开发工具] 【新定义MCU开发板测评】 + MDM_2802屏中文菜单的MP3播放器

[复制链接]
 楼主| jinglixixi 发表于 2022-11-17 14:29 | 显示全部楼层 |阅读模式
#申请原创#
该播放器是由MDM_2802屏、MP3模块、触摸按键、喇叭及开发板所构成,见图1所示。
通过触摸按键可循环以轮回的方式来选择播放歌曲,并通过串口来控制MP3模块来播放指定的歌曲。
1.jpg
图1 硬件构成

1. MDM_2802屏
MDM_2802屏是一款SPI接口的显示屏,其分辨率为320*240像素点,其几何尺寸为2.8寸。相对于一般的显示屏,它更节省引脚,例如它无需DC控制引脚。此外,它在不接背光引脚的情况下也可正常地显示。
为此除电源引脚外,它只需占用4I/O口就能工作,它与开发板的连接关系为:
LCD_CLK --- P43
LCD_SDA--- P45
LCD_REST--- P44
LCD_CS --- P53
2.jpg
图2 MDM_2802屏接口

在MDM_2802显示屏的驱动上是以I/O口来模拟SPI发送字节数据,其函数内容如下:
  1. void send_byte(u8 dat)
  2. {
  3.     u8 i;
  4.     for(i=0;i<8;i++)
  5.     {
  6.         LCD_CLK=0;
  7.         if(dat&0x80)
  8.            LCD_SDA=1;
  9.         else
  10.            LCD_SDA=0;
  11.                 Delay_us(8);
  12.         dat<<=1;
  13.                 LCD_CLK=1;
  14.                 Delay_us(8);
  15.     }
  16. }
复制代码
该显示屏的核心控制芯片为ili9341,其初始化函数为:
  1. void ili9341_init(void)
  2. {
  3.     LCD_REST=0;
  4.         Delay(20);
  5.         LCD_REST=1;
  6.         Delay(20);
  7.     LCD_CS=0;
  8.         write_register(0xCF);  
  9.     write_data(0x00);
  10.     write_data(0xC1);
  11.     write_data(0X30);
  12.     write_register(0xED);  
  13.     write_data(0x64);
  14.     write_data(0x03);
  15.     write_data(0X12);
  16.     write_data(0X81);
  17.     write_register(0xE8);  
  18.     write_data(0x85);
  19.     write_data(0x10);
  20.     write_data(0x7A);
  21.     write_register(0xCB);  
  22.     write_data(0x39);
  23.     write_data(0x2C);
  24.     write_data(0x00);
  25.     write_data(0x34);
  26.     write_data(0x02);
  27.     write_register(0xF7);  
  28.     write_data(0x20);
  29.     write_register(0xEA);  
  30.     write_data(0x00);
  31.     write_data(0x00);
  32.     write_register(0xC0);
  33.     write_data(0x1B);
  34.     write_register(0xC1);
  35.     write_data(0x01);
  36.     write_register(0xC5);
  37.     write_data(0x30);
  38.     write_data(0x30);
  39.     write_register(0xC7);
  40.     write_data(0XB7);
  41.         write_register(0x36);
  42.     write_data(0x08);
  43.         write_register(0x3A);
  44.     write_data(0x55);
  45.         write_register(0xB1);
  46.     write_data(0x00);
  47.     write_data(0x1A);
  48.         write_register(0xB6);
  49.     write_data(0x0A);
  50.     write_data(0xA2);
  51.         write_register(0xF2);
  52.     write_data(0x00);
  53.     write_register(0x26);
  54.     write_data(0x01);
  55.         write_register(0xE0);
  56.     write_data(0x0F);
  57.     write_data(0x2A);
  58.     write_data(0x28);
  59.     write_data(0x08);
  60.     write_data(0x0E);
  61.     write_data(0x08);
  62.     write_data(0x54);
  63.     write_data(0XA9);
  64.     write_data(0x43);
  65.     write_data(0x0A);
  66.     write_data(0x0F);
  67.     write_data(0x00);
  68.     write_data(0x00);
  69.     write_data(0x00);
  70.     write_data(0x00);
  71.         write_register(0XE1);
  72.     write_data(0x00);
  73.     write_data(0x15);
  74.     write_data(0x17);
  75.     write_data(0x07);
  76.     write_data(0x11);
  77.     write_data(0x06);
  78.     write_data(0x2B);
  79.     write_data(0x56);
  80.     write_data(0x3C);
  81.     write_data(0x05);
  82.     write_data(0x10);
  83.     write_data(0x0F);
  84.     write_data(0x3F);
  85.     write_data(0x3F);
  86.     write_data(0x0F);
  87.     write_register(0x2B);
  88.     write_data(0x00);
  89.     write_data(0x00);
  90.     write_data(0x01);
  91.     write_data(0x3f);
  92.     write_register(0x2A);
  93.     write_data(0x00);
  94.     write_data(0x00);
  95.     write_data(0x00);
  96.     write_data(0xef);         
  97.     write_register(0x11);
  98.     lcdc_delay(1000);
  99.     write_register(0x29);  
  100.     ili9341_clear(BLACK);
  101. }
复制代码
该显示屏的色彩清屏函数为:
  1. void ili9341_clear(int c)
  2. {
  3.       unsigned int i,j;
  4.           set_cursor(0x00, 0x0000);
  5.           gram_prepare();
  6.           for(i = 0; i < 320; i++)
  7.           {
  8.             for(j = 0; j < 240; j++)
  9.             {
  10.                       write_data(c >> 8);
  11.                       write_data(c);
  12.             }
  13.           }
  14. }
复制代码
为了修饰画面,还配置直线绘制函数,其内容为:
  1. void LCD_DrawLine(int fcolor,uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
  2. {
  3.         uint16_t t;
  4.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  5.         int incx,incy,uRow,uCol;
  6.         delta_x=x2-x1;
  7.         delta_y=y2-y1;
  8.         uRow=x1;
  9.         uCol=y1;
  10.         if(delta_x>0)incx=1;
  11.         else if(delta_x==0)incx=0;
  12.         else {incx=-1;delta_x=-delta_x;}
  13.         if(delta_y>0)incy=1;
  14.         else if(delta_y==0)incy=0;   
  15.         else{incy=-1;delta_y=-delta_y;}
  16.         if( delta_x>delta_y)distance=delta_x;
  17.         else distance=delta_y;
  18.         for(t=0;t<=distance+1;t++ )
  19.         {
  20.                 ili9341_draw_pixel(fcolor,uRow, uCol);
  21.                 xerr+=delta_x ;
  22.                 yerr+=delta_y ;
  23.                 if(xerr>distance)
  24.                 {
  25.                         xerr-=distance;
  26.                         uRow+=incx;
  27.                 }
  28.                 if(yerr>distance)
  29.                 {
  30.                         yerr-=distance;
  31.                         uCol+=incy;
  32.                 }
  33.         }
  34. }
复制代码
此外,在字符显示函数的基础上还配置了字符串显示函数,其内容为:
  1. void LCD_ShowString(unsigned int x,unsigned int y,const char *p)
  2. {
  3.     while(*p!='\0')
  4.     {
  5.         if(x>LCD_W-16){x=0;y+=16;}
  6.         if(y>LCD_H-16){y=x=0;}
  7.                         GUI_DispCharv(*p, x,y);
  8.         x=x+8;
  9.         p++;
  10.     }
  11. }
复制代码
为显示中文歌单,在构建中文字库的基础上,所配置的中文显示函数为:
  1. void showhanzi16(unsigned int x,unsigned int y,unsigned char index, int fcolor, int bcolor)        
  2. {  
  3.         unsigned char i,j,k;
  4.     unsigned char *temp=hanzi16;         
  5.         temp+=index*32;        
  6.         for(j=0;j<16;j++)
  7.         {
  8.                 for(k=0;k<2;k++)
  9.                 {
  10.                         for(i=0;i<8;i++)
  11.                         {                     
  12.                                  if((*temp&(1<<i))!=0)
  13.                                 {
  14.                                         ili9341_draw_pixel(fcolor, x+i+k*8, y+j);
  15.                                 }
  16.                                 else
  17.                                 {
  18.                                         ili9341_draw_pixel(bcolor, x+i+k*8, y+j);
  19.                                 }
  20.                         }
  21.                         temp++;
  22.                 }
  23.          }
  24. }
复制代码
在以上函数的配合下,所实现的显示界面如图3所示。
3.jpg
图3 显示界面

2. 按键控制与LED指示

为了能轻松地进行播放内容的选取,这里选择的是独立的触摸按键,其连接的引脚则是触摸功能板上触摸键所用的引脚P35。为了则是触摸键的操作结果,是用开发板上的LED来进行指示,其电路如图4所示。当触摸按键时,LED灯会被点亮;释放后,就会熄灭。
4.jpg
图4 按键与LED电路


3. 串行通讯与MP3控制

MP3播放模块是一款可通过串行通讯进行控制的器件,其通讯波特率为9600 bps。为了控制MP3模块,这里所使用的UART1。

UART1的初始化函数为:
  1. void SC_USCI1_Init(void)
  2. {
  3.         GPIO_Init(GPIO1, GPIO_PIN_1,GPIO_MODE_IN_PU);
  4.         GPIO_Init(GPIO1, GPIO_PIN_3,GPIO_MODE_IN_PU);
  5.         USCI1_ITConfig(DISABLE,LOW);
  6.         USCI1_UART_Init(32000000,9600,USCI1_UART_Mode_10B,USCI1_UART_RX_ENABLE);
  7. }
复制代码
以串口测试指令发送的结果如图5所示。
5.jpg
5 串口测试

实现整个显示与播放控制功能的主程序为:
  1. void main(void)
  2. {
  3.     USCI1_HandleInfoDef USCI1_HandleInfo;
  4.         int i,h;
  5.         Delay(50);
  6.         P0CON = 0xFF;
  7.         P0PH  = 0x00;
  8.         P1CON = 0x00;
  9.         P1PH  = 0x00;
  10.         P2CON = 0xFF;
  11.         P2PH  = 0x00;
  12.         P3CON = 0x00;
  13.         P3PH  = 0xFF;
  14.         P4CON = 0xFF;
  15.         P4PH  = 0x01;
  16.         P5CON = 0xFF;
  17.         P5PH  = 0x00;
  18.         GPIO_Init(GPIO0, GPIO_PIN_1 |GPIO_PIN_6, GPIO_MODE_OUT_PP);
  19.         GPIO_Init(GPIO2, GPIO_PIN_2, GPIO_MODE_OUT_PP);
  20.         GPIO_Init(GPIO5, GPIO_PIN_3, GPIO_MODE_OUT_PP);
  21.     GPIO_Init(GPIO4, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5, GPIO_MODE_OUT_PP);
  22.         GPIO_Init(GPIO1, GPIO_PIN_5, GPIO_MODE_IN_PU);
  23.         Delay(100);
  24.     ili9341_init();
  25.         ili9341_clear(RED);
  26.         LCD_DrawLine(WHITE ,0, 5, 239, 5);
  27.         LCD_DrawLine(WHITE ,0, 55, 239, 55);
  28.         LCD_DrawLine(WHITE,0, 296, 239, 296);
  29.         showimage();
  30.         BACK_COLOR=RED;
  31.         POINT_COLOR=YELLOW;
  32.         LCD_ShowString(60,300,"BY: jinglixixi");
  33.         Delay(1000);
  34.         BACK_COLOR=RED;
  35.         POINT_COLOR=WHITE;
  36.         GUI_DispCharv('M',80,20);
  37.         GUI_DispCharv('P',90,20);
  38.         GUI_DispCharv('3',100,20);
  39.         showhanzi16(115,16,32,YELLOW,RED);
  40.         showhanzi16(135,16,33,YELLOW,RED);
  41.         showhanzi16(155,16,34,YELLOW,RED);
  42.         showhanzi16(175,16,35,YELLOW,RED);
  43.         showhanzi16(195,16,36,YELLOW,RED);
  44.         BACK_COLOR=RED;     
  45.         POINT_COLOR=YELLOW;
  46.         showhanzi16(60,75,0,YELLOW,RED);
  47.         showhanzi16(80,75,1,YELLOW,RED);
  48.         showhanzi16(100,75,2,YELLOW,RED);
  49.         showhanzi16(30,75,37,YELLOW,RED);
  50.         showhanzi16(60,105,3,YELLOW,RED);
  51.         showhanzi16(80,105,4,YELLOW,RED);
  52.         showhanzi16(100,105,5,YELLOW,RED);
  53.         showhanzi16(120,105,6,YELLOW,RED);
  54.         showhanzi16(60,135,7,YELLOW,RED);
  55.         showhanzi16(80,135,8,YELLOW,RED);
  56.         showhanzi16(60,165,9,YELLOW,RED);
  57.         showhanzi16(80,165,10,YELLOW,RED);
  58.         showhanzi16(60,195,11,YELLOW,RED);
  59.         showhanzi16(80,195,12,YELLOW,RED);
  60.         showhanzi16(100,195,13,YELLOW,RED);
  61.         showhanzi16(120,195,14,YELLOW,RED);
  62.         showhanzi16(60,225,15,YELLOW,RED);
  63.         showhanzi16(80,225,16,YELLOW,RED);
  64.         showhanzi16(100,225,17,YELLOW,RED);
  65.         showhanzi16(120,225,18,YELLOW,RED);
  66.         showhanzi16(140,225,19,YELLOW,RED);
  67.         showhanzi16(60,255,20,YELLOW,RED);
  68.         showhanzi16(80,255,21,YELLOW,RED);
  69.         showhanzi16(100,255,22,YELLOW,RED);
  70.         showhanzi16(120,255,23,YELLOW,RED);
  71.         showhanzi16(140,255,24,YELLOW,RED);
  72.         showhanzi16(160,255,25,YELLOW,RED);
  73.         showhanzi16(180,255,26,YELLOW,RED);
  74.     h=75;
  75.         i=0;
  76.         SC_USCI1_Init();
  77.         setVolume(10);
  78.     USCI1_HandleInfo.TxState = USCI1_STATE_READY;
  79.         USCI1_UART_Transmit(&USCI1_HandleInfo, cmd6, 10, 0xFFFF);
  80.     while(1)
  81.         {
  82.                   if(KEY==1)
  83.                   {
  84.                                 LED=1;
  85.                                 if(i<6)
  86.                                 {
  87.                                          i++;
  88.                                          showhanzi16(30,h,37,RED,RED);
  89.                                      h=h+30;
  90.                                      showhanzi16(30,h,37,YELLOW,RED);
  91.                                          playn(i);
  92.                      USCI1_HandleInfo.TxState = USCI1_STATE_READY;
  93.                                          USCI1_UART_Transmit(&USCI1_HandleInfo, cmd3, 10, 0xFFFF);
  94.                                 }
  95.                                 else
  96.                                 {
  97.                                        showhanzi16(30,h,37,RED,RED);
  98.                                      h=75;
  99.                          i=0;
  100.                                      showhanzi16(30,h,37,YELLOW,RED);
  101.                                      playn(i);
  102.                      USCI1_HandleInfo.TxState = USCI1_STATE_READY;
  103.                                          USCI1_UART_Transmit(&USCI1_HandleInfo, cmd3, 10, 0xFFFF);
  104.                                 }
  105.                         }
  106.             else
  107.                         {
  108.                                     LED=0;
  109.                         }
  110.             Delay(200);
  111.         }
  112. }
复制代码
后续将尝试以触摸板来控制MP3的播放操作,那样将会更加方便和具有特色!


演示视频:https://www.bilibili.com/video/BV1RW4y1s7d8/?vd_source=f302fc0cc3a0425328db53a3b92082ca


youtome 发表于 2023-2-7 20:11 | 显示全部楼层
这个用51单片机都可以操作的吗              
 楼主| jinglixixi 发表于 2023-2-7 20:25 | 显示全部楼层
youtome 发表于 2023-2-7 20:11
这个用51单片机都可以操作的吗

应该问题不大,主要是存储空间要大些来存放汉字字库,其它不受影响。
jtracy3 发表于 2023-2-7 21:04 | 显示全部楼层
MDM_2802刷屏速度怎么样              
 楼主| jinglixixi 发表于 2023-2-7 21:08 | 显示全部楼层
jtracy3 发表于 2023-2-7 21:04
MDM_2802刷屏速度怎么样

一般,不是很快。
febgxu 发表于 2023-2-7 21:53 | 显示全部楼层
这个操作屏幕会不会很慢呢              
 楼主| jinglixixi 发表于 2023-2-8 08:27 | 显示全部楼层
febgxu 发表于 2023-2-7 21:53
这个操作屏幕会不会很慢呢

显示和刷新菜单很快,显示满屏的图片慢些。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

518

主题

2935

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部