zoukankan      html  css  js  c++  java
  • [STemWin教程入门篇]第二期:emWin5.xx的详细移植步骤

    转自: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);        
            }
    }

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

  • 相关阅读:
    [国嵌攻略][183][账号管理子系统设计]
    [国嵌攻略][182][Sqlite嵌入式数据库移植]
    [国嵌攻略][181][线程池技术优化]
    [国嵌攻略][180][加密传输优化]
    [国嵌攻略][179][OpenSSL加密系统]
    [国嵌攻略][178][网络安全传输系统框架搭建]
    [国嵌攻略][177][网络安全传输系统模型设计]
    [国嵌攻略][174][CGI快速入门-网页控制LED]
    [国嵌攻略][173][BOA嵌入式服务器移植]
    [转载]Architecture and framework
  • 原文地址:https://www.cnblogs.com/flyheart33/p/3601271.html
Copyright © 2011-2022 走看看