主控MCU: STM32F103ZET6
STM32程序开发IDE: keil5
STM32程序风格: 采用寄存器方式开发,注释齐全,执行效率高,方便移植
硬件包含: 一块STM32F103ZET6开发板、一个3.5寸TFT电阻触摸显示屏(使用的是正点原子的3.5寸电阻触摸屏)
前言:STemwin图形界面库比较吃内存的,一般跑图形界面库都需要配一块SRAM,M3系列官方推荐频率是72MHZ(当前也是可以超频的),界面不是非常复杂,刷新要求不是特别高的情况下,跑起来还是不错的。
这篇文章主要讲解Stemwin的移植与基本使用。
下面示例图是为了讲解STemwin基本用法,做的界面两个例子。 QQ应用的界面完成之后加上网卡就可以完成局域网之间多个设备之间聊天了。
emWin是由德国SEGGER公司开发,可为图形LCD设计提供高级支持,极大简化了LCD设计。为恩智浦ARM微控制器用户免费提供的emWin图形库。
在国内做嵌入式系统的大部分都使用emwin,其简单来说就是一套图形库。
做电子硬件开发,常常要为设计一个良好的UI伤透脑筋,写很多的代码也不尽人意,还要不断调试,emwin正是解决这种用户界面需求的图形库,只要在你的设计中嵌入这种图形库,就能很方便使用里面的模块化设计,既能提高设计界面图形质量,还大大的减少开发时间。
SEGGER公司的产品
Segger微控制器股份有限公司开发与发布软件开发工具及ANSI C软件组件(中间件)给嵌入式系统使用并应用在许多工业应用中,如通信、医疗仪器、消费性电子产品、汽车工业及工业自动化设备。
拓展资料:
嵌入式系统无疑是当前最热门最有发展前途的IT应用领域之一。
嵌入式系统用在一些特定专用设备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时响应要求很高等。特别是随着消费家电的智能化,嵌入式更显重要。像我们平常见到的手机、PDA、电子字典、可视电话、VCD/DVD/MP3 Player、数字相机(DC)、数字摄像机(DV)、U-Disk、机顶盒(Set Top Box)、高清电视(HDTV)、游戏机、智能玩具、交换机、路由器、数控设备或仪表、汽车电子、家电控制系统、医疗仪器、航天航空设备等等都是典型的嵌入式系统。
Keil软件
Keil公司是一家业界领先的微控制器(MCU)软件开发工具的独立供应商。
Keil公司由两家私人公司联合运营,分别是德国慕尼黑的Keil Elektronik GmbH和美国德克萨斯的Keil Software Inc。Keil公司制造和销售种类广泛的开发工具,包括ANSI C编译器、宏汇编程序、调试器、连接器、库管理器、固件和实时操作系统核心(real-time kernel)。
Keil 官网虽然没有发布中文版本,但是Keil 系列软件却被中国80%以上的软硬件工程师使用,但凡与电子相关的专业,都会开始从单片机和计算机编程开始学习,而学习单片机自然会用到Keil 软件。国内由米尔科技、亿道电子、英倍特提供Keil 的销售和技术支持服务,他们是ARM公司合作伙伴,也是国内领先的嵌入式解决方案提供商。
说起UCGUI得先从UCOS说起,在国内做嵌入式系统的,开始入门OS的时候,大家应该都会选择uC/OS,主要是因为代码开源且资料众多。由于uC/OS的原因大家也一定接触了uC/GUI的嵌入式图形软件库。其实uC/Gui的核心代码并不是Micrium公司开发的,而是Segger公司为Micrium公司定制的图形软件库,当然也是基于Segger公司的emwin图形软件库开发的。所有说uC/GUI和emwin的使用方法没有区别。
在以前较旧的版本程序中uC/Gui的源代码是开源的(可以在网上能够找到),但是新版本的程序emWin和uC/gui只对用户提供库文件,是不开源的。
Segger 除了向Micrium公司提供定制的uC/GUI版本,还向其他的IC厂家提供定制服务,比如: 向ST 公司出售了emWin 的版权,从而ST公司也得到了定制版的emWin,然后改了名字叫 STemWin。当用户在 STM32 芯片上使用 emWin 软件库时,是不需要向 emWin 或 ST 公司付费的。还有NXP公司也使用了emWin的图形库,大家使用NXP芯片的时候同样也不需要支付费用。
总而言之,uC/GUI和STemWin都是 Segger 公司的 emWin 产品,而且它们的版本编号是统一的,如 uC/GUI 目前最新版本命名为uC-GUI V5.24, STemWin 最新版本命名为STemWin Library V5.24,emWin 最新版本则为 emWin V5.24,所以,要比较这三个软件库功能上的区别,只需要看它们的版本号就可以了。
在选择的时候,虽然功能上没有区别,但因为版权付费问题,在实际使用时就需要根据自己的平台来选择。如果我们使用的是 STM32 开发平台,自然我们选择的是STemWin;如果我们使用的是NXP的平台,我们就是用为NXP定制的emwim。
在使用特定的平台,我们也需要选择定制的emWin,在STemWin里有一个检测机制确定代码所运行的平台,若是 STM32 芯片,则运行正常,若非 STM32 芯片,就不能正常使用了。同样,NXP也是一样的机制。
如果使用的芯片没有授权emWin的版权,可以推荐使用UCGUI。
emWin官方下载地址:https://www.segger.com/emwin.html
STemWin官方下载地址:https://www.st.com/en/embedded-software/stm32cubef1.html
GCGUI官网下载地址:https://www.micrium.com/
很多产品需要人机交互,人机交互大多数是通过LCD来完成的,所以就需要我们在应用中设计LCD交互界面,简单的UI界面我们可以自己写代码完成,但是比较复杂、绚丽的界面自己来做就比较困难了。STemWin中提供了很多的控件,我们可以使用这些控件来完成复杂的界面设计。
emwin下载地址: https://www.segger.com/downloads/emwin/
在keil软件的安装目录下,自带了emwin的所有资料,适合NXP(恩智浦)单片机使用。
路径: \ARM\Segger\emWin
STemwin适合在ST意法半导体的芯片上使用,Stemwin的资料包可直接在ST官网上进行下载。
ST意法半导体官网首页地址: https://www.st.com
下面是下载的步骤截图:
移植之前,需要先准备一个带LCD屏驱动、触摸屏驱动的完整Keil工程。
(1) 在工程目录下创建一个ST_EMWIN文件夹,用于存放STEMWIN相关的文件
(2) 拷贝的目录
inc文件夹从下载的包里直接拷贝过来,不做任何修改。
Config文件夹里留下以下文件:
Lib目录下留下以下文件: (不带OS的库文件)
(3) 在keil软件里创建一个新的分组,用于存放STemwin文件。
(4) 添加头文件路径
GUIConf.h是STemwin的核心配置文件,主要配置操作系统、触摸屏、最大窗口的支持。
GUIConf.c文件配置STemwin运行时需要的内存,如果使用了SRAM外扩内存,可以将数组定义在外部的SRAM空间。
GUIDRV_Template.c文件是LCD屏的驱动模板文件,需要根据自己的LCD屏驱动进行修改。
主要修改的函数是: 画点函数、读点函数。
NT35310_Fill(x0,y0,x1,y1,LCD_COLORINDEX);
void LCD_X_Config(void)
{
GUI_DEVICE * pDevice;
pDevice = GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
//触摸屏校准参数设置
GUI_TOUCH_Calibrate(GUI_COORD_X,0,319,0,319);
GUI_TOUCH_Calibrate(GUI_COORD_Y,0,479,0,479);
//这两个函数在GUI.h文件的1292行定义
}
GUIDRV_Template_API 变量是在GUI.h的167行定义。
GUI_TOUCH_Calibrate函数是在GUI.h的
这4个函数原型在GUI.h文件的1404行声明。
在GUIDRV_Template.c文件下面增加这4个触摸屏的接口函数。
#include "touch_xpt2046.h"
void GUI_TOUCH_X_ActivateX(void) { //激活X
}
void GUI_TOUCH_X_ActivateY(void) { //激活Y
}
int GUI_TOUCH_X_MeasureX(void) { //测量X
TOUCH_ReadXY();
return touch.x;
}
int GUI_TOUCH_X_MeasureY(void) { //测量Y
TOUCH_ReadXY();
return touch.y;
}
触摸屏底层函数增加之后,再次编译。
这4个函数,在GUI_X.c文件里定义,需要将GUI_X.c文件添加到工程中。
GUI_X.c文件路径: \en.stemwin\STemWin_Library_V1.2.0\Libraries\STemWinLibrary532\OS\GUI_X.c
将GUI_X.c文件拷贝到工程目录下的ST_EMWIN\Config目录下。
在STemwin的GUI_X.c文件里,带有GUI_X_Delay()延时函数,该延时函数是通过OS_TimeMS变量来计算延时的时间,如果需要使用该延时函数,就需要在自己工程的硬件定时器里1ms的频率自增OS_TimeMS变量,提供时间基准。
需要使用触摸屏,就需要定期调用GUI_TOUCH_Exec()函数,每秒100次的频率调用。
进行GUI框架初始化之前,需要先开启CRC时钟校验。
/*获取触摸屏状态\设置光标位置*/
void Touch_Process(void)
{
GUI_PID_STATE STATE; //该变量为GUI触屏的x y位置存储坐标
GUI_TOUCH_GetState(&STATE); //获取触摸屏状态
if(STATE.Pressed == 1) //按下
{
GUI_CURSOR_SetPosition(STATE.x,STATE.y);//设置光标位置
GUI_CURSOR_Show(); //设置显示光标
}
}
运行效果如下:
SEGGER官方提供的DEMO代码,在ST意法半导体的官网上下载的包里没有提供,需要去SEGGER官方提供的emwin包里获取。在keil软件的安装目录下,有完整的emwin包,可以找到DEMO代码。
将GUIDemo文件夹全部拷贝到工程目录下,并将里面所有的.c文件加到工程中。
GUIBulider是emwin官方出的软件,每个版本的emwin都有其对应版本的。
GUIBulider软件,控件非常齐全,熟练使用 GUIBulider在使用emWin设计GUI界面的时候会起到事半功倍的效果,使用这款软件就不需要我们自己用C语言编写界面了,可以在 GUIBulider 中设计好界面,然后导出C程序,十分的方便。
GUIBulider生成的代码只是一个界面框架,程序执行的逻辑代码需要用户自己填充。
逻辑代码比如: 按下按键做什么,松开按键做什么等等,这些需要用户自己设计。
(1) 制作GBK中文字库
制作好的字库效果:
字库制作好之后,可以通过文件系统+SD将字库文件烧写到板载的W25Q64 FLASH里指定位置,方便后续调用。
(2) 制作ASCII 码字库
上面制作了GBK中文字库,这里还需要制作尺寸一样的ASCII码字库,方便显示与中文大小相同的英文字母和标点符号。
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
注意: 最前面有个空格。 一共95个数据。
存放到程序里的只能放 12号字体、16号字体、24号字体。 太大的字体Keil软件存放不了。
超出了24号的字体,可以像GBK中文字库一样存放到FLASH W25Q128里,使用的时候在去读取数据,这样就不会占用CPU本身的FLASH空间。
(3) 制作好的字库文件列表
(4) 添加ASCII码字库和GBK字库的支持
先将字库的必要文件添加到工程中: (如果用不到这么多字体可以自己添加要使用的大小)
#define GUI_FONTTYPE_PROP_USER \
GUIPROP_X_DispChar, \
(GUI_GETCHARDISTX*)GUIPROP_X_GetCharDistX, \
GUIMONO_GetFontInfo, \
GUIMONO_IsInFont, \
(GUI_GETCHARINFO *)0, \
(tGUI_ENC_APIList*)0
QQ登录界面(中文显示)
QQ登录框点击登录按钮之后登录成功的效果
GUI_SendKeyMsg()函数: 向一个指定的按键发送一个状态消息。
函数原型: void GUI_SendKeyMsg(int Key, int Pressed);
参数 | 含意 |
---|---|
Key | 可以是任何可扩展的 ASCII 字符(在 0x20 和 0xFF 之间)或者任何预定义的µC/GUI 信息码。 |
Pressed | 键的状态(参 GUI_StoreKeyMsg()) |
示例:
key=KEY_Scanf();
switch(key)
{
case 1:
GUI_SendKeyMsg(GUI_KEY_BACKTAB, 1);//选择上一个聚焦控件
break;
case 2:
GUI_SendKeyMsg(GUI_KEY_ENTER,1); //回车
break;
case 3:
GUI_SendKeyMsg(GUI_KEY_TAB, 1); //选择下一个聚焦控件
break;
case 4:
GUI_SendKeyMsg(GUI_KEY_SPACE,1); //空格键
break;
default:
/*发送按钮松开消息*/
GUI_SendKeyMsg(GUI_KEY_BACKTAB,0); //选择上一个聚焦控件
GUI_SendKeyMsg(GUI_KEY_ENTER,0); //回车
GUI_SendKeyMsg(GUI_KEY_TAB, 0); //选择下一个聚焦控件
GUI_SendKeyMsg(GUI_KEY_SPACE,0); //空格键
break;
}