基于STM32emWin532版本的移植

  • 移植前提
  • 1、下载所需源码
  • 2、直接拷贝Cubemx的STemwin
  • 文件说明
  • 2、需已完成底层绘制LCD的驱动调试
  • 移植
  • 在项目工程目录增加以下文件夹及文件
  • 配置单次图像刷写最大允许字节
  • 配置驱动API接口及屏幕属性
  • 配置底层绘制调用接口
  • 配置定时器所需计时功能读写锁信号量等
  • 加入静态库文件
  • 测试代码
  • 常用颜色及格式转换
  • IAR与Keil指定缓冲区地址的两种方式
  • 测试GUI绘制接口


移植前提

1、下载所需源码

下载地址 下载完成后目录结构如下(demo目录来自CubeMAX的拷贝):重点关注Config、Lib、OS文件夹

freemodbus tcp stm32 主机 移植 stm32移植emwin_单片机

2、直接拷贝Cubemx的STemwin

freemodbus tcp stm32 主机 移植 stm32移植emwin_stm32_02


看到仓库地址路径信息,打开它

freemodbus tcp stm32 主机 移植 stm32移植emwin_#define_03


freemodbus tcp stm32 主机 移植 stm32移植emwin_#if_04

文件说明

参考

目录/文件名

说明

config

液晶驱动接口、emwin配置文件

GUIConf.c

用于配置emwin使用RAM空间的大小

GUIConf.H

用于剪裁emwin的功能

GUIDRV_Template.c LCDConf_XXXX_Template.c

应用在不同液晶时使用的驱动文件

inc

emwin库核心的头文件

XXXX.h

各种关于库函数的申明、定义

Lib

emwin的核心库文件

MCD-ST Image SW License Agreement V2.pdf

软件许可协议

emwin核心库文件

STemWin_CM4_wcXX.a XX=16时

适用于EWARM7 和 Keil5

STemWin_CM4_wcXX.a XX=32时

适用于EWARM8和SW4STM32

STemWin_CM4_wcXX_ot.a

ot表示此核心库已做优化

STemWin_CM4_wcXX_ARGB.a

ARGB 表示此核心库的逻辑颜色从高位到低位的排列顺序为 ARGB

STemWin_CM4_wcXX_to_ARGB.a

优化使用ARGB颜色排列

STemWin_CM4_OS_wcXX.a

OS表示操作系统环境下使用的核心库,

其余同上

STemWin_CM4_OS_wcXX_to.a

STemWin_CM4_OS_wcXX_ARGB.a

STemWin_CM4_OS_wcXX_to_ARGB.a

STemWin_WIN32.lib STemWin_WIN32_ARGB.lib

在Windows系统中仿真使用的核心库

OS

emwin 的时间相关文件

GUI_X.C

裸机环境下的延时和时基相关文件

GUI_X_OS.C

提供给操作系统的接口,用于在操作系统环境下的延时和进程调度管理

Software

包含emwin的各种PC端软件工具

JPEG2MovieScripts

视频格式转换器用到的一些脚本文件

Bin2C.exe

二进制C转换器

BmpCvtST.exe

位图转换器

emVNC.exe

通用VNC客户端

emWinPlayer.exe

视频播放器

emWinSPY.exe

运行时资源查看器

emWinView.exe

模拟查看器

FontCvST.exe

字体生成器

GUIBulider.exe

界面编辑器

JPEG2Movie.exe

视频格式转换器

license.txt

软件许可协议

U2C.EXE

UTF-8编码到C转换器

Release_Notes.html

关于 emwin 库不同发行版本的简要更新说明文档

2、需已完成底层绘制LCD的驱动调试

移植

在项目工程目录增加以下文件夹及文件

freemodbus tcp stm32 主机 移植 stm32移植emwin_嵌入式_05

配置单次图像刷写最大允许字节

GUIConf.c中配置:

freemodbus tcp stm32 主机 移植 stm32移植emwin_#define_06

配置驱动API接口及屏幕属性

LCDConf_FlexColor_Template.c配置实现画点函数等API接口选择依据液晶芯片IC型号

freemodbus tcp stm32 主机 移植 stm32移植emwin_单片机_07

#define XSIZE_PHYS  480 // To be adapted to x-screen size
#define YSIZE_PHYS  272 // To be adapted to y-screen size
//```
//```
//````
void LCD_X_Config(void) {
  GUI_DEVICE * pDevice;
  CONFIG_FLEXCOLOR Config = {0};
  GUI_PORT_API PortAPI = {0};
  //
  // Set display driver and color conversion
  //
  pDevice = GUI_DEVICE_CreateAndLink(&GUIDRV_FLEXCOLOR, 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);
  //
  // Orientation
  //
  Config.Orientation = 0;//GUI_SWAP_XY | GUI_MIRROR_Y;
  GUIDRV_FlexColor_Config(pDevice, &Config);
  //
  // Set controller and operation mode
  //
  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);
}


/*找不到适合的驱动*/
void LCD_X_Config(void) {
	CONFIG_FLEXCOLOR Config = {0};
	 // 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, XSIZE_PHYS, YSIZE_PHYS);
	  //
	  // Orientation
	  //
	  Config.Orientation = 0;//GUI_SWAP_XY | GUI_MIRROR_Y;
	  GUIDRV_FlexColor_Config(pDevice, &Config);
}

配置底层绘制调用接口

GUIDRV_Template.c

static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
    //
    // 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
    #endif
    GUI_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(xPhys ,yPhys ,PixelIndex); //此处调用画点函数
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
      #undef xPhys
      #undef yPhys
    #endif
}
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
  unsigned int PixelIndex;
    //
    // 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
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    {
      //
      // Write into hardware ... Adapt to your system
      //
      // TBD by customer...
      //
      //PixelIndex = 0;
      PixelIndex = LCD_ReadPoint(xPhys ,yPhys);//次处调用读点函数
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
      #undef xPhys
      #undef yPhys
    #endif
  return PixelIndex;
}
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);//此处修改为画矩形函数
  }
}

配置定时器所需计时功能读写锁信号量等

GUI_X.c

freemodbus tcp stm32 主机 移植 stm32移植emwin_#if_08


硬件启动定时器或者直接使用systick1ms中断,本例使用定时器

freemodbus tcp stm32 主机 移植 stm32移植emwin_#define_09


注意需要包含头文件引用:#include "GUI.h"

freemodbus tcp stm32 主机 移植 stm32移植emwin_#define_10

依据操作系统增加修改以下代码,本例FreeRTOS

#include "cmsis_os.h"
    
/*********************************************************************
*
* Global data
*/
static osMutexId osMutex;
static osSemaphoreId osSemaphore;
/**********************************************************************/

/* Init OS */
void GUI_X_InitOS(void)
{ 
  /* Create Mutex lock */
  osMutexDef(MUTEX);
  
  /* Create the Mutex used by the two threads */
  osMutex = osMutexCreate(osMutex(MUTEX));
  
  /* Create Semaphore lock */
  osSemaphoreDef(SEM);
  
  /* Create the Semaphore used by the two threads */
  osSemaphore= osSemaphoreCreate(osSemaphore(SEM), 1);  
}

void GUI_X_Unlock(void)
{ 
  osMutexRelease(osMutex);
}

void GUI_X_Lock(void)
{
  osMutexWait(osMutex , osWaitForever) ;
}

/* Get Task handle */
U32 GUI_X_GetTaskId(void) 
{ 
  return ((U32) osThreadGetId());
}


void GUI_X_WaitEvent (void) 
{
  osSemaphoreWait(osSemaphore , osWaitForever) ;
}


void GUI_X_SignalEvent (void) 
{
  osMutexRelease(osSemaphore);
}

加入静态库文件

这个依据编译器选择,keil选择时注意文件类型应为lib型否则无法编译

freemodbus tcp stm32 主机 移植 stm32移植emwin_单片机_11


freemodbus tcp stm32 主机 移植 stm32移植emwin_嵌入式_12

测试代码

常用颜色及格式转换

/*常用转换*/
#define TL_GET_ARGB8888(a, r, g, b) ((((unsigned int)(a)) << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b)))
#define TL_GET_ARGB8888_A(rgb) ((((unsigned int)(rgb)) >> 24) & 0xFF)
#define TL_GET_RGB888(r, g, b) ((0xFF << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b)))
#define TL_GET_RGB888_R(rgb) ((((unsigned int)(rgb)) >> 16) & 0xFF)
#define TL_GET_RGB888_G(rgb) ((((unsigned int)(rgb)) >> 8) & 0xFF)
#define TL_GET_RGB888_B(rgb) (((unsigned int)(rgb)) & 0xFF)
#define TL_CV_RGB_32_to_16(rgb) (((((unsigned int)(rgb)) & 0xFF) >> 3) | ((((unsigned int)(rgb)) & 0xFC00) >> 5) | ((((unsigned int)(rgb)) & 0xF80000) >> 8))
#define TL_CV_RGB_16_to_32(rgb) ((0xFF << 24) | ((((unsigned int)(rgb)) & 0x1F) << 3) | ((((unsigned int)(rgb)) & 0x7E0) << 5) | ((((unsigned int)(rgb)) & 0xF800) << 8))
/*RGB565*/
#define TL_GET_RGB565_R(rgb) ((((unsigned short)(rgb)) >> 11) & 0xF800)/*11111 111111 11111*/
#define TL_GET_RGB565_G(rgb) ((((unsigned short)(rgb)) >> 5) & 0x07E0)
#define TL_GET_RGB565_B(rgb) (((unsigned short)(rgb)) & 0x001F)
#define ASSEMBLE_RGB(R, G, B)    ((((R)& 0xF8) << 8) | (((G) & 0xFC) << 3) | (((B) & 0xF8) >> 3))
/*红蓝交换*/
#define TL_CV_RGB888_SWAP(RGB)   (((unsigned int)RGB>>16&0xFF)|((unsigned int)RGB&0x00FF00)|((unsigned int)RGB<<16&0xFF0000))
/*LCD color*/
#define LCD_COLOR_WHITE          0xFFFFU
#define LCD_COLOR_BLACK          0x0000U
#define LCD_COLOR_GREY           0xF7DEU
#define LCD_COLOR_BLUE           0x001FU
#define LCD_COLOR_BLUE2          0x051FU
#define LCD_COLOR_RED            0xF800U
#define LCD_COLOR_MAGENTA        0xF81FU
#define LCD_COLOR_GREEN          0x07E0U
#define LCD_COLOR_CYAN           0x7FFFU
#define LCD_COLOR_YELLOW         0xFFE0U
#define     RED          0xF800   //红色
#define     GREEN        0x07E0   //绿色
#define     BLUE         0x001F   //蓝色
#define     WHITE        0xFFFF   //白色
#define     GRAY        0x8430    //灰色
#define     LGRAY        0xC618   //浅灰色
#define     DARKGRAY     0x8410   //深灰色
#define     PORPO        0x801F   //紫色
#define     PINK         0xF81F	  //粉色	 
#define     GRAYBLUE     0x5458   //灰蓝色
#define     LGRAYBLUE    0xA651   //浅灰蓝色
#define     DARKBLUE     0x01CF   //深灰蓝色
#define     LIGHTBLUE    0x7D7C   //浅蓝色
#define     BLACK        0x0000   //黑色
#define     YELLOW       0xFFE0   //黄色
#define     ORANGE       0xFC08   //橙色

IAR与Keil指定缓冲区地址的两种方式

#if defined(__ICCARM__) 
/*IAR版本:定义帧缓冲区地址*/ 
uint16_t ltdc_layer0[LCD_PIXEL_HEIGHT][LCD_PIXEL_WIDTH] @LCD_FRAME_BUFFER;  
uint16_t ltdc_layer1[LCD_PIXEL_WIDTH][LCD_PIXEL_HEIGHT] @(LCD_FRAME_BUFFER+BUFFER_OFFSET);  
#else defined(__CC_ARM) || defined(__GNUC__)
/*MDK版本:定义帧缓冲区地址*/ 
uint16_t ltdc_layer0[LCD_PIXEL_HEIGHT][LCD_PIXEL_WIDTH] __attribute__((at(LCD_FRAME_BUFFER)));
uint16_t ltdc_layer1[LCD_PIXEL_HEIGHT][LCD_PIXEL_WIDTH] __attribute__((at(LCD_FRAME_BUFFER+BUFFER_OFFSET)));

测试GUI绘制接口

void MainWindow_Init(void)
{
    GUI_Init();
  
    GUI_SetBkColor(GUI_BLUE);   //设置背景颜色
    GUI_SetColor(GUI_YELLOW);   //设置颜色
    GUI_Clear();                //清屏
  
    GUI_SetFont(GUI_FONT_24_ASCII); //设置字体
    GUI_DispStringAt("HELLO WORD!", 0, 0);
    GUI_DispStringAt("123456789", 0, 200);
}