转自:http://bbs.armfly.com/read.php?tid=1545

重要说明:
(0)由于这个移植教程是去年过年的时候做的,用的是5.16,这就不再做个5.20的移植了,方法是一样的。
(1)emWin手册里面有这样一句话:“驱动接口的改变始于emWin V5。不再支持针对emWin V4 或更早版本开发的老显示驱动”。
(2)如果不使用V5以后版本的新特性,基本和以前的版本使用是一样的,也就是说,大家用V5以前版本实现的功能,直接升级
          到现有的版本,基本可以正常运行。
(3)尽管emWin提供了大部分屏的驱动,但是不能包含所有,这篇移植文档就因此而生。不管是emWin已经支持的,还是没有
提供支持的,均可采用这种方法。

(4)提供了一个非常好的触摸滤波方法,此方法可以有效的滤除飞点。

STM42F4+emWin5.16+3.0寸视频演示

STM42F4+emWin5.16+4.3寸视频演示

STM42F4+emWin5.16+7寸视频演示

一.移植前的准备工作
(1)MDK4.54版本里面的有emWin5.16的库,大家注意一下这个文件夹里面的emWin库。

可以看到支持M4的GUI库,所有就用这个库,大家都知道M4相对于M3,主要是增加了浮点运算,
但是emWin手册里面有这样一个说明。

手册里面明确的说明了emWin的库,绝对无浮点使用。所有如果使用M3的emWin库也是没有问题的。
(2)MDK要添加下面的LICENSE, 如果不添加是不能用emWin的库。

添加方法也很简单,用大家注册MDK时的-注-册-机就可以的,不贴全图了。

(3)要添加MDK对M4的浮点支持,添加方法也很简单,提供的例程里面就有,看一下就会了,这里不
再做说明了。
二.现在就可以开始移植工作了。
      主要添加下图所示的几个文件

下面就对这些文件进行详细的说明
(1) bsp_touch.c这个文件主要提供触摸的驱动函数,以便emWin中
GUI_TOUCH_X_MeasureX     GUI_TOUCH_X_MeasureY
两个函数的调用。
特别注意,这里改变触摸的滤波方法,以前用去点前几个点和后几个点,然后中间数值取平均的方法,效果并不理想,
不用有效的滤除飞点,这里使用一个新的方法。
1.1、在emWin里面使用使用触摸的中断方式,效果并不好,所以这里使用查询,查询此引脚的电平,这样可以避免不必要的调用
GUI_TOUCH_X_MeasureX
GUI_TOUCH_X_MeasureY
两个函数。
1.2、触摸滤波,主要是滤的是飞点,就应为这些飞点的存在,才使得触摸很不稳定。
下面的这个函数,大家应该很熟悉,就是滤除前几个点和后面几个点,然后中间几个点取平均
/* 读取次数  根据实际情况修改 */
#define XPT2046_READ_TIMES    5
/* 丢弃值  */
#define XPT2046_LOST_VAL      1
uint16_t TOUCH_DataFilter(uint8_t _ucCh)
{
uint16_t i, j;
uint16_t buf[XPT2046_READ_TIMES];
uint16_t usSum;
uint16_t usTemp;/* 读取READ_TIMES次数据 */
for(i=0; i < XPT2046_READ_TIMES; i++)
{
if (g_ChipID == IC_8875)
{
if(_ucCh == ADC_CH_X)
{
buf = RA8875_TouchReadX();
}
else
{
buf = RA8875_TouchReadY();
}
}
else
{
buf = TSC2046_ReadAdc(_ucCh);
}
}

/* 升序排列 */
for(i = 0; i < XPT2046_READ_TIMES - 1; i++)
{
for(j = i + 1; j < XPT2046_READ_TIMES; j++)
{
if(buf > buf[j])
{
usTemp = buf;
buf = buf[j];
buf[j] = usTemp;
}
}
}

usSum = 0;

/*求和 */
for(i = XPT2046_LOST_VAL; i < XPT2046_READ_TIMES - XPT2046_LOST_VAL; i++)
{
usSum += buf;
}
/*求平均 */
usTemp = usSum / (XPT2046_READ_TIMES - 2 * XPT2046_LOST_VAL);

return usTemp;
}

下面的这个函数就很重要了,要滤除飞点,就全靠它了。
/* 误差范围 根据实际情况调节误差范围 */
uint8_t ADC_ERR_RANGE = 5;
uint8_t TOUCH_ReadAdcXY(int16_t *_usX, int16_t *_usY)
{
uint16_t iX1, iY1;
uint16_t iX2, iY2;
uint16_t iX, iY;

iX1 = TOUCH_DataFilter(ADC_CH_X);
iY1 = TOUCH_DataFilter(ADC_CH_Y);
iX2 = TOUCH_DataFilter(ADC_CH_X);
iY2 = TOUCH_DataFilter(ADC_CH_Y);

iX = TOUCH_Abs(iX1 - iX2);
iY = TOUCH_Abs(iY1 - iY2);

/* 前后两次采样在+-ERR_RANGE内 */
if ((iX <= ADC_ERR_RANGE) && (iY <= ADC_ERR_RANGE))
{

if(g_ucGPIX == 1)
{
*_usY = (iX1 + iX2) / 2;
*_usX = (iY1 + iY2) / 2;
}
else
{
*_usX = (iX1 + iX2) / 2;
*_usY = (iY1 + iY2) / 2;
}

return 1;
}
else
{
return 0;
}
}
触摸的驱动就这些东西,详细的使用看例程级可以,然后在文件GUI_X_Touch_Analog.c里面调用就可以了。
int  GUI_TOUCH_X_MeasureX(void)
{
TOUCH_SCAN();
return(g_tTP.usAdcNowX);
}

int  GUI_TOUCH_X_MeasureY(void)
{
return(g_tTP.usAdcNowY);
}

(2) 下面的说明就很重要了,这个是实现emWin移植成功的关键。
在文件夹DisplayDriver有这三个文件,这里我们使用第一个。

打开这个文件,会发现里面的函数很面熟,是的,基本和UCGUI3.98里面的差不多,但是这个里面的功能更加全面。
2.1、如果不使用优化,直接提供一个打点和读点的函数就可以了,如果想优化一下,就继续往下看。
优化需要修改的函数有下面几个。
/*
********************************************************************
*
*       _DrawHLine
*
*******************************************************************
*/
static void _DrawHLine  (GUI_DEVICE * pDevice, int x0, int y,  int x1) {
  if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
    for (; x0 <= x1; x0++) {
      _XorPixel(pDevice, x0, y);
    }
  } else {
  #if emWin_Optimize   //这里使用了一个宏定义,是否使用优化
          //LCD8875_DrawHLine(x0, y, x1, LCD_COLORINDEX);
        s_ucRA8875BusyNow = 1;
        LCD_DrawLineH(x0, y, x1, LCD_COLORINDEX);
        s_ucRA8875BusyNow = 0;
  #else
    LCD_PIXELINDEX ColorIndex;
    ColorIndex = LCD__GetColorIndex();
    for (; x0 <= x1; x0++) {
      _SetPixelIndex(pDevice, x0, y, ColorIndex);
    }
  #endif        
  }        
}

/*
*************************************************************************
*
*       _DrawVLine, not optimized
*
*************************************************************************
*/
static void _DrawVLine  (GUI_DEVICE * pDevice, int x, int y0,  int y1) {
  if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
    for (; y0 <= y1; y0++) {
      _XorPixel(pDevice, x, y0);
    }
  } else {

#if emWin_Optimize
//                LCD8875_DrawVLine(x, y0, y1, LCD_COLORINDEX);
                s_ucRA8875BusyNow = 1;
                LCD_DrawLineV(x, y0, y1, LCD_COLORINDEX);
                s_ucRA8875BusyNow = 0;
        #else
                LCD_PIXELINDEX ColorIndex;
                ColorIndex = LCD__GetColorIndex();
            for (; y0 <= y1; y0++) {
              _SetPixelIndex(pDevice, x, y0, ColorIndex);
            }
        #endif
  }
}

/*
**************************************************************************
*
*       _FillRect
*
**************************************************************************
*/
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) 
{
#if emWin_Optimize

if (g_ChipID == IC_8875)
        {
                s_ucRA8875BusyNow = 1;
                BTE_SetTarBlock(x0, y0, y1-y0+1, x1-x0+1, 0);  /* 设置BTE位置和宽度高度 */
                BTE_SetOperateCode(0x0C);                               /* 设定BTE 操作码和光栅运算码  REG[51h] Bit[3:0] = 0Ch */
                RA8875_SetFrontColor(LCD_COLORINDEX);    /* 设置BTE前景色   */
                BTE_Start();                                                   /* 开启BTE 功能     */
                BTE_Wait();                                                  /* 等待操作结束     */
                s_ucRA8875BusyNow = 0;                
        }
        else
        {
                for (; y0 <= y1; y0++) 
                {
                        _DrawHLine(pDevice, x0, y0, x1);
                }                
        }

#else
        for (; y0 <= y1; y0++) 
        {
                _DrawHLine(pDevice, x0, y0, x1);
        }
#endif 
}

下面的这个函数优化很重要,要想窗口打开的快点,下面的必须优化!!!!!!!
/*
**************************************************************************
*
*       Draw Bitmap 16 BPP, not optimized
*
**************************************************************************
*/
static void _DrawBitLine16BPP(GUI_DEVICE * pDevice, int x, int y, U16 const GUI_UNI_PTR * p, int xsize) 
{
#if emWin_Optimize

//                RA8875_SetCursor(x,y);
//                RA8875_REG = 0x02;
//                for (;xsize > 0; xsize--,p++)
//                {
//                        RA8875_RAM = *p;
//                }
        s_ucRA8875BusyNow = 1;
        LCD_DrawHColorLine(x, y, xsize, (uint16_t *)p);
        s_ucRA8875BusyNow = 0;        
#else
        for (;xsize > 0; xsize--, x++, p++) 
        {
                _SetPixelIndex(pDevice, x, y, *p);
        }
#endif
}
(3)驱动函数写好以后,就是配置函数了,配置函数写好了,emWin就可以跑起来了。
         写贴一个官方的配置流程。
       
     下面就按照这个流程进行配置,如果没有说到的,看例程就可以。
/* Define the available number of bytes available for the GUI */
#define GUI_NUMBYTES  130000
/* Define the average block size */
#define GUI_BLOCKSIZE 0x80
为emWin分配动态内存
/*********************************************************************
*
*       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 */
        static U32 aMemory[GUI_NUMBYTES / 4];

/*  Assign memory to emWin */
        GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
        GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
}

然后就是最关键的LCD_X_Config,这里对7寸4.3寸 3.0寸都做了支持。  
/*
****************************************************************************
*
*       LCD_X_Config
*
* Purpose:
*   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 for 1st layer */
        GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0);

if (g_ChipID == IC_8875)
        {
                if (g_ucGPIX == 1)        /*         GPIX = 1  4.3  480x272 */
                {
                        /* Display driver configuration */
                        LCD_SetSizeEx    (0, 480, 272);
                        LCD_SetVSizeEx   (0, 480, 272);

/* Touch calibration */ 
                        GUI_TOUCH_Calibrate(GUI_COORD_X, 0, 479, 985,  50);
                        GUI_TOUCH_Calibrate(GUI_COORD_Y, 0, 271, 920,  100);
                }
                else         /*         GPIX = 0  7  800*480 */
                {
                        /* Display driver configuration */
                        LCD_SetSizeEx    (0, XSIZE_PHYS, YSIZE_PHYS);
                        LCD_SetVSizeEx   (0, VXSIZE_PHYS, VYSIZE_PHYS);
                //        LCD_SetVRAMAddrEx(0, (void *)VRAM_ADDR);

/* Touch calibration */
                //        GUI_TOUCH_SetOrientation(0);  
                        GUI_TOUCH_Calibrate(GUI_COORD_X, 0, XSIZE_PHYS - 1, GUI_TOUCH_AD_LEFT,  GUI_TOUCH_AD_RIGHT);
                        GUI_TOUCH_Calibrate(GUI_COORD_Y, 0, YSIZE_PHYS - 1, GUI_TOUCH_AD_TOP,  GUI_TOUCH_AD_BOTTOM);                
                }
        }
        else
        {
                LCD_SetSizeEx    (0, 400, 240);
                LCD_SetVSizeEx   (0, 400, 240);

/* Touch calibration */ 
                GUI_TOUCH_Calibrate(GUI_COORD_X, 0, 399, 300, 3600);
                GUI_TOUCH_Calibrate(GUI_COORD_Y, 0, 239, 273,  3671);        
        }
}

大家根据自己的屏,配置屏的大小和触摸校准就可以了。到这里移植就算结束了。

[STemWin教程入门篇]第二期:emWin5.xx的详细移植步骤的更多相关文章

  1. [STemWin教程入门篇] 第一期:emWin介绍

    转自:http://bbs.armfly.com/read.php?tid=1544 SEGGER公司介绍 了解emWin之前,先了解一下SEGGER这家公司,了解生产商才能对emWin有更加全面的认 ...

  2. CE修改器使用教程 [入门篇]

    Cheat Engine 一般简称CE,是一个开放源代码的作弊软件,其功能包括:内存扫描.十六进制编辑器.调试工具,Cheat Engine 自身附带了外挂制作工具,可以用它直接生成外挂工具,CE可以 ...

  3. JqueryEasyUI教程入门篇

    什么是jQueryEasyUI? JqueryUI是一组基于jQuery的UI插件集合 学习jQueryEasyUI的条件? 必须掌握Jquery的基本语法知识 jQueryEasyUI的特点? 1. ...

  4. [转]JqueryEasyUI教程入门篇

    什么是jQueryEasyUI? JqueryUI是一组基于jQuery的UI插件集合 学习jQueryEasyUI的条件? 必须掌握Jquery的基本语法知识 jQueryEasyUI的特点? 1. ...

  5. OpenCV学习教程入门篇&lt;一、介绍&gt;

    OpenCV,是Inter公司开发的免费开源专门因为图像处理和机器视觉的C/C++库,英文全称是Open Source Computer Vision. 1. 可视化语言Matlab与OpenCV都能 ...

  6. shell教程<入门篇>

    由于我平时的工作环境是linux,所以无可避免的经常使用命令行模式和shell脚本,而且有些命令行每天都要输好多遍,比如ssh登录之类的,所以干脆把平时常用的命令都写成脚本文件,所以特意开了一个she ...

  7. 转:jQuery LigerUI 使用教程表格篇(3) 复选框、多表头、分组、汇总和明细

    阅读目录 复选框 多表头 分组 汇总 明细 复选框 grid可以设置复选框模式进行多选,只需要简单的配置 checked:true 获取选中行 如果要获取选中的行,可以用getSelecteds方法: ...

  8. SQLAlchemy 教程 —— 基础入门篇

    SQLAlchemy 教程 -- 基础入门篇 一.课程简介 1.1 实验内容 本课程带领大家使用 SQLAlchemy 连接 MySQL 数据库,创建一个博客应用所需要的数据表,并介绍了使用 SQLA ...

  9. Android Studio2.0 教程从入门到精通Windows版 - 入门篇

    http://www.open-open.com/lib/view/open1468121363300.html 本文转自:深度开源(open-open.com)原文标题:Android Studio ...

随机推荐

  1. Union比or快 Using UNION is faster when it comes to cases like scan two different column。

    problem: 595. Big Countries A country is big if it has an area of bigger than 3 million square km or ...

  2. 题解 P1017 【进制转换】

    我赶jio这个题难道是让我们写快写? 不管了,赶紧把咕咕咕了一万年的题解写出来. 这个题就是考察负进制和在mod意义下的除法运算的基础运算. (其实也没多大问题) 首先我们先假设一个原始数据\(num ...

  3. STM32几个IO的工作模式

    浮空,顾名思义就是浮在空中,上面用绳子一拉就上去了,下面用绳子一拉就沉下去了.  开漏,就等于输出口接了个NPN三极管,并且只接了e,b. c极 是开路的,你可以接一个电阻到3.3V,也可以接一个电阻 ...

  4. 测开之路二十六:Flask基础之最小web程序

    Flask中文文档:http://docs.jinkan.org/docs/flask/ 安装Flask库 选端口号的一种方法(避免和别人选的端口冲突,小于1024的时候重新选) 最小web程序 用1 ...

  5. win7系统 无线路由关闭了ssid广播 我手动设置了SSID和密码仍然连接不上

    http://zhidao.baidu.com/link?url=KwDGWPc67avpj2OUPg5UqvtqE_80R80P3xzhNIRI1_X5WnSLG7PLEpybb4TnzDAYAB6 ...

  6. Nginx的作用详解

    Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器.基于REST架构风格,以统一资源描述符(Unifor ...

  7. Linux崩溃时启动脚本获取进程相关信息

    编写test.cpp #include <stdlib.h> #include <stdio.h> #include <exception> #include &l ...

  8. PAT_A1071#Speech Patterns

    Source: PAT A1071 Speech Patterns (25 分) Description: People often have a preference among synonyms ...

  9. upc组队赛15 Lattice's basics in digital electronics【模拟】

    Lattice's basics in digital electronics 题目链接 题目描述 LATTICE is learning Digital Electronic Technology. ...

  10. 伪造请求头向url传递参数爬取百度默认翻译

    from urllib import request,parse import json # 翻译函数 def fanyi(msg): #参数封装 data = { "kw": c ...