【嵌入式】MCU(HC32F460)+并口LCD液晶屏ILI9341 移植emWin记录

本文主要是介绍【嵌入式】MCU(HC32F460)+并口LCD液晶屏ILI9341 移植emWin记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一 并口屏接线

        之前整了一块串口屏,实际使用中,感觉整屏(320*240)的刷新速度还是有点偏慢,肉眼能够看到明显的刷屏动作,故而考虑改用并口屏来实现显示功能。

        首先根据显示屏的接线图进行接线:

 

        其中,真正需要关注的是CS、RS、WR、RD、RESET以及DB0-15数据线。 

 

二 并口屏驱动初始化

        接线完成之后,就需要在程序中对这几个接口进行初始化。

        这边区别于SPI的串口屏,只要把所有的引脚作为GPIO口输入输出即可。

        【1】首先选定几个管脚,做一些定义(注意!!!:这边的DATAOUT(x)宏是采用了位带操作,直接对PortE的PODRE寄存器进行操作,这样就相当于在PortE接满0-15管脚的情况下,输出对应的16位数据):

#define LCD_CS_HIGH()                  (PORT_SetBits(PortC, Pin00))
#define LCD_CS_LOW()                   (PORT_ResetBits(PortC, Pin00))
#define LCD_RS_HIGH()                  (PORT_SetBits(PortC, Pin01))
#define LCD_RS_LOW()                   (PORT_ResetBits(PortC, Pin01))
#define LCD_WR_HIGH()                  (PORT_SetBits(PortC, Pin02))
#define LCD_WR_LOW()                   (PORT_ResetBits(PortC, Pin02))
#define LCD_RD_HIGH()                  (PORT_SetBits(PortC, Pin03))
#define LCD_RD_LOW()                   (PORT_ResetBits(PortC, Pin03))
#define LCD_RES_HIGH()                 (PORT_SetBits(PortA, Pin07))
#define LCD_RES_LOW()                  (PORT_ResetBits(PortA, Pin07))#define DATAOUT(x)                     M4_PORT->PODRE=(x)

        【2】其次是GPIO口初始化:

/**************************************************************************
* 函数名称: LCD_InitGPIO
* 功能描述: LCD初始化GPIO引脚
* 输入参数: 
* 输出参数: 
* 返 回 值: 
* 其它说明: 初始化LCD用到的GPIO口,包括CS\RS\WR\RD\RES\DB0-15
**************************************************************************/
void LCD_InitGPIO(void)
{stc_port_init_t stcPortInit;/* configure structure initialization */MEM_ZERO_STRUCT(stcPortInit);stcPortInit.enPinMode = Pin_Mode_Out;/* CS & RS & WR & RD & RES*/PORT_Init(PortC, Pin00, &stcPortInit);PORT_Init(PortC, Pin01, &stcPortInit);PORT_Init(PortC, Pin02, &stcPortInit);PORT_Init(PortC, Pin03, &stcPortInit);PORT_Init(PortA, Pin07, &stcPortInit);LCD_CS_HIGH();LCD_RS_HIGH();LCD_WR_HIGH();LCD_RD_HIGH();LCD_RES_HIGH();/*DB0-15*/PORT_Init(PortE, Pin00, &stcPortInit);PORT_Init(PortE, Pin01, &stcPortInit);PORT_Init(PortE, Pin02, &stcPortInit);PORT_Init(PortE, Pin03, &stcPortInit);PORT_Init(PortE, Pin04, &stcPortInit);PORT_Init(PortE, Pin05, &stcPortInit);PORT_Init(PortE, Pin06, &stcPortInit);PORT_Init(PortE, Pin07, &stcPortInit);PORT_Init(PortE, Pin08, &stcPortInit);PORT_Init(PortE, Pin09, &stcPortInit);PORT_Init(PortE, Pin10, &stcPortInit);PORT_Init(PortE, Pin11, &stcPortInit);PORT_Init(PortE, Pin12, &stcPortInit);PORT_Init(PortE, Pin13, &stcPortInit);PORT_Init(PortE, Pin14, &stcPortInit);PORT_Init(PortE, Pin15, &stcPortInit);
}

        【3】封装LCD写命令、写数据、写GRAM接口(注意!!!:这边的入参与串口屏有区别,串口屏入参为一个字节数据,而这边是U16即两字节数据,这会影响到颜色的表现):

/**************************************************************************
* 函数名称: LCD_WriteCMD
* 功能描述: LCD写命令
* 输入参数: 
* 输出参数: 
* 返 回 值: 
* 其它说明: 
**************************************************************************/
void LCD_WriteCMD(U16 Command)
{LCD_RS_LOW();LCD_CS_LOW();DATAOUT(Command);LCD_WR_LOW();LCD_WR_HIGH();LCD_CS_HIGH();
}/**************************************************************************
* 函数名称: LCD_WriteDAT
* 功能描述: LCD写数据
* 输入参数: 
* 输出参数: 
* 返 回 值: 
* 其它说明: 
**************************************************************************/
void LCD_WriteDAT(U16 Data)
{LCD_RS_HIGH();LCD_CS_LOW();DATAOUT(Data);LCD_WR_LOW();LCD_WR_HIGH();LCD_CS_HIGH();
}/**************************************************************************
* 函数名称: LCD_WriteRAM
* 功能描述: LCD写GRAM,写颜色值
* 输入参数: 
* 输出参数: 
* 返 回 值: 
* 其它说明: 
**************************************************************************/
void LCD_WriteRAM(uint16_t Data)
{LCD_RS_HIGH();LCD_CS_LOW();DATAOUT(Data);LCD_WR_LOW();LCD_WR_HIGH();LCD_CS_HIGH();
}

        【4】有了底层驱动之后,因为串口屏和并口屏都是用的ILI9341驱动,所以其他的功能接口,包括寄存器的配置,参考【嵌入式】MCU(HC32F460)+SPI接口LCD液晶屏ILI9341 移植emWin记录1----点亮LCD屏即可。

三 并口屏点亮

        有了上面的接口作为准备,就可以驱动并口屏显示一些简单的界面了。这边的程序也与串口屏类似,这边不再赘述。

四 移植emwin

        完成了点亮LCD屏之后,考虑到将要设计较为复杂的界面GUI,光用一些基本的绘图、显示字符接口不能满足要求,所以琢磨着再移植一套emWin,用来辅助设计GUI(由emWin的用户手册中可以看到,emWin是可以支持ILI9341的液晶屏驱动芯片的)。

        移植准备与串口屏类似,参考【嵌入式】MCU(HC32F460)+SPI接口LCD液晶屏ILI9341 移植emWin记录2----移植emWin,这边也不再赘述。

        需要重点提一下与串口屏emwin移植的区别,这也是本文的重点:

        这边涉及到两种移植方法,一种是直接线性访问驱动、第二种是间接访问驱动。关于这两种移植方法的区别可以参考方法一:直接线性访问驱动、方法一:间接访问驱动。

        【方法一】:直接线性访问驱动

void LCD_X_Config(void) {//方法1:直接线性访问驱动GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0);if (LCD_GetSwapXY()) {LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS);LCD_SetVSizeEx(0, YSIZE_PHYS, XSIZE_PHYS);} else {LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);}
}

        修改GUIDRV_Template.c文件。这边需要修改画点函数_SetPixelIndex(),在其中嵌入

自己的打点函数LCD_DrawPoint(x, y):

static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, LCD_PIXELINDEX PixelIndex) {#ifdef WIN32LCDSIM_SetPixelIndex(x, y, PixelIndex, pDevice->LayerIndex);#else//// Convert logical into physical coordinates (Dep. on LCDConf.h)//#if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)int xPhys, yPhys;xPhys = LOG2PHYS_X(x, y);yPhys = LOG2PHYS_Y(x, y);#else#define xPhys x#define yPhys y#endifGUI_USE_PARA(pDevice);GUI_USE_PARA(x);GUI_USE_PARA(y);GUI_USE_PARA(PixelIndex);{//// Write into hardware ... Adapt to your system//// TBD by customer...//LCD_DrawPoint(x, y);  //重要:自行添加的画点函数}#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)#undef xPhys#undef yPhys#endif#endif
}

        与此同时,清屏程序_FillRect也需要改一下,有利于提高清屏速度(注意!!!:之前的串口屏程序没有这个操作也能用,但可能会影响到清屏速度):

/**************************************************************************
* 函数名称: LCD_Fill
* 功能描述: 填充色块函数
* 输入参数: 
* 输出参数: 
* 返 回 值: 
* 其它说明: 
**************************************************************************/
void LCD_Fill(U16 sx,U16 sy,U16 ex,U16 ey,U16 color)
{          U16 i,j;U16 xlen=0;xlen=ex-sx+1;	   for(i=sy;i<=ey;i++){LCD_SetCursor(sx,i);      				//设置光标位置 LCD_WriteRAM_Prepare();     			//开始写入GRAM	  for(j=0;j<xlen;j++)LCD_WriteRAM(color);	//设置光标位置 	    }
}  /*********************************************************************
*
*       _FillRect
*/
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) {LCD_PIXELINDEX PixelIndex;int x;PixelIndex = LCD__GetColorIndex();if (GUI_pContext->DrawMode & LCD_DRAWMODE_XOR) {for (; y0 <= y1; y0++) {for (x = x0; x <= x1; x++) {_XorPixel(pDevice, x, y0);}}} else {
//    for (; y0 <= y1; y0++) {
//      for (x = x0; x <= x1; x++) {
//        _SetPixelIndex(pDevice, x, y0, PixelIndex);
//      }
//    }LCD_Fill(x0,y0,x1,y1,LCD_COLORINDEX);}
}

        其他部分的改动延用串口屏的移植即可。这样直接线性访问(LIN方式)移植成功。

        【方法二】:间接访问驱动

void LCD_X_Config(void) {//方法2:间接访问驱动GUI_DEVICE * pDevice;GUI_PORT_API PortAPI = {0};pDevice = GUI_DEVICE_CreateAndLink(&GUIDRV_FlexColor_API, COLOR_CONVERSION, 0, 0);if (LCD_GetSwapXY()) {LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS);LCD_SetVSizeEx(0, YSIZE_PHYS, XSIZE_PHYS);} else {LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);}//    PortAPI.pfWrite8_A0  = LcdWriteReg;
//    PortAPI.pfWrite8_A1  = LcdWriteData;
//    PortAPI.pfWriteM8_A1 = LcdWriteDataMultiple;
//    PortAPI.pfReadM8_A1  = LcdReadDataMultiple;PortAPI.pfWrite16_A0  = LcdWriteReg;PortAPI.pfWrite16_A1  = LcdWriteData;PortAPI.pfWriteM16_A1 = LcdWriteDataMultiple;PortAPI.pfReadM16_A1  = LcdReadDataMultiple;GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66709, GUIDRV_FLEXCOLOR_M16C0B16);
}

        这边的读写命令接口仍然使用8位访问的话,对于并口屏会有问题,所以修改接口为16位访问的方式:

static void LcdWriteReg(U16 Data) {LCD_WriteCMD(Data);
}static void LcdWriteData(U16 Data) {LCD_WriteDAT(Data);
}static void LcdWriteDataMultiple(U16 * pData, int NumItems) {while(NumItems--){LCD_WriteDAT(*pData);}
}static void LcdReadDataMultiple(U16 * pData, int NumItems) {return ;
}

        后面的GUIDRV_FlexColor_SetFunc接口内容,由于还是用的驱动芯片ILI9341,所以也无需改动这边的代码。(注意!!!:GUIDRV_FLEXCOLOR_F66709 和 GUIDRV_FLEXCOLOR_M16C0B16 ,前一个参数是选择控制器的,后一个参数是选择位宽等模式的。首先你要看一下你所用的LCD控制器是否在受支持的范围内,如果不支持那就GG了。我的显示器是ILI9341所以我选择了66709这种方式。具体可以参考emWin用户手册中的内容

         至此,第二种方法也移植成功。

五 汇总几个遇到的坑

        (1)设置LCD自动扫描方向的接口LCD_ScanDir中,有一段这样的代码:

        这边我一开始设置成regval |= 0x08,导致的结果就是颜色反向了,原因在于0x36命令是存储器访问控制,其中有一位寄存器表示RGB与BGR的顺序(若为1,则是BGR;若为0,则是RGB):

         (2)emWin中定义驱动器颜色COLOR_CONVERSION为GUICC_565或者GUICC_M565是有区别的,同样一个是RGB,一个是BGR。

        (3)一开始使用方法二间接访问驱动,不管怎么操作,预期是GUI_SetBkColor(GUI_WHITE),然而出来的屏幕背景都是红色。后来查明原因在于LCDConf.c中,还是使用的之前串口屏的8位读写访问,可能预期发送的是白色(0xFFFF)命令,而实际只发出去了一半,即红色(0xFF00)命令。后来将这边的8位访问修改为16位访问,问题得到解决

六 附录

【1】【嵌入式】MCU(HC32F460)+SPI接口LCD液晶屏ILI9341 移植emWin记录1----点亮LCD屏

【2】【嵌入式】MCU(HC32F460)+SPI接口LCD液晶屏ILI9341 移植emWin记录2----移植emWin

【3】HC32F460相关文档资料汇总

【4】emWin_V5.42中文手册

【5】ILI9341驱动器相关文档资料汇总

这篇关于【嵌入式】MCU(HC32F460)+并口LCD液晶屏ILI9341 移植emWin记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/212603

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

嵌入式方向的毕业生,找工作很迷茫

一个应届硕士生的问题: 虽然我明白想成为技术大牛需要日积月累的磨练,但我总感觉自己学习方法或者哪些方面有问题,时间一天天过去,自己也每天不停学习,但总感觉自己没有想象中那样进步,总感觉找不到一个很清晰的学习规划……眼看 9 月份就要参加秋招了,我想毕业了去大城市磨练几年,涨涨见识,拓开眼界多学点东西。但是感觉自己的实力还是很不够,内心慌得不行,总怕浪费了这人生唯一的校招机会,当然我也明白,毕业

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

深入探索嵌入式 Linux

摘要:本文深入探究嵌入式 Linux。首先回顾其发展历程,从早期尝试到克服诸多困难逐渐成熟。接着阐述其体系结构,涵盖硬件、内核、文件系统和应用层。开发环境方面包括交叉编译工具链、调试工具和集成开发环境。在应用领域,广泛应用于消费电子、工业控制、汽车电子和智能家居等领域。关键技术有内核裁剪与优化、设备驱动程序开发、实时性增强和电源管理等。最后展望其未来发展趋势,如与物联网融合、人工智能应用、安全性与

perl的学习记录——仿真regression

1 记录的背景 之前只知道有这个强大语言的存在,但一直侥幸自己应该不会用到它,所以一直没有开始学习。然而人生这么长,怎就确定自己不会用到呢? 这次要搭建一个可以自动跑完所有case并且打印每个case的pass信息到指定的文件中。从而减轻手动跑仿真,手动查看log信息的重复无效低质量的操作。下面简单记录下自己的思路并贴出自己的代码,方便自己以后使用和修正。 2 思路整理 作为一个IC d