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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第1张图片

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

1.1Config:

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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第2张图片

首先显示驱动方式有两种,一种是画点,另一种是操作显存。画点是万能的,适用于所有屏幕。操作显存适用于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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第3张图片

存放在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初始化流程图

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第4张图片

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工程,或者刷新一下。出现了刚才新增的文件。

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第5张图片

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

2、添加头文件。 

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第6张图片

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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第7张图片

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

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 效果

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第8张图片

4.FlexColor自带IC驱动

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

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

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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第9张图片

4.1 准备

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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第10张图片

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 user
	LCD_WR_REG(Data);
}


static void LcdWriteData(U16 Data) {
  // ... TBD by user
	LCD_WR_DATA(Data);
}


static void LcdWriteDataMultiple(U16 * pData, int NumItems) {
  while (NumItems--) {
    // ... TBD by user
	  LCD_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 库入门指南》提及。

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第11张图片

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第12张图片

6.2 关于动画部分背景黑屏

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

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

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第13张图片

STM32CubeIDE TFT-LCD移植STemWin,FlexColor(间接访问)两种实现方式_第14张图片

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

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

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

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

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

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

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

  全篇完。

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

 

 

你可能感兴趣的:(STM32,stm32,ide,单片机)