物联网智慧教室项目4

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章

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值