Funpack第11期 项目:使用NXP官方开发板LPC55S69EVK,从SD卡中获取预存的图像数据,并显示在LCD屏幕上
参加FunPack 第11期活动,选择任务二,项目相关的视频,如:使用的开发环境,硬件平台,软件平台
标签
嵌入式系统
显示
强者的心
更新2021-11-02
1106

Funpack是硬禾学堂联合Digi-Key发起,为期一年的“玩成功就能得奖”活动。在第十一期的时候使用的是NXP官方出的LPC55S69EVK。这次和往期一样还是有四个任务,挑选其中一个完成就行了。

下面就是本次的四个任务

任务一:
读取SD卡(SD卡自备)中的音频文件,使用板卡上的3.5mm音频接口播放音乐。

任务二:
读取SD卡中预先存入的图像,显示在屏幕上(OLED或LCD)

任务三:
实现USB-UART Hub,自己设计通信方式,实现USB到多路UART的收发。

任务四:
移植Micropython,并实现串口通信和控制IO口。

我选择的是任务二,通过使用本次的LPC55S69从SD卡中读取图片数据然后显示在LCD屏幕上。下面我将具体的说明一下我是如何完成的。

首先在硬件方面:我使用的本次活动板卡LPC5569EVK,一张16GB储存大小的SD卡,一块3.5寸的Arduino接口的TFT彩屏。

在软件方面是使用的MDK进行开发的,通过在官网下载LPC55S69的SDK包,通过MCUXpresso Config Tools生成MDK的工程,在屏幕方面,我选用的这款屏是并口屏,有八个数据管脚,是通过软件模拟并口时序驱动这块屏幕的

下面的图片是一些关于LCD驱动的相关底层函数,开始的这两张是往LCD里面写指令和数据,具体的操作是:首先将LCD的片选将拉低,将DC管脚拉低或者拉高(管脚拉高时代表写数据,管脚拉低时代表写指令)将拉低,将读数据引脚拉高,然后写入八位的数据或者指令。

/*
*函数名:static void LCD_WR_REG(uint8_t Reg)
*入参:
 Reg:LCD寄存器地址
*返回值:无
*作用域:本地
*函数作用:向LCD发送指令
*/
 static void LCD_WR_REG(uint8_t Reg)
 {
	 LCD_CS_CLR();
	 LCD_RS_CLR();
	 LCD_RD_SET();
	 LCD_Write_8Bit(Reg);
	 LCD_CS_SET();
 }
 
/*
*函数名:static void LCD_WR_DATA(uint8_t Data)
*入参:
 Data:往LCD寄存器里写入的数据
*返回值:无
*作用域:本地
*函数作用:向LCD的写入一字节数据
*/
 static void LCD_WR_DATA(uint8_t Data)
 {
	 LCD_CS_CLR();
	 LCD_RS_SET();
	 LCD_RD_SET();
	 LCD_Write_8Bit(Data);
	 LCD_CS_SET();
 }

 

下面这张是对LCD进行初始化,这块屏幕的主控IC使用的是ILI9481,初始化的真正目的是往主控IC的寄存器里里写入数据配置LCD的一些参数如:屏幕的显示的长和宽,显示的方向是那种(可以配置为横屏还是竖屏)等等,

/*
*函数名:void LCD_Init(void)
*入参:
无
*返回值:无
*作用域:整工程
*函数作用:初始化LCD
*/
void LCD_Init(void)
{
	LCD_Reset();

	LCD_WR_REG(0x11);
	Delay_ms(150);
	LCD_WR_REG(0xD0);
	LCD_WR_DATA(0x07);
	LCD_WR_DATA(0x42);
	LCD_WR_DATA(0x18);
	
	LCD_WR_REG(0xD1);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x07);
	LCD_WR_DATA(0x10);
	
	LCD_WR_REG(0xD2);
	LCD_WR_DATA(0x01);
	LCD_WR_DATA(0x02);
	
	LCD_WR_REG(0xC0);
	LCD_WR_DATA(0x10);
	LCD_WR_DATA(0x3B);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x02);
	LCD_WR_DATA(0x11);
	
	LCD_WR_REG(0xC5);
	LCD_WR_DATA(0x03);
	
	LCD_WR_REG(0xC8);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x32);
	LCD_WR_DATA(0x36);
	LCD_WR_DATA(0x45);
	LCD_WR_DATA(0x06);
	LCD_WR_DATA(0x16);
	LCD_WR_DATA(0x37);
	LCD_WR_DATA(0x75);
	LCD_WR_DATA(0x77);
	LCD_WR_DATA(0x54);
	LCD_WR_DATA(0x0C);
	LCD_WR_DATA(0x00);
	
	LCD_WR_REG(0x36);
	LCD_WR_DATA(0x4A);
	
	LCD_WR_REG(0x3A);
	LCD_WR_DATA(0x55);
	
	LCD_WR_REG(0x2A);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x01);
	LCD_WR_DATA(0x3F);
	
	LCD_WR_REG(0x2B);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x01);
	LCD_WR_DATA(0xE0);
	Delay_ms(120);
	LCD_WR_REG(0x29);
	LCD_WR_DATA(0x2c);
	 
	LCD_SetParam();
	
}

在LCD驱动中我们最终使用的函数是下面这一张图片里面的函数,这个函数首先是设置里屏幕将要显示的窗口大小,然后将函数入口参数为首地址的数据发送给LCD让屏幕在刚才设置好的窗口上显示我们发送的数据。

void LCD_Drawbmp16_1( unsigned char *p) 										//显示图片
{
  	unsigned int i; 
	unsigned char picH,picL; 
	LCD_SetWindows(40,40,40+240-1,40+320-1);									//窗口设置
    for(i=0;i<240*320;i++)
	{	
	 	picL=*(p+i*2);															//数据低位在前
		picH=*(p+i*2+1);				
		LCD_WR_DATA_16Bit(picH<<8|picL);  						
	}	
	//LCD_SetWindows(0,0,Width-1,Height-1);										//恢复显示窗口为全屏	

}

在SD卡方面我使用是通过SDIO来驱动SD卡,然后通过FATFS来挂载SD卡,然后让其通过程序里的指定路径和文件名,区读取我们在SD卡存储的数据。下面的图片上是是MAIN函数和显示图片的函数,下面我仔细讲解一下它们,在MAIN函数里首先是初始化板卡相关的东西和初始化板子上使用到的管脚,接着初始化时钟设置芯片的主频为150M,然后初始化滴答定时器,后面要通过使用滴答定时器来进行延时。接着就是初始化LCD屏幕,然后将屏幕清屏成白色。通过f_mount这个函数将SD卡挂在到FATFS上,通过获取返回的参数来判断是否挂在成功,并打印一些信息。在ShowImage这个函数里通过f_open来打开在程序里指定的路径和文件,通过f_read来获取一张将要显示的图片数据,将读取出来的数据存放到SRAM里面开辟了一个大数组里,通过f_close这个函数将上面刚读取的数据文件关闭,防止误操作到相关文件。通过这两个LCD_Drawbmp16_1(image_buff);SysTick_DelayTicks(500);函数将读取数据在屏幕上显示和延迟500MS,这个Show_Image函数里面一共读取了五张图片数据并显示在LCD屏幕上,将这个函数放在While死循环中调用。

 

 

/*!
 * @brief Main function
 */
int main(void)
{
    FRESULT error;
    DIR directory; /* Directory object */
    FILINFO fileInformation;
    UINT bytesWritten;
    UINT bytesRead;
    const TCHAR driverNumberBuffer[3U] = {SDDISK + '0', ':', '/'};
    volatile bool failedFlag           = false;
    char ch                            = '0';
    BYTE work[FF_MAX_SS];

    /* set BOD VBAT level to 1.65V */
    POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false);
    CLOCK_EnableClock(kCLOCK_InputMux);
    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
    CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

    BOARD_InitPins();
    BOARD_BootClockPLL150M();
    BOARD_InitDebugConsole();
	if (SysTick_Config(SystemCoreClock / 1000U))
    {
        while (1)
        {
        }
    }
    LCD_Init();
	LCD_Clear(WHITE);
 

    

    if (sdcardWaitCardInsert() != kStatus_Success)
    {
        return -1;
    }

    if (f_mount(&g_fileSystem, driverNumberBuffer, 0U))
    {
        PRINTF("Mount volume failed.\r\n");
        return -1;
    }

#if (FF_FS_RPATH >= 2U)
    error = f_chdrive((char const *)&driverNumberBuffer[0U]);
    if (error)
    {
        PRINTF("Change drive failed.\r\n");
        return -1;
    }
#endif


    while (true)
    {
      Show_Image();
    }
}
int Show_Image(void)
{
	uint8_t error;
	UINT bytesRead;
	volatile bool failedFlag           = false;
	 error = f_open(&g_fileObject, _T("/1.bin"), (FA_READ | FA_OPEN_ALWAYS));
    if (error)
    {
        if (error == FR_EXIST)
        {
            PRINTF("File exists.\r\n");
        }
        else
        {
            PRINTF("Open file failed.\r\n");
            return -1;
        }
    }

    PRINTF("\r\nWrite/read file until encounters error......\r\n");
//    while (true)
    {

        PRINTF("Read from above created file.\r\n");
        error = f_read(&g_fileObject, image_buff, sizeof(image_buff), &bytesRead);
        if ((error) || (bytesRead != sizeof(image_buff)))
        {
            PRINTF("Read file failed. \r\n");
            failedFlag = true;
        }
    }
    PRINTF("\r\nThe example will not read/write file again.\r\n");
    

    if (f_close(&g_fileObject))
    {
        PRINTF("\r\nClose file failed.\r\n");
        return -1;
    }
    LCD_Drawbmp16_1(image_buff);
	SysTick_DelayTicks(500);	
	
	error = f_open(&g_fileObject, _T("/2.bin"), (FA_READ | FA_OPEN_ALWAYS));
    if (error)
    {
        if (error == FR_EXIST)
        {
            PRINTF("File exists.\r\n");
        }
        else
        {
            PRINTF("Open file failed.\r\n");
            return -1;
        }
    }

    PRINTF("\r\nWrite/read file until encounters error......\r\n");
//    while (true)
    {

        PRINTF("Read from above created file.\r\n");
        error = f_read(&g_fileObject, image_buff, sizeof(image_buff), &bytesRead);
        if ((error) || (bytesRead != sizeof(image_buff)))
        {
            PRINTF("Read file failed. \r\n");
            failedFlag = true;
        }
    }
    PRINTF("\r\nThe example will not read/write file again.\r\n");
    

    if (f_close(&g_fileObject))
    {
        PRINTF("\r\nClose file failed.\r\n");
        return -1;
    }
    LCD_Drawbmp16_1(image_buff);
	SysTick_DelayTicks(500);
	
	error = f_open(&g_fileObject, _T("/3.bin"), (FA_READ | FA_OPEN_ALWAYS));
    if (error)
    {
        if (error == FR_EXIST)
        {
            PRINTF("File exists.\r\n");
        }
        else
        {
            PRINTF("Open file failed.\r\n");
            return -1;
        }
    }

    PRINTF("\r\nWrite/read file until encounters error......\r\n");
//    while (true)
    {

        PRINTF("Read from above created file.\r\n");
        error = f_read(&g_fileObject, image_buff, sizeof(image_buff), &bytesRead);
        if ((error) || (bytesRead != sizeof(image_buff)))
        {
            PRINTF("Read file failed. \r\n");
            failedFlag = true;
        }
    }
    PRINTF("\r\nThe example will not read/write file again.\r\n");
    

    if (f_close(&g_fileObject))
    {
        PRINTF("\r\nClose file failed.\r\n");
        return -1;
    }
    LCD_Drawbmp16_1(image_buff);
	SysTick_DelayTicks(500);
	
	error = f_open(&g_fileObject, _T("/4.bin"), (FA_READ | FA_OPEN_ALWAYS));
    if (error)
    {
        if (error == FR_EXIST)
        {
            PRINTF("File exists.\r\n");
        }
        else
        {
            PRINTF("Open file failed.\r\n");
            return -1;
        }
    }

    PRINTF("\r\nWrite/read file until encounters error......\r\n");
//    while (true)
    {

        PRINTF("Read from above created file.\r\n");
        error = f_read(&g_fileObject, image_buff, sizeof(image_buff), &bytesRead);
        if ((error) || (bytesRead != sizeof(image_buff)))
        {
            PRINTF("Read file failed. \r\n");
            failedFlag = true;
        }
    }
    PRINTF("\r\nThe example will not read/write file again.\r\n");
    

    if (f_close(&g_fileObject))
    {
        PRINTF("\r\nClose file failed.\r\n");
        return -1;
    }
    LCD_Drawbmp16_1(image_buff);
	SysTick_DelayTicks(500);
	
	error = f_open(&g_fileObject, _T("/5.bin"), (FA_READ | FA_OPEN_ALWAYS));
    if (error)
    {
        if (error == FR_EXIST)
        {
            PRINTF("File exists.\r\n");
        }
        else
        {
            PRINTF("Open file failed.\r\n");
            return -1;
        }
    }

    PRINTF("\r\nWrite/read file until encounters error......\r\n");
//    while (true)
    {

        PRINTF("Read from above created file.\r\n");
        error = f_read(&g_fileObject, image_buff, sizeof(image_buff), &bytesRead);
        if ((error) || (bytesRead != sizeof(image_buff)))
        {
            PRINTF("Read file failed. \r\n");
            failedFlag = true;
        }
    }
    PRINTF("\r\nThe example will not read/write file again.\r\n");
    

    if (f_close(&g_fileObject))
    {
        PRINTF("\r\nClose file failed.\r\n");
        return -1;
    }
    LCD_Drawbmp16_1(image_buff);
	SysTick_DelayTicks(500);
}

下面就是实际板卡的功能演示图片

Fveu37HcwhlFd_45yPLG0UJ_20_GFsUmyLsfJtshyS-o8vpK5Pt63W9uFoo6bT49ApXZvq_voUe6zgAVkQ5CFs0pfUpe6ndEzDd3lLzu3bXOY-bTFmILq9hlGN_C1hb10joytDvhltDs

对本活动的心得体会:从FunPack 第11期中,我学会了对于LPC55S69这款芯片的常见外设的使用,和通过MCUXpresso Config Tools这个开发工具配置外设进行快速将板卡开发起来。

也了解和掌握了LPC55S69这款芯片的性能。同时也希望硬禾学堂在未来有更多这样的活动,让我们学生能学到更多的技术和支持,同时祝硬禾学堂在未来越来越好。

 

附件下载
2.tf_lcd.zip
任务2的MDK工程源码
团队介绍
一名在校大学生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号