首先得说一下为什么要用STemwin;很多人搞嵌入式的同志应该都想有一个自己的开发环境,每个功能每个模块都自己写;但是到最后发现无从下手,写出来的代码效率也并不高,因为脑袋里就没有这些模块或者功能运行的模式。就像很多人说的“你再怎么写,也超不过现有的成熟技术,除非你学会了,在做一些升华”。
STemWin在ST官网上是停止更新的了,最新的STemwin都不含在了stm32cube里面了。不过区别也不大,移植就用5.22版本,硬件用的是F407(后续会更新F439的移植于优化,主要不同在于有了SDRAM STemwin的内存空间可以做到很大,而且LCD的数据传输F439有LCD接口和LCD的专属DMA通道,性能肯定比F407快很多)。
第一步:软件包下载:官方下载地址:http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stemwin.zip
第二部:STM32 DSP包下载名字叫做STSW-STM32065,有利于STemwin的内部计算速度。官方下载地址:
整个需要改动的的文件分别是:
GUIConf.c ----->分配GUI的内存池,根据自己平台来分配
GUIDRV_Template.c----->点,线,面,图,的基本LCD操作函数,这个是我们移植和优化的重点
LCDConf_FlexColor_Template.c--->涉及到LCD的尺寸与显示设备属性的声明,这个也是重点。
GUI_X.c-->无操作系统外部依赖配置(就是程序心跳,时钟OS_TimeMS)
GUI_XOS.c-->有操作系统外部依赖设置。(时钟,信号量,邮箱)
新建LCD_Conf.h-->可以为空,但是必须要有这个文件
GUI的配置也就是需要这几个文件,STemWin522_CM4_Keil.lib用于无操作系统,STemWin522_CM4_OS_Keil.lib用于操作系统
这次是以无操作系统版本修改;修改前必须完成LCD的驱动代码调试,这样才能进行GUI的移植。
修改的重点在于三个点:
第一:GUI_X.c,GUI时钟信号OS_TimeMS的驱动,通常用sysTick为之提供毫秒级的时钟。
第二:LCDConf_FlexColor_Template.c,LCD的尺寸与显示设备属性的声明
第三:GUIDRV_Template.c,画,点,面,图,的基本LCD操作函数嵌入。
上边三个问题解决基本上GUI就可以显示出来了。
第一点:
首先我们打开GUIConf.h
确保 GUI_OS (0) ;因为不用操作系统
其次我们得打开系统sysTick的功能:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
SysTick_Config(21000);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//(168M/8)
产生毫秒中断,在stm32f4xx_it.c中加入
#include "gui.h"
extern __IO int32_t OS_TimeMS;
void SysTick_Handler(void)
{
OS_TimeMS ++;
}
这样GUI的时钟源就解决了
第二点:
这一步就是选择用STemwin自带的LCD的驱动还是用自己的API函数,这个选择在void LCD_X_Config(void) 函数中体现;
用自己的LCD API函数就只保留void LCD_X_Config(void) 和LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData);
void LCD_X_Config(void) 默认用的是自带驱动函数这个地修改:
void LCD_X_Config(void) {
GUI_DEVICE * pDevice;
//
// Set display driver and color conversion
//
pDevice = GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_565, 0, 0);//声明用什么函数接口驱动LCD,还有一个就是LCD的像素格式GUIDRV_Template_API在GUIDRV_Template.c中定义。
//
// Display driver configuration, required for Lin-driver
//
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS); //设置LCD分辨率
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS); //设置LCD显示分辨率,这个可以动态修改,用于屏幕的横竖反转。
}
LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData)这个函数可以把我们的LCD初始化,开关函数加进去,以自己的系统为准,有的系统在GUI启动之前就得初始化。
{
int r;
(void) LayerIndex;
(void) pData;
switch (Cmd) {
case LCD_X_INITCONTROLLER: {
//初始化函数
return 0;
};
case LCD_X_OFF:{
//关闭显示
return 0;
};
case LCD_X_ON:{
//打开显示
return 0;
};
default:
r = -1;
}
return r;
}
第三点:
这一步我们需要LCD的驱动代码;
分别修改GUIDRV_Template.c中的:
//画点函数
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex)
{
//自己的画点函数
}
//读点函数
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y)
{
unsigned int PixelIndex;
PixelIndex = //自己的读点函数
return PixelIndex;
}
//填充函数
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1)
{
LCD_PIXELINDEX PixelIndex;
int x;
PixelIndex = LCD__GetColorIndex();
//自己的填充函数
}
//16bit数据划线函数
static void _DrawBitLine16BPP(GUI_DEVICE * pDevice, int x, int y, U16 const GUI_UNI_PTR * p, int xsize)
{
//自己划线或者开窗函数,
//如果LCD可以直接定点输入,先定点在循环输入颜色即可
例如:LCD_SetCursor(x, y);(确保自己的LCD光标输入不影响LCD的输入窗口,如果影响就用开窗口函数)
for (;xsize > 0; xsize--, x++, p++)
{
LCDADDR->LCD_RAM = *p;
}
}
修改好后GUI就可以正常的运行了,代码优化主要是在GUIDRV_Template.c中,那些基础函数需要自己根据自己LCD去优化,主要是消除代码冗余,原生的驱动,都是靠打点函数实现的线,面,图函数。
我的没有优化输入点速度只有70几万点美妙,优化后速度到140多万基本提速一陪。
之后会更新有操作系统下的修改。