打印
[开发工具]

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

[复制链接]
1354|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创#
该播放器是由MDM_2802屏、MP3模块、触摸按键、喇叭及开发板所构成,见图1所示。
通过触摸按键可循环以轮回的方式来选择播放歌曲,并通过串口来控制MP3模块来播放指定的歌曲。

图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 MDM_2802屏接口

在MDM_2802显示屏的驱动上是以I/O口来模拟SPI发送字节数据,其函数内容如下:
void send_byte(u8 dat)
{
    u8 i;
    for(i=0;i<8;i++)
    {
        LCD_CLK=0;
        if(dat&0x80)
           LCD_SDA=1;
        else
           LCD_SDA=0;
                Delay_us(8);
        dat<<=1;
                LCD_CLK=1;
                Delay_us(8);
    }
}
该显示屏的核心控制芯片为ili9341,其初始化函数为:
void ili9341_init(void)
{
    LCD_REST=0;
        Delay(20);
        LCD_REST=1;
        Delay(20);
    LCD_CS=0;
        write_register(0xCF);  
    write_data(0x00);
    write_data(0xC1);
    write_data(0X30);
    write_register(0xED);  
    write_data(0x64);
    write_data(0x03);
    write_data(0X12);
    write_data(0X81);
    write_register(0xE8);  
    write_data(0x85);
    write_data(0x10);
    write_data(0x7A);
    write_register(0xCB);  
    write_data(0x39);
    write_data(0x2C);
    write_data(0x00);
    write_data(0x34);
    write_data(0x02);
    write_register(0xF7);  
    write_data(0x20);
    write_register(0xEA);  
    write_data(0x00);
    write_data(0x00);
    write_register(0xC0);
    write_data(0x1B);
    write_register(0xC1);
    write_data(0x01);
    write_register(0xC5);
    write_data(0x30);
    write_data(0x30);
    write_register(0xC7);
    write_data(0XB7);
        write_register(0x36);
    write_data(0x08);
        write_register(0x3A);
    write_data(0x55);
        write_register(0xB1);
    write_data(0x00);
    write_data(0x1A);
        write_register(0xB6);
    write_data(0x0A);
    write_data(0xA2);
        write_register(0xF2);
    write_data(0x00);
    write_register(0x26);
    write_data(0x01);
        write_register(0xE0);
    write_data(0x0F);
    write_data(0x2A);
    write_data(0x28);
    write_data(0x08);
    write_data(0x0E);
    write_data(0x08);
    write_data(0x54);
    write_data(0XA9);
    write_data(0x43);
    write_data(0x0A);
    write_data(0x0F);
    write_data(0x00);
    write_data(0x00);
    write_data(0x00);
    write_data(0x00);
        write_register(0XE1);
    write_data(0x00);
    write_data(0x15);
    write_data(0x17);
    write_data(0x07);
    write_data(0x11);
    write_data(0x06);
    write_data(0x2B);
    write_data(0x56);
    write_data(0x3C);
    write_data(0x05);
    write_data(0x10);
    write_data(0x0F);
    write_data(0x3F);
    write_data(0x3F);
    write_data(0x0F);
    write_register(0x2B);
    write_data(0x00);
    write_data(0x00);
    write_data(0x01);
    write_data(0x3f);
    write_register(0x2A);
    write_data(0x00);
    write_data(0x00);
    write_data(0x00);
    write_data(0xef);         
    write_register(0x11);
    lcdc_delay(1000);
    write_register(0x29);  
    ili9341_clear(BLACK);
}
该显示屏的色彩清屏函数为:
void ili9341_clear(int c)
{
      unsigned int i,j;
          set_cursor(0x00, 0x0000);
          gram_prepare();
          for(i = 0; i < 320; i++)
          {
            for(j = 0; j < 240; j++)
            {
                      write_data(c >> 8);
                      write_data(c);
            }
          }
}
为了修饰画面,还配置直线绘制函数,其内容为:
void LCD_DrawLine(int fcolor,uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
        uint16_t t;
        int xerr=0,yerr=0,delta_x,delta_y,distance;
        int incx,incy,uRow,uCol;
        delta_x=x2-x1;
        delta_y=y2-y1;
        uRow=x1;
        uCol=y1;
        if(delta_x>0)incx=1;
        else if(delta_x==0)incx=0;
        else {incx=-1;delta_x=-delta_x;}
        if(delta_y>0)incy=1;
        else if(delta_y==0)incy=0;   
        else{incy=-1;delta_y=-delta_y;}
        if( delta_x>delta_y)distance=delta_x;
        else distance=delta_y;
        for(t=0;t<=distance+1;t++ )
        {
                ili9341_draw_pixel(fcolor,uRow, uCol);
                xerr+=delta_x ;
                yerr+=delta_y ;
                if(xerr>distance)
                {
                        xerr-=distance;
                        uRow+=incx;
                }
                if(yerr>distance)
                {
                        yerr-=distance;
                        uCol+=incy;
                }
        }
}
此外,在字符显示函数的基础上还配置了字符串显示函数,其内容为:
void LCD_ShowString(unsigned int x,unsigned int y,const char *p)
{
    while(*p!='\0')
    {
        if(x>LCD_W-16){x=0;y+=16;}
        if(y>LCD_H-16){y=x=0;}
                        GUI_DispCharv(*p, x,y);
        x=x+8;
        p++;
    }
}
为显示中文歌单,在构建中文字库的基础上,所配置的中文显示函数为:
void showhanzi16(unsigned int x,unsigned int y,unsigned char index, int fcolor, int bcolor)        
{  
        unsigned char i,j,k;
    unsigned char *temp=hanzi16;         
        temp+=index*32;        
        for(j=0;j<16;j++)
        {
                for(k=0;k<2;k++)
                {
                        for(i=0;i<8;i++)
                        {                     
                                 if((*temp&(1<<i))!=0)
                                {
                                        ili9341_draw_pixel(fcolor, x+i+k*8, y+j);
                                }
                                else
                                {
                                        ili9341_draw_pixel(bcolor, x+i+k*8, y+j);
                                }
                        }
                        temp++;
                }
         }
}
在以上函数的配合下,所实现的显示界面如图3所示。

图3 显示界面

2. 按键控制与LED指示

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


3. 串行通讯与MP3控制

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

UART1的初始化函数为:
void SC_USCI1_Init(void)
{
        GPIO_Init(GPIO1, GPIO_PIN_1,GPIO_MODE_IN_PU);
        GPIO_Init(GPIO1, GPIO_PIN_3,GPIO_MODE_IN_PU);
        USCI1_ITConfig(DISABLE,LOW);
        USCI1_UART_Init(32000000,9600,USCI1_UART_Mode_10B,USCI1_UART_RX_ENABLE);
}
以串口测试指令发送的结果如图5所示。
5 串口测试

实现整个显示与播放控制功能的主程序为:
void main(void)
{
    USCI1_HandleInfoDef USCI1_HandleInfo;
        int i,h;
        Delay(50);
        P0CON = 0xFF;
        P0PH  = 0x00;
        P1CON = 0x00;
        P1PH  = 0x00;
        P2CON = 0xFF;
        P2PH  = 0x00;
        P3CON = 0x00;
        P3PH  = 0xFF;
        P4CON = 0xFF;
        P4PH  = 0x01;
        P5CON = 0xFF;
        P5PH  = 0x00;
        GPIO_Init(GPIO0, GPIO_PIN_1 |GPIO_PIN_6, GPIO_MODE_OUT_PP);
        GPIO_Init(GPIO2, GPIO_PIN_2, GPIO_MODE_OUT_PP);
        GPIO_Init(GPIO5, GPIO_PIN_3, GPIO_MODE_OUT_PP);
    GPIO_Init(GPIO4, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5, GPIO_MODE_OUT_PP);
        GPIO_Init(GPIO1, GPIO_PIN_5, GPIO_MODE_IN_PU);
        Delay(100);
    ili9341_init();
        ili9341_clear(RED);
        LCD_DrawLine(WHITE ,0, 5, 239, 5);
        LCD_DrawLine(WHITE ,0, 55, 239, 55);
        LCD_DrawLine(WHITE,0, 296, 239, 296);
        showimage();
        BACK_COLOR=RED;
        POINT_COLOR=YELLOW;
        LCD_ShowString(60,300,"BY: jinglixixi");
        Delay(1000);
        BACK_COLOR=RED;
        POINT_COLOR=WHITE;
        GUI_DispCharv('M',80,20);
        GUI_DispCharv('P',90,20);
        GUI_DispCharv('3',100,20);
        showhanzi16(115,16,32,YELLOW,RED);
        showhanzi16(135,16,33,YELLOW,RED);
        showhanzi16(155,16,34,YELLOW,RED);
        showhanzi16(175,16,35,YELLOW,RED);
        showhanzi16(195,16,36,YELLOW,RED);
        BACK_COLOR=RED;     
        POINT_COLOR=YELLOW;
        showhanzi16(60,75,0,YELLOW,RED);
        showhanzi16(80,75,1,YELLOW,RED);
        showhanzi16(100,75,2,YELLOW,RED);
        showhanzi16(30,75,37,YELLOW,RED);
        showhanzi16(60,105,3,YELLOW,RED);
        showhanzi16(80,105,4,YELLOW,RED);
        showhanzi16(100,105,5,YELLOW,RED);
        showhanzi16(120,105,6,YELLOW,RED);
        showhanzi16(60,135,7,YELLOW,RED);
        showhanzi16(80,135,8,YELLOW,RED);
        showhanzi16(60,165,9,YELLOW,RED);
        showhanzi16(80,165,10,YELLOW,RED);
        showhanzi16(60,195,11,YELLOW,RED);
        showhanzi16(80,195,12,YELLOW,RED);
        showhanzi16(100,195,13,YELLOW,RED);
        showhanzi16(120,195,14,YELLOW,RED);
        showhanzi16(60,225,15,YELLOW,RED);
        showhanzi16(80,225,16,YELLOW,RED);
        showhanzi16(100,225,17,YELLOW,RED);
        showhanzi16(120,225,18,YELLOW,RED);
        showhanzi16(140,225,19,YELLOW,RED);
        showhanzi16(60,255,20,YELLOW,RED);
        showhanzi16(80,255,21,YELLOW,RED);
        showhanzi16(100,255,22,YELLOW,RED);
        showhanzi16(120,255,23,YELLOW,RED);
        showhanzi16(140,255,24,YELLOW,RED);
        showhanzi16(160,255,25,YELLOW,RED);
        showhanzi16(180,255,26,YELLOW,RED);
    h=75;
        i=0;
        SC_USCI1_Init();
        setVolume(10);
    USCI1_HandleInfo.TxState = USCI1_STATE_READY;
        USCI1_UART_Transmit(&USCI1_HandleInfo, cmd6, 10, 0xFFFF);
    while(1)
        {
                  if(KEY==1)
                  {
                                LED=1;
                                if(i<6)
                                {
                                         i++;
                                         showhanzi16(30,h,37,RED,RED);
                                     h=h+30;
                                     showhanzi16(30,h,37,YELLOW,RED);
                                         playn(i);
                     USCI1_HandleInfo.TxState = USCI1_STATE_READY;
                                         USCI1_UART_Transmit(&USCI1_HandleInfo, cmd3, 10, 0xFFFF);
                                }
                                else
                                {
                                       showhanzi16(30,h,37,RED,RED);
                                     h=75;
                         i=0;
                                     showhanzi16(30,h,37,YELLOW,RED);
                                     playn(i);
                     USCI1_HandleInfo.TxState = USCI1_STATE_READY;
                                         USCI1_UART_Transmit(&USCI1_HandleInfo, cmd3, 10, 0xFFFF);
                                }
                        }
            else
                        {
                                    LED=0;
                        }
            Delay(200);
        }
}
后续将尝试以触摸板来控制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刷屏速度怎么样              

使用特权

评论回复
5
jinglixixi|  楼主 | 2023-2-7 21:08 | 只看该作者
jtracy3 发表于 2023-2-7 21:04
MDM_2802刷屏速度怎么样

一般,不是很快。

使用特权

评论回复
6
febgxu| | 2023-2-7 21:53 | 只看该作者
这个操作屏幕会不会很慢呢              

使用特权

评论回复
7
jinglixixi|  楼主 | 2023-2-8 08:27 | 只看该作者
febgxu 发表于 2023-2-7 21:53
这个操作屏幕会不会很慢呢

显示和刷新菜单很快,显示满屏的图片慢些。

使用特权

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

本版积分规则

451

主题

2747

帖子

38

粉丝