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);        
            }
    }

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

  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/flyheart33/p/3601271.html
Copyright © 2011-2022 走看看