基于STM32emWin532版本的移植
移植前提
1、下载所需源码
下载地址
下载完成后目录结构如下(demo目录来自CubeMAX的拷贝):重点关注Config
、Lib、OS
文件夹
2、直接拷贝Cubemx的STemwin
看到仓库地址路径信息,打开它
文件说明
目录/文件名 | 说明 |
---|---|
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的驱动调试
移植
在项目工程目录增加以下文件夹及文件
配置单次图像刷写最大允许字节
GUIConf.c中配置:
配置驱动API接口及屏幕属性
LCDConf_FlexColor_Template.c配置实现画点函数等API接口选择依据液晶芯片IC型号
#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
硬件启动定时器或者直接使用systick1ms中断,本例使用定时器
注意需要包含头文件引用:#include "GUI.h"
依据操作系统增加修改以下代码,本例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型
否则无法编译
测试代码
常用颜色及格式转换
/*常用转换*/
#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);
}