STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式

本文主要是介绍STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

随言:

STemWin、emWin 与ucGUI其实都师出同门,都是是Segger 公司之手。

STemWin 是Segger 公司为ST公司定制的图形软件库;uC/GUI 是Segger 公司为Micrium 公司定制的图形软件库;

与其说是花钱定制的版本,其实都是正统emWin的别名版本,微改动。

但是在STM32芯片上面使用STemWin是免费的。当然ST公司也不会给其他芯片使用STemWin的机会,

故在库函数里使用了ST芯片内部CRC32寄存器进行校验是否为ST的芯片,若是则工作正常,否则反之。

像STemWin这个平台通用GUI库来说,就是按要求填充底层接口,然后程序调用库上层API接口。

初接触STemWin强力推荐官方手册《AN4323 应用笔记 STemWin 库入门指南》!!!

去官网搜索:AN4323 即可。

1.STemWin:

先写好一份TFTLCD显示和支持触摸的代码(以前文章写过)。

然后打开Cube库文件安装路径,找到与硬件对应的库文件,比如我用的是STM32F407对应F4系列。

C:\Users\admin\STM32Cube\Repository\STM32Cube_FW_F4_V1.25.1\Middlewares\ST\STemWin

其实各个文件夹下放的文件,只看文件夹名字大概都猜到了大概对应文件功能。

1.1Config:

包含库和LCD驱动程序的配置文件

首先显示驱动方式有两种,一种是画点,另一种是操作显存。画点是万能的,适用于所有屏幕。操作显存适用于RGB屏幕。

GUIConf.c:主要作用是分配STemWin内部缓存。

LCDConf_Lin_Template.c: 屏幕显示驱动底层填充接口,以显存方式。

LCDConf_FlexColor_Template.c:屏幕显示驱动底层填充接口,以画点方式

                                       画点有两种做法:使用自定义画点和STemWin自带画点函数(依据MCU屏幕IC)。

GUIDRV_Template.c: 里面是自定义画点填充底层函数,通过画点读点方式,适用于所有的屏幕。

1.2 Documentation:

包含emWin“用户和参考指南”英文版STemWin544.pdf用户手册,其实就是emWin544手册。

 但是网上有emWIN5.12中文手册,虽不是最新,但是够用,比看英文手册舒服。

1.3 inc:

存放STemWin库组件的头文件。

1.4 Lib

存放在STemWin的静态库文件,不开源。

命名格式为STemWin_CM x _ YY_wc_ot_zzzz .a,其中

         x:CMx核心类别(CM0,CM3,CM4或CM7)
         YY:操作系统支持
         wc:  Wchar_t类型大小(wc16或wc32。根据编译器选择,先随便选一个报错再换)
         ot: 高速优化生成的二进制文件
         zzzz:支持ARGB

上面内容来源于文件夹中的Release_Notes.html。

1.5 OS

根据用户程序是否带RTOS选择哪个文件。带了RTOS就选名字带OS的。

其实带着RTOS选择使用GUI_X.c也没关系。

2.环境

我用的是STM32CubeIDE开发,硬件是STM32F407 + TFT LCD,分辨率800 *480.

由于我使用的是TFT MCU屏幕,故只实现FlexColor方式中的两种画点做法

使能STM32F4的CRC寄存器。

2.1 STemWin初始化流程图

3.FlexColor自定义画点

3.1 选择STemWin源文件

在写好TFTLCD的工程中把上面cube库中的STemWin的Config、inc、Lib和OS复制到新建文件夹,并命名为STemWin。

1、打开工程中的STemWin文件夹中Config,把LCDConf_Lin_Template.c、LCDConf_Lin_Template.h和SIMConf.c删除,LCDConf_FlexColor_Template.h重命名为LCDConf.h

2、打开工程中的STemWin文件夹中Lib,我选择使用STemWin_CM4_wc32.a,其他的文件删除。若出错就选STemWin_CM4_wc16.a,和编译器有关。

3、打开工程中的STemWin文件夹中OS,我没有带系统,删除GUI_X_OS.c。

3.2 设置STM32CubeIDE工程

打开STM32CubeIDE工程,或者刷新一下。出现了刚才新增的文件。

1、右键工程,比如我这是F407 TFT-LCD STemWin。选择属性。

2、添加头文件。 

3、添加静态库。需要注意的是添加静态库名字前面需要添加一个: 

最后编译一下,就会通过。如果不通过检测一下步骤。我是边写边做。

3.3 编程

1、先打开GUIConfig.c,修改STemWin内部缓存大小。我先设置50Kb大小作为缓存。

#define GUI_NUMBYTES  (50*1024)

2、打开GUIDRV_Template.c修改底层填充函数。

分别是:画点函数_SetPixelIndex()、读点函数_GetPixelIndex()和 填充色块函数_FillRect()。

static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {LCD_Fast_DrawPoint(x, y, PixelIndex);
}static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {return LCD_ReadPoint(x,y);
}static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) {LCD_PIXELINDEX PixelIndex;PixelIndex = LCD__GetColorIndex();LCD_Fill(x0, y0, x1, y1, PixelIndex);
}

3、打开LCDConf_FlexColor_Template.c

先修改屏幕分辨率,我的屏幕分辨率是480 x 800.

#define XSIZE_PHYS  480 // To be adapted to x-screen size
#define YSIZE_PHYS  800 // To be adapted to y-screen size

修改LCD显示驱动配置函数LCD_X_Config()

GUIDRV_Template_API是会调用上面配置的LCD驱动,画点。

GUICC_M565是LCD调色板。颜色是RRRRRGGGGGGBBBBB,与GUICC_565颜色顺序相反。

void LCD_X_Config(void) {//// Set display driver and color conversion//GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API , GUICC_M565, 0, 0);//// Display driver configuration, required for Lin-driver//LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
}

LCD_X_DisplayDriver()显示驱动程序出于多种目的调用此函数。添加LCD初始化函数LCD_Init()。

int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {int r;(void) LayerIndex;(void) pData;switch (Cmd) {case LCD_X_INITCONTROLLER: {LCD_Init();return 0;}default:r = -1;}return r;
}

还有打开stm32f4xx_it.c,添加GUI内部延时计数,修改如下:

#include "GUI.h"extern volatile GUI_TIMER_TIME OS_TimeMS;void SysTick_Handler(void)
{HAL_IncTick();OS_TimeMS++;
}

最后修改main函数:

GUI_Init(); 初始化STemWin。

WM_SetCreateFlags(WM_CF_MEMDEV);

把屏幕显示内容暂时缓存,再复制到显示屏。主要作用是避免闪变效应,提升速度。

#include "GUI.h"
#include "WM.h"int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_FSMC_Init();MX_USART1_UART_Init();MX_CRC_Init();/* Init the STemWin GUI Library */GUI_Init();/* Activate the use of memory device feature */WM_SetCreateFlags(WM_CF_MEMDEV);GUI_Clear();GUI_SetFont(&GUI_Font20_1);GUI_DispStringAt("Hello world!", (LCD_GetXSize()-100)/2, (LCD_GetYSize()-20)/2);while (1){}
}

3.4 效果

4.FlexColor自带IC驱动

刚好我的MCU TFT LCD屏幕的IC不在STemWin自带的IC里面,下面只能把过程写出来,抱歉了~。

有机会如果能借到一块手册中有的IC的话我再补上吧,哎~。

首先先确保所使用的MCU LCD IC在STemWin 544版本的手册中。

4.1 准备

把上面的程序复制一份。config文件夹重新去cube库里面复制如下文件

4.2 编程

1、现将堆栈空间改大。防止运行时堆栈不足导致错误。

2、打开GUIConf.c,修改缓存大小。根据实况自行修改。

#define GUI_NUMBYTES  (100* 1024)void GUI_X_Config(void) {static U32 aMemory[GUI_NUMBYTES / 4];GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);GUI_SetDefaultFont(GUI_FONT_6X8);
}

3、打开LCDConf_FlexColor_Template.c

#define XSIZE_PHYS  480 // To be adapted to x-screen size
#define YSIZE_PHYS  800 // To be adapted to y-screen size

4、修改LCD显示驱动配置函数LCD_X_Config()

GUIDRV_Template_API是会调用上面配置的LCD驱动,画点。

void LCD_X_Config(void) {GUI_DEVICE * pDevice;CONFIG_FLEXCOLOR Config = {0};GUI_PORT_API PortAPI = {0};pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_M565, 0, 0);LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);Config.Orientation = GUI_SWAP_XY | GUI_MIRROR_Y;GUIDRV_FlexColor_Config(pDevice, &Config);PortAPI.pfWrite16_A0  = LcdWriteReg;PortAPI.pfWrite16_A1  = LcdWriteData;PortAPI.pfWriteM16_A1 = LcdWriteDataMultiple;PortAPI.pfReadM16_A1  = LcdReadDataMultiple;GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66708, GUIDRV_FLEXCOLOR_M16C0B16);
}

主要注意的是这个函数GUIDRV_FlexColor_SetFunc()的参数.

GUIDRV_FLEXCOLOR_F66708:表示对应手册上自己使用的LCD MCU一致。如下图。

GUIDRV_FLEXCOLOR_M16C0B16:表示16位总线无缓存。

5、填充下面四个函数

LcdWriteReg()设置寄存器地址函数。这个函数一般设置x、y、写RAM和读RAM 寄存器地址。

如果花屏了,百分98%是这里设置问题,打印数据排查。

LcdWriteData()写数据函数。

LcdWriteDataMultiple()连续写数据函数。

LcdReadDataMultiple()连续读数据函数。

static void LcdWriteReg(U16 Data) {// ... TBD by userLCD_WR_REG(Data);
}static void LcdWriteData(U16 Data) {// ... TBD by userLCD_WR_DATA(Data);
}static void LcdWriteDataMultiple(U16 * pData, int NumItems) {while (NumItems--) {// ... TBD by userLCD_WR_DATA(*pData);pData++;}
}static void LcdReadDataMultiple(U16 * pData, int NumItems) {while (NumItems--) {// ... TBD by user}
}

LCD_X_DisplayDriver()显示驱动程序出于多种目的调用此函数。添加LCD初始化函数LCD_Init()。

int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {int r;(void) LayerIndex;(void) pData;switch (Cmd) {case LCD_X_INITCONTROLLER: {LCD_Init();return 0;}default:r = -1;}return r;
}

还有打开stm32f4xx_it.c,添加GUI内部延时计数,修改如下:

#include "GUI.h"extern volatile GUI_TIMER_TIME OS_TimeMS;void SysTick_Handler(void)
{HAL_IncTick();OS_TimeMS++;
}

main函数就不写。

5. STemWin_SampleDemo

TFT STemWin_哔哩哔哩_bilibili

TFT STemWin

6. 问题记录

6.1 关于STemWin内部缓存大小

关于STemWin内部缓存大小分配问题,主要取决程序使用了内部什么功能而定。

官方手册《AN4323 应用笔记 STemWin 库入门指南》提及。

6.2 关于动画部分背景黑屏

如果出现下面两种鼠标指针移动过程中背景黑色和动画移动过程黑屏。

那就是你的读点函数_GetPixelIndex()出现问题了,读到的值不正确。

6.3 使用FlexColor自带驱动出现花屏

如果花屏了,首先先确定函数GUIDRV_FlexColor_SetFunc()的参数.设置是否和硬件IC一致。

LcdWriteReg()设置寄存器地址函数。

这个函数一般设置x、y、写RAM和读RAM 寄存器地址。

如果花屏了,百分98%是这里设置问题,打印数据排查。

LcdWriteData()写数据函数。也要打印设置寄存器的数据。

拿到对应的数据后,与厂商给的驱动设置x、y、写RAM和读RAM代码进行对比。

  全篇完。

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!

 

 

这篇关于STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S