参考博客链接
1.官方文件介绍

| 文件夹 | 说明 |
|---|---|
| Config | 其中的 GUIConf.c 文件用于配置 emWin 的存储空间分配,GUIConf.h 文 件 用 于 裁 剪 emWin 的 功 能 。 其 余 的 GUIDRV_Template.c 、LCDConf_FlexColor.c、 GUIDRV_wf.c 是 emWin 应用在不同液晶时使用的不同驱动模板 |
| Lib | 包含了 emWin 的代码库文件,针对 Cortex-M0、 M3 和 M4 这些不同 CPU 内核以及是否优化,都有一个相对应的 emWin 库,在使用的时候我们要根据自己的平台选择合适的库文件 |
| inc | 包含了全部的 emWin 库核心的头文件,各种关于库函数的声明、定义都在这些文件里面 |
| OS | 包含了 GUI_X.c 及 GUI_X_FreeRTOS.c 文件,分别是对应裸机平台的 GUI 延时,和多任务系统平台的关于进程调度之类的一些 emWin 所需要的底层接口 |
现在开始新建工程,假定我们已经实现了以下函数
| LCD初始化函数 | void xxLCD_Init(void) |
|---|---|
| LCD画点函数 | void LCD_DrawPoint(uint16_t x, uint16_t y, uint32_t color) |
| LCD读点函数 | uint32_t LCD_ReadPoint(uint16_t x, uint16_t y); |
/ * @功能说明: LCD画点函数 * @参数: x:x坐标 * y:y坐标 * color:颜色 * @返回值: 无 */ void LCD_DrawPoint(uint16_t x, uint16_t y, uint32_t color) {
}
/ * @功能说明: LCD读点函数 * @参数: x:x坐标 * y:y坐标 * @返回值: 像素值 */ uint32_t LCD_ReadPoint(uint16_t x, uint16_t y) {
}
2.添加文件进工程
- 将Inc里面的文件全部添加进工程,因为全是头文件,只需要添加头文件路径即可

- 添加Lib文件夹中合适的库文件,并注意添加为库文件
如图

- OS文件夹中选裸机文件添加进工程

- Config文件夹中需要添加的文件

- 完成之后如下图

箭头指向的库文件略有不同
编辑文件
- GUIconf.h文件
这里需要根据自己的需要配置STemWin
简要介绍宏定义
GUI_NUM_LAYERS 图层数目
OS_SUPPORT 是否支持操作系统
GUI_SUPPORT_TOUCH 是否支持触摸屏
GUI_DEFAULT_FONT 字体大小
#ifndef GUICONF_H #define GUICONF_H /* * * Multi layer/display support */ #define GUI_NUM_LAYERS 1 // Maximum number of available layers /* * * Multi tasking support */ #ifdef OS_SUPPORT #define GUI_OS (1) // Compile with multitasking support #else #define GUI_OS (0) #endif /* * * Configuration of touch support */ #ifndef GUI_SUPPORT_TOUCH #define GUI_SUPPORT_TOUCH (0) // Support touchscreen #endif /* * * Default font */ #define GUI_DEFAULT_FONT &GUI_Font8x16 /* * * Configuration of available packages */ #define GUI_SUPPORT_MOUSE (1) /* Support a mouse */ #define GUI_WINSUPPORT (1) /* Use window manager */ #define GUI_SUPPORT_MEMDEV (1) /* Memory device package available */ #define GUI_SUPPORT_DEVICES (1) /* Enable use of device pointers */ #endif /* Avoid multiple inclusion */ - GUIConf.c
#include "GUI.h" #include "myLCD.h" /* * * Defines * */ // // Define the available number of bytes available for the GUI // #define GUI_NUMBYTES 1024 * 1024 * 8 //8MB #define GUI_EXTBUFADD (LCD_FRAME_BUFFER + 800 * 480 * 3) static U32 aMemory[GUI_NUMBYTES / 4] __attribute__((at(GUI_EXTBUFADD))); /* * * Public code * */ /* * * GUI_X_Config * * Purpose: * Called during the initialization process in order to set up the * available memory for the GUI. */ void GUI_X_Config(void) { // // 32 bit aligned memory area // //static U32 *aMemory = [GUI_NUMBYTES / 4]; // // Assign memory to emWin // GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES); // // Set default font // GUI_SetDefaultFont(GUI_DEFAULT_FONT); } /* End of file / static U32 aMemory[GUI_NUMBYTES / 4] STemWin的动态内存单位 字
如果使用内部RAM作为STemWin的动态内存 可以把
#define GUI_EXTBUFADD (LCD_FRAME_BUFFER + 800 * 480 * 3) static U32 aMemory[GUI_NUMBYTES / 4] __attribute__((at(GUI_EXTBUFADD)));
改为
#define GUI_NUMBYTES 1024 * 8 //8KB static U32 aMemory[GUI_NUMBYTES / 4];
- LCDConf_Lin_Template.c
/* * SEGGER Microcontroller GmbH & Co. KG * * Solutions for real time microcontroller applications * * * * (c) 1996 - 2017 SEGGER Microcontroller GmbH & Co. KG * * * * Internet: www.segger.com Support: * * * emWin V5.44 - Graphical user interface for embedded applications All Intellectual Property rights in the Software belongs to SEGGER. emWin is protected by international copyright laws. Knowledge of the source code may not be used to write a similar product. This file may only be used in accordance with the following terms: The software has been licensed to STMicroelectronics International N.V. a Dutch company with a Swiss branch and its headquarters in Plan- les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_ troller products commercialized by Licensee only, sublicensed and dis_ tributed under the terms and conditions of the End User License Agree_ ment supplied by STMicroelectronics International N.V. Full source code is available at: www.segger.com We appreciate your understanding and fairness. ---------------------------------------------------------------------- File : LCDConf_Lin_Template.c Purpose : Display controller configuration (single layer) ---------------------------END-OF-HEADER------------------------------ */ / * @attention * *
© Copyright (c) 2018 STMicroelectronics. * All rights reserved.
* * This software component is licensed by ST under Ultimate Liberty license SLA0044, * the "License"; You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * http://www.st.com/SLA0044 * */ #include "GUI.h" #include "GUIDRV_Lin.h" #include "MyLCD.h" /* * * Layer configuration (to be modified) * */ // // Physical display size // #define XSIZE_PHYS TFTLCD_WIDTH //定义宽度 #define YSIZE_PHYS TFTLCD_HEIGHT//定义长度 // // Color conversion // #define COLOR_CONVERSION GUICC_M565 // // Display driver // #define DISPLAY_DRIVER &GUIDRV_Template_API // // Buffers / VScreens // #define NUM_BUFFERS 1 // Number of multiple buffers to be used #define NUM_VSCREENS 1 // Number of virtual screens to be used /* * * Configuration checking * */ #ifndef VRAM_ADDR #define VRAM_ADDR 0 // TBD by customer: This has to be the frame buffer start address #endif #ifndef XSIZE_PHYS #error Physical X size of display is not defined! #endif #ifndef YSIZE_PHYS #error Physical Y size of display is not defined! #endif #ifndef COLOR_CONVERSION #error Color conversion not defined! #endif #ifndef DISPLAY_DRIVER #error No display driver defined! #endif #ifndef NUM_VSCREENS #define NUM_VSCREENS 1 #else #if (NUM_VSCREENS <= 0) #error At least one screeen needs to be defined! #endif #endif #if (NUM_VSCREENS > 1) && (NUM_BUFFERS > 1) #error Virtual screens and multiple buffers are not allowed! #endif /* * * Public code * */ /* * * LCD_X_Config * * Purpose: * Called during the initialization process in order to set up the * display driver configuration. * */ void LCD_X_Config(void) {
// // At first initialize use of multiple buffers on demand // #if (NUM_BUFFERS > 1) GUI_MULTIBUF_Config(NUM_BUFFERS); #endif // // Set display driver and color conversion for 1st layer // GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0); // // Display driver configuration, required for Lin-driver // if (LCD_GetSwapXY()) {
LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS); LCD_SetVSizeEx(0, YSIZE_PHYS * NUM_VSCREENS, XSIZE_PHYS); } else {
LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS); LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS * NUM_VSCREENS); } LCD_SetVRAMAddrEx(0, (void *)VRAM_ADDR); // // Set user palette data (only required if no fixed palette is used) // #if defined(PALETTE) LCD_SetLUTEx(0, PALETTE); #endif // // Set custom functions for several operations to optimize native processes // // LCD_SetDevFunc(0, LCD_DEVFUNC_COPYBUFFER, (void(*)(void))CUSTOM_LCD_CopyBuffer); // LCD_SetDevFunc(0, LCD_DEVFUNC_COPYRECT, (void(*)(void))CUSTOM_LCD_CopyRect); // LCD_SetDevFunc(0, LCD_DEVFUNC_FILLRECT, (void(*)(void))CUSTOM_LCD_FillRect); // LCD_SetDevFunc(0, LCD_DEVFUNC_DRAWBMP_8BPP, (void(*)(void))CUSTOM_LCD_DrawBitmap8bpp); // LCD_SetDevFunc(0, LCD_DEVFUNC_DRAWBMP_16BPP, (void(*)(void))CUSTOM_LCD_DrawBitmap16bpp); } /* * * LCD_X_DisplayDriver * * Purpose: * This function is called by the display driver for several purposes. * To support the according task the routine needs to be adapted to * the display controller. Please note that the commands marked with * 'optional' are not cogently required and should only be adapted if * the display controller supports these features. * * Parameter: * LayerIndex - Index of layer to be configured * Cmd - Please refer to the details in the switch statement below * pData - Pointer to a LCD_X_DATA structure * * Return Value: * < -1 - Error * -1 - Command not handled * 0 - Ok */ int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
int r; switch (Cmd) {
case LCD_X_INITCONTROLLER: {
// // Called during the initialization process in order to set up the // display controller and put it into operation. If the display // controller is not initialized by any external routine this needs // to be adapted by the customer... // // ... TFTLCD_Init(); return 0; } case LCD_X_SETVRAMADDR: {
// // Required for setting the address of the video RAM for drivers // with memory mapped video RAM which is passed in the 'pVRAM' element of p // LCD_X_SETVRAMADDR_INFO * p; p = (LCD_X_SETVRAMADDR_INFO *)pData; //... return 0; } case LCD_X_SETORG: {
// // Required for setting the display origin which is passed in the 'xPos' and 'yPos' element of p // LCD_X_SETORG_INFO * p; p = (LCD_X_SETORG_INFO *)pData; //... return 0; } case LCD_X_SHOWBUFFER: {
// // Required if multiple buffers are used. The 'Index' element of p contains the buffer index. // LCD_X_SHOWBUFFER_INFO * p; p = (LCD_X_SHOWBUFFER_INFO *)pData; //... return 0; } case LCD_X_SETLUTENTRY: {
// // Required for setting a lookup table entry which is passed in the 'Pos' and 'Color' element of p // LCD_X_SETLUTENTRY_INFO * p; p = (LCD_X_SETLUTENTRY_INFO *)pData; //... return 0; } case LCD_X_ON: {
// // Required if the display controller should support switching on and off // return 0; } case LCD_X_OFF: {
// // Required if the display controller should support switching on and off // // ... return 0; } default: r = -1; } return r; } /* End of file /
/* * * LCD_X_DisplayDriver * * Purpose: * This function is called by the display driver for several purposes. * To support the according task the routine needs to be adapted to * the display controller. Please note that the commands marked with * 'optional' are not cogently required and should only be adapted if * the display controller supports these features. * * Parameter: * LayerIndex - Index of layer to be configured * Cmd - Please refer to the details in the switch statement below * pData - Pointer to a LCD_X_DATA structure * * Return Value: * < -1 - Error * -1 - Command not handled * 0 - Ok */ int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
int r; switch (Cmd) {
case LCD_X_INITCONTROLLER: {
// // Called during the initialization process in order to set up the // display controller and put it into operation. If the display // controller is not initialized by any external routine this needs // to be adapted by the customer... // // ... TFTLCD_Init(); return 0; } case LCD_X_SETVRAMADDR: {
// // Required for setting the address of the video RAM for drivers // with memory mapped video RAM which is passed in the 'pVRAM' element of p // LCD_X_SETVRAMADDR_INFO * p; p = (LCD_X_SETVRAMADDR_INFO *)pData; //... return 0; } case LCD_X_SETORG: {
// // Required for setting the display origin which is passed in the 'xPos' and 'yPos' element of p // LCD_X_SETORG_INFO * p; p = (LCD_X_SETORG_INFO *)pData; //... return 0; } case LCD_X_SHOWBUFFER: {
// // Required if multiple buffers are used. The 'Index' element of p contains the buffer index. // LCD_X_SHOWBUFFER_INFO * p; p = (LCD_X_SHOWBUFFER_INFO *)pData; //... return 0; } case LCD_X_SETLUTENTRY: {
// // Required for setting a lookup table entry which is passed in the 'Pos' and 'Color' element of p // LCD_X_SETLUTENTRY_INFO * p; p = (LCD_X_SETLUTENTRY_INFO *)pData; //... return 0; } case LCD_X_ON: {
// // Required if the display controller should support switching on and off // return 0; } case LCD_X_OFF: {
// // Required if the display controller should support switching on and off // // ... return 0; } default: r = -1; } return r; }
- GUIDRV_Template.c
添加自己的画点读点函数
在文件中找到_SetPixelIndex函数 画点函数
在注释下面添加自己的画点函数
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(x, y, 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 = LCD_ReadPoint(x, y); //PixelIndex = 0; } #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0) #undef xPhys #undef yPhys #endif return PixelIndex; } 中断处理
extern __IO uint32_t OS_TimeMS; void SysTick_Handler(void) { OS_TimeMS++; TimingDelay_Decrement(); } 主函数
#include "LED.h" #include "Systick.h" #include "USART.h" #include "GUI.h" #include "SDRAM.h" int main() { //系统定时器设置 Systick_Init(); //中断分组 2位抢占优先权,2位子优先级 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); //LED初始化 LED_Init(); //串口初始化 USART1_Init(); SDRAM_Init(); GUI_Init(); GUI_Clear(); GUI_DispStringAt("Hello World!",0,0); while(1) { LED_G = ~LED_G; Delay_ms(500); } } 优化
const GUI_DEVICE_API GUIDRV_Template_API = { // // Data // DEVICE_CLASS_DRIVER, // // Drawing functions // _DrawBitmap, _DrawHLine, _DrawVLine, _FillRect, _GetPixelIndex, _SetPixelIndex, _XorPixel, // // Set origin // _SetOrg, // // Request information // _GetDevFunc, _GetDevProp, _GetDevData, _GetRect, }; /* * * _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, PixelIndex); } } 画位图函数
/* * * _DrawBitmap */ static void _DrawBitmap(GUI_DEVICE * pDevice, int x0, int y0, int xSize, int ySize, int BitsPerPixel, int BytesPerLine, const U8 GUI_UNI_PTR * pData, int Diff, const LCD_PIXELINDEX * pTrans) {
int i; switch (BitsPerPixel) {
case 1: for (i = 0; i < ySize; i++) {
_DrawBitLine1BPP(pDevice, x0, i + y0, pData, Diff, xSize, pTrans); pData += BytesPerLine; } break; case 2: for (i = 0; i < ySize; i++) {
_DrawBitLine2BPP(pDevice, x0, i + y0, pData, Diff, xSize, pTrans); pData += BytesPerLine; } break; case 4: for (i = 0; i < ySize; i++) {
_DrawBitLine4BPP(pDevice, x0, i + y0, pData, Diff, xSize, pTrans); pData += BytesPerLine; } break; case 8: for (i = 0; i < ySize; i++) {
_DrawBitLine8BPP(pDevice, x0, i + y0, pData, xSize, pTrans); pData += BytesPerLine; } break; // // Only required for 16bpp color depth of target. Should be removed otherwise. // case 16: // for (i = 0; i < ySize; i++) {
// _DrawBitLine16BPP(pDevice, x0, i + y0, (const U16 *)pData, xSize); // pData += BytesPerLine; // } //可以直接用自己的画图函数 TFTLCD_DrawBmp16(x0, y0, pData, xSize, ySize); break; // // Only required for 32bpp color depth of target. Should be removed otherwise. // case 32: for (i = 0; i < ySize; i++) {
_DrawBitLine32BPP(pDevice, x0, i + y0, (const U32 *)pData, xSize); pData += BytesPerLine; } break; } }
OS的移植
这里以FreeRTOS为例
- 导入FreeRTOS头文件
- 定义互斥量信号量
- 完善函数
#include "GUI.h" /* FreeRTOS include files */ #include "FreeRTOS.h" #include "task.h" #include "semphr.h" /* * * Global data */ //static osMutexId osMutex; //static osSemaphoreId osSemaphore; static xSemaphoreHandle osMutex = NULL; static xSemaphoreHandle osSemaphore = NULL; /* * * Timing: * GUI_X_GetTime() * GUI_X_Delay(int) Some timing dependent routines require a GetTime and delay function. Default time unit (tick), normally is 1 ms. */ int GUI_X_GetTime(void) {
return ((int) xTaskGetTickCount()); } void GUI_X_Delay(int ms) {
vTaskDelay( ms ); } /* * * GUI_X_Init() * * Note: * GUI_X_Init() is called from GUI_Init is a possibility to init * some hardware which needs to be up and running before the GUI. * If not required, leave this routine blank. */ void GUI_X_Init(void) {
} /* * * GUI_X_ExecIdle * * Note: * Called if WM is in idle state */ void GUI_X_ExecIdle(void) {
} /* * * Multitasking: * * GUI_X_InitOS() * GUI_X_GetTaskId() * GUI_X_Lock() * GUI_X_Unlock() * * Note: * The following routines are required only if emWin is used in a * true multi task environment, which means you have more than one * thread using the emWin API. * In this case the * #define GUI_OS 1 * needs to be in GUIConf.h */ /* Init OS */ void GUI_X_InitOS(void) {
/* 创建互斥信号量 用于资源共享 */ osMutex = xSemaphoreCreateMutex(); configASSERT (osMutex != NULL); /* 创建二值信号量 用于事件触发 */ osSemaphore = xSemaphoreCreateBinary(); configASSERT ( osSemaphore != NULL ); } void GUI_X_Unlock(void) {
/* 给出互斥量 */ xSemaphoreGive(osMutex); } void GUI_X_Lock(void) {
if(osMutex == NULL) {
GUI_X_InitOS(); } /* 获取互斥量 */ xSemaphoreTake(osMutex, /* 互斥量句柄 */ portMAX_DELAY);/* 阻塞等待 */ } /* Get Task handle */ U32 GUI_X_GetTaskId(void) {
return ((U32) xTaskGetCurrentTaskHandle()); } void GUI_X_WaitEvent (void) {
/* 获取信号量 */ while(xSemaphoreTake( osSemaphore, /* 信号量句柄 */ portMAX_DELAY) != pdTRUE);/* 阻塞等待 */ } void GUI_X_SignalEvent (void) {
/* 给出信号量 */ xSemaphoreGive(osSemaphore); } /* * * Logging: OS dependent Note: Logging is used in higher debug levels only. The typical target build does not use logging and does therefor not require any of the logging routines below. For a release build without logging the routines below may be eliminated to save some space. (If the linker is not function aware and eliminates unreferenced functions automatically) */ void GUI_X_Log (const char *s) {
} void GUI_X_Warn (const char *s) {
} void GUI_X_ErrorOut(const char *s) {
}
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214363.html原文链接:https://javaforall.net
