D4emWin图形界面库
4.1图形用户界面(GUI)编程介绍
GUI开发流程
emWin--GUI库
emWin应用场景
emWin介绍
STemWin
emWin开发流程
LCD怎么驱动
常见的TFT-LCD屏
两种TFT-LCD驱动接口
LCD驱动程序
#ifndef __LCD_H__
#define __LCD_H__
#include "stm32f4xx_hal.h"
void lcd_clear(uint16_t Color);
void lcd_init(void);
void write_data_Prepare(void);
unsigned short lcd_read_gram(unsigned int x,unsigned int y);
void LCD_DrawPoint(uint16_t xsta, uint16_t ysta, uint16_t color);
void LCD_ShowString(uint16_t x0, uint16_t y0, uint8_t *pcStr, uint16_t PenColor, uint16_t BackColor);
void LCD_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t colour);
#endif
4.2emWin移植上(电阻屏)
(一)STemWin结构框架
CubeMx/computing/打开CRC
移植:关注lexColor
(二)获取STemWin源码文件
STemWin默认在STM32CUBEMX文档下
例如D:qianrishiruanjian\STM32Cube\Repository\STM32Cube_FW_F4_V1.24.3Middlewares\ST\STemWin
(三)emWin移植到项目工程
1. 复制STemWin源码到项目工程中
工程目录:SmartClassRoom\Middlewares\Third_Party\STemWin
2. 在keil工程中添加相关文件
1. 新建工作组:Middlewares/STemWin
2. 添加需要编译的C和库文件
| 文件名称 | 文件描述 |
| ---------------------------- | -------------------------------------------- |
| GUI_X_OS.c | OS支持文件,不需要修改 |
| GUIConf.c | GUI配置文件,主要用于GUI内存块初始化 |
| GUIDRV_Template.c | GUI驱动模块,主要针对LCD操作接口 |
| LCDConf_FlexColor_Template.c | GUI显示配置文件,主要用于LCD参数配置,初始化 |
| GUI_X_Touch_Analog.c | 需要自己单独定义,用于触摸笔驱动 |
| STemWin_CM4_OS_wc16_ot.a | 基于Cortex-M4驱动库,STemWin源码不开放 |
STemWin/lib/.....a
3. 修改库文件格式(keil默认不识别.a文件格式,需要我们手动配置)
打开option
(四)移植lcd和touch驱动文件
看4.3下面
4.3mWin移植下(电阻屏)
(一)emWin LCD驱动适配
修改GUIConf.c
指定分配内存
(1)添加宏
(2) 修改GUI_X_Config函数
#include "GUI.h"
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
//
// Define the available number of bytes available for the GUI
//
#define GUI_NUMBYTES (512*1024) //定义外部存储器大小
#define GUI_BLOCKSUZE (0X80) //定义最小内存库操作大小
#define SRAM_BANK_ADDR ((U32)0x68000000) //FSMC->SRAM定义外部存储器首地址
/*********************************************************************
*
* 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
//
volatile U32* aMemory = (volatile U32*)(SRAM_BANK_ADDR);
//
// Assign memory to emWin
//分配GUI存储器首地址及最小操作内存块大小
GUI_ALLOC_AssignMemory((void *)aMemory, GUI_NUMBYTES);
//设置存储块大小
GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSUZE);
//
// Set default font
//
GUI_SetDefaultFont(GUI_FONT_32_1);
}
修改GUIDRV_Template.c
添加lcd.c里实现画点和读点函数
添加头文件#include "lcd.h"
LCD_Fast_DrawPoint(x,y,PixelIndex);
PixelIndex = lcd_read_gram(x,y);
/*********************************************************************
*
* _SetPixelIndex
*
* Purpose:
* Sets the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
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
//添加lcd画点接口
LCD_Fast_DrawPoint(x,y,PixelIndex);
// TBD by customer...
//
}
#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
#endif
}
/*********************************************************************
*
* _GetPixelIndex
*
* Purpose:
* Returns the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
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
//添加lcd读取点接口
PixelIndex = lcd_read_gram(x,y);
// TBD by customer...
//
PixelIndex = 0;
}
#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
#endif
return PixelIndex;
}
修改LCDConf_FlexColor_Template.c
1. 修改液晶屏尺寸
2. 关联驱动API
3. 添加触摸校准
4. 添加lcd和Touch初始化
#include "GUI.h"
#include "GUIDRV_FlexColor.h"
#include "lcd.h"
#include "Touch.h"
/*********************************************************************
*
* Layer configuration (to be modified)
*
**********************************************************************
*/
//
// Physical display size
//
#define XSIZE_PHYS 800// 屏幕X坐标长度
#define YSIZE_PHYS 480// 屏幕Y坐标长度
/*********************************************************************
*
* Configuration checking
*
**********************************************************************
*/
#ifndef VXSIZE_PHYS
#define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef VYSIZE_PHYS
#define VYSIZE_PHYS YSIZE_PHYS
#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 GUICC_565
#error Color conversion not defined!
#endif
#ifndef GUIDRV_FLEXCOLOR
#error No display driver defined!
#endif
/*********************************************************************
*
* Public functions
*
**********************************************************************
*/
/*********************************************************************
*
* LCD_X_Config
*
* Function description:
* Called during the initialization process in order to set up the
* display driver configuration.
*
*/
void LCD_X_Config(void) {
// Set display driver and color conversion
//创建显示驱动API,并关联将使用的颜色转换程序
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, VXSIZE_PHYS, VYSIZE_PHYS);
//
// 触摸笔校准
GUI_TOUCH_Calibrate(GUI_COORD_X, 0,799, 0,799);
GUI_TOUCH_Calibrate(GUI_COORD_Y, 0,479, 0,479);
}
/*********************************************************************
*
* LCD_X_DisplayDriver
*
* Function description:
* 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;
(void) LayerIndex;
(void) pData;
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...
//
// ...
//添加lcd初始化
lcd_init();
//添加触摸屏初始化
tp_dev.init();
return 0;
}
default:
r = -1;
}
return r;
}
LCDConf_ FlexColor Template.c
添加GUI_X_Touch_Analog.c
#include "GUI.h"
#include "Touch.h"
void GUI_TOUCH_X_ActivateX(void)
{
}
void GUI_TOUCH_X_ActivateY(void)
{
}
//获取X坐标AD值
int GUI_TOUCH_X_MeasureX(void)
{
return tp_read_value_x();
}
//获取Y坐标AD值
int GUI_TOUCH_X_MeasureY(void)
{
returntp_read_value_y();
}
(二) emWin移植测试程序编写
测试程序编写
/* USER CODE BEGIN Header_Touch_Task */
/**
* @brief Function implementing the TouchTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Touch_Task */
void Touch_Task(void const * argument)
{
GUI_PID_STATE State;
// /* init code for FATFS */
// MX_FATFS_Init();
// /* init code for LWIP */
// MX_LWIP_Init();
GUI_Init();
GUI_SetBkColor(GUI_BLUE);
GUI_SetFont(GUI_FONT_32_1);
GUI_SetColor(GUI_YELLOW);
GUI_Clear();
GUI_PID_STATE State;
/* Infinite loop */
for(;;)
{
//执行触摸笔检测
GUI_TOUCH_Exec();
//获取触摸笔状态值
GUI_TOUCH_GetState(&State);
//是否按下
if(State.Pressed){
//打印触摸笔坐标信息
GUI_DispStringAt("X:",0,0);
GUI_DispDecAt(State.x,32,0,4);
GUI_DispStringAt("Y:",0,28);
GUI_DispDecAt(State.y,32,28,4);
}
osDelay(10);
}
/* USER CODE END Touch_Task */
}
测试结果
当触摸笔按下时,显示X(0-480)和Y(0-272)坐标信息
补充:电容屏驱动移植
一驱动移植
2.开启宏定义
全局搜索: INCLUDE_vTaskDelayUntil
在delay.c里面
3添加应用代码测试
在任务中添加内容:freeRTOS.c
添加头文件#include "lcd.h"
#inckude "touch.h"
Touch_Task()
{
char buf []= "hello world";
//LCD初始化
LCD_Init();
//触摸屏初始化
tp_dev.init();
//显示字符串
LCD_ShowString(0,0,sizeof( buf)*24,24,24,(uint8_t *)buf);
LCD_DrawRectangle(100,100,300,300);
/* Infinite loop */
for(;;)
{
//扫描触摸屏
tp_dev.scan(0);
//判断是否按下
if(tp_dev.sta & TP_PRES_DOWN)
{
printf("x = %d y = %d\r\n",tp_dev.x[0],tp_dev.y[0]);
}
}
osDelay(20);
}
4.4emWin开发环境搭建
开发环境介绍
CodeBlocks
GUIBuilder
CubeMx/STM32Cube_FW_F4_V1.23.0/Middlewares/ST/STemWin/Software里面有需要的工具
Simulation(模拟器)
emwin Simulation(模拟器)
仿真模拟器是在window开发环境下的C工程,可以通过VC6或者codeblockd IDE环境下进行开发仿真
1. 下载地址
https://www.segger.com/downloads/emwin/
2. 添加工程到codeblockd
1. 打开外部工程
2. 选择.cbp文件
2. 添加工程到codeblockd
1. 点击编译运行按钮
2. 生成模拟器
GUIBuilder制作界面
界面添加到模拟器
修改模拟器原始工程
1. 把无用的代码移除工程
2. 添加WindowDLG.c到工程中
1. 首先复制WindowDLG.c到SeggerEval_WIN32_MSVC_MinGW_GUI_V544\Application目录下。
2. 添加WindowDLG.c到工程中
3. 选择Application工程目录,新建mainTask.c
4. 在mainTask.c添加代码
#include "dialog.h"//包含window对话框 头文件
void MainTask(void)
{
GUI_Init(); //初始化emWin
CreateWindow(); //创建窗体,父窗体是桌面背景
while(1) {GUI_Delay(20);} //调用GUI_Delay函数延时20MS(最终目的是调用GUI_Exec()函数)
}
4.5emWin运行原理分析
emWin使用说明书
emWin初始化
执行模型
时间调度
指针输入设备
4.6emWin应用编程方法
GUIBuilder
emWin中文手册第17章
对话框
emWin中文手册第16章
窗口管理器
emWin中文手册第14章
窗口对象
emWin中文手册第15章