本帖最后由 硬汉Eric2013 于 2015-3-16 11:13 编辑
2.3 STemWin的裸机移植2.3.1 工程中添加的文件 添加如图所示的几个文件:
这几个文件从上往下依次进行一下简单的说明: 1. bsp_tft_lcd.c, LCD_RA887, LCD_SPFD5420.c是用户要实现的TFT驱动文件。 2. bsp_touch.c是触摸文件,也是用户要实现的。 3. GUIDRV_Template.c文件在ST官方提供的STemWin包里面没有,需要在MDK的安装目录里面找。 比如在MDK4.73安装目录中查找位置是:C:Keil4.73ARMSeggeremWinSampleDisplayDriver
4. 上面MDK工程目录中GUI_X中的几个文件在MDK安装目录和STemWin软件包中都有: Ø STemWin软件包中路径如下:STemWin_Library_V1.1.2LibrariesSTemWinLibrary522OS,只是STemWin软件包中相关文件比较少。 Ø MDK4.73安装目录中的如下路径中:C:Keil4.73ARMSeggeremWinSampleGUI_X,这里文件夹里面的内容比较全。 5. GUI和LCD配置文件所在位置: MDK4.73安装目录:C:Keil4.73ARMSeggeremWinSampleConfig STemWin软件包:STemWin_Library_V1.1.2LibrariesSTemWinLibrary522Config 6. GUI/DEMO中的函数需要用户实现,简单的写个程序即可。 7. GUI/Lib里面是emWin,所在位置 MDK4.73安装目录:C:Keil4.73ARMSeggeremWinLib STemWin软件包:STemWin_Library_V1.1.2LibrariesSTemWinLibrary522Lib 2.3.2 触摸屏滤波的实现 这里提供了一种有效的滤波方法。具体函数在bsp_touch.c这个文件里面,得到触摸数值后供emWin中的函数GUI_TOUCH_X_MeasureX 和GUI_TOUCH_X_MeasureY两个函数的调用。 特别注意这里改变触摸的滤波方法,以前的时候大家都是采用舍弃触摸数值的前几个点和后几个点,然后中间数值取平均的方法,效果并不理想,因为这种方法不能有效的滤除飞点,这里提供一个新的方法。1. 在STemWin里面使用触摸的中断方式,效果并不好,所以这里使用查询,查询此引脚的电平,这样可以避免不必要的读取触摸数据。 2. 触摸滤波,主要滤的是飞点,正是因为这些飞点的存在,才使得触摸很不稳定。 下面的这个函数,大家应该很熟悉,就是滤除前几个点和后面几个点,然后中间几个点取平均
- /*
- *********************************************************************************************************
- * 函 数 名: TOUCH_DataFilter
- * 功能说明: 读取一个坐标值(x或者y)
- * 连续读取XPT2046_READ_TIMES次数据,对这些数据升序排列,
- * 然后去掉最低和最高XPT2046_LOST_VAL个数,取平均值
- * 形 参:无
- * 返 回 值: 读到的数据
- *********************************************************************************************************
- */
- /* 读取次数 */
- #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[i] = RA8875_TouchReadX();
- }
- else
- {
- buf[i] = RA8875_TouchReadY();
- }
- }
- else
- {
- buf[i] = TSC2046_ReadAdc(_ucCh);
- }
- }
- /* 升序排列 */
- for(i = 0; i < XPT2046_READ_TIMES - 1; i++)
- {
- for(j = i + 1; j < XPT2046_READ_TIMES; j++)
- {
- if(buf[i] > buf[j])
- {
- usTemp = buf[i];
- buf[i] = buf[j];
- buf[j] = usTemp;
- }
- }
- }
- usSum = 0;
-
- /*求和 */
- for(i = XPT2046_LOST_VAL; i < XPT2046_READ_TIMES - XPT2046_LOST_VAL; i++)
- {
- usSum += buf[i];
- }
- /*求平均 */
- usTemp = usSum / (XPT2046_READ_TIMES - 2 * XPT2046_LOST_VAL);
-
- return usTemp;
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TOUCH_ReadAdcXY
- * 功能说明: 连续2次读取触摸屏IC,且这两次的偏差不能超过
- * ADC_ERR_RANGE,满足条件,则认为读数正确,否则读数错误.
- * 该函数能大大提高准确度
- * 形 参:x,y:读取到的坐标值
- * 返 回 值: 0,失败;1,成功
- *********************************************************************************************************
- */
- /* 误差范围 */
- 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))
- {
- *_usX = (iX1 + iX2) / 2;
- *_usY = (iY1 + iY2) / 2;
-
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TOUCH_Scan
- * 功能说明: 触摸板事件检测程序。该函数被周期性调用,每ms调用1次. 见 bsp_Timer.c
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TOUCH_SCAN(void)
- {
- uint8_t s_invalid_count = 0;
- if(TOUCH_PressValid == 0)
- {
- while(!TOUCH_ReadAdcXY(&g_tTP.usAdcNowX, &g_tTP.usAdcNowY)&&s_invalid_count < 20);
- {
- s_invalid_count++;
- }
- if(s_invalid_count >= 20)
- {
- g_tTP.usAdcNowX = -1;
- g_tTP.usAdcNowY = -1;
- }
- }
- else
- {
- g_tTP.usAdcNowX = -1;
- g_tTP.usAdcNowY = -1;
- }
- }
复制代码
触摸的驱动就这些东西,详细的使用看例程级可以,然后在文件GUI_X_Touch_Analog.c里面调用就可以了。
- #include "GUI.h"
- #include "LCD_RA8875.h"
- #include "bsp_touch.h"
-
- void GUI_TOUCH_X_ActivateX(void)
- {
-
- }
-
- void GUI_TOUCH_X_ActivateY(void)
- {
-
- }
-
- int GUI_TOUCH_X_MeasureX(void)
- {
- TOUCH_SCAN();
- return(g_tTP.usAdcNowX);
- }
-
- int GUI_TOUCH_X_MeasureY(void)
- {
- return(g_tTP.usAdcNowY);
- }
复制代码
2.3.3 底层驱动接口函数(GUIRV_Template) STemWin的底层驱动函数也很简单,用户只需提供打点和读点函数即可。但是这种没有经过优化的移植方式非常的影响STemWin的实际性能。这里就针对RA8875说一下需要优化的地方。 l 画水平线的函数
- /*********************************************************************
- *
- * _DrawHLine
- */
- static void _DrawHLine (GUI_DEVICE * pDevice, int x0, int y, int x1) {
- // LCD_PIXELINDEX ColorIndex;
-
- if (GUI_pContext->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
- }
- }
复制代码
l 画垂直线的函数
- /*********************************************************************
- *
- * _DrawVLine
- */
- static void _DrawVLine (GUI_DEVICE * pDevice, int x, int y0, int y1) {
- // LCD_PIXELINDEX ColorIndex;
-
- if (GUI_pContext->DrawMode & LCD_DRAWMODE_XOR) {
- for (; y0 <= y1; y0++) {
- _XorPixel(pDevice, x, y0);
- }
- } else {
- #if emWin_Optimize
- 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
- }
- }
复制代码
l 矩形填充函数
- /*********************************************************************
- *
- * _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
- }
复制代码
l 绘制16BPP的函数
- /*******************************************************************************************************
- *
- * 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
- 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
- }
复制代码
l 这里要根据实际的情况进行填写,不能填错,要不系统无法启动。
- /*********************************************************************
- *
- * _GetDevData
- */
- static void * _GetDevData(GUI_DEVICE * pDevice, int Index) {
- GUI_USE_PARA(pDevice);
- #if GUI_SUPPORT_MEMDEV
- switch (Index) {
- case LCD_DEVDATA_MEMDEV:
- // TBD: Has to be adapted to the right memory device depending on the used color depth!
- return (void *)&GUI_MEMDEV_DEVICE_16;
- }
- #else
- GUI_USE_PARA(Index);
- #endif
- return NULL;
- }
复制代码
优化好上面四个地方即可。 2.3.4 系统函数配置 STemWin的底层驱动做好以后,就可以进行GUI和LCD的配置工作,这个是官方提供的配置流程:
1. GUI的配置 主要是配置STemWin所需的动态内存,下面的配置方式支持使用芯片内部存储器也支持使用外部存储器(比如:SRAM,SDRAM),使用外部存储器的话,一定要记得初始化相应器件。
- ----------------------------------------------------------------------
- File : GUIConf.c
- Purpose : Display controller initialization
- ---------------------------END-OF-HEADER------------------------------
- */
- #include "GUI.h"
- #include "bsp.h"
-
- /*
- **********************************************************************
- *
- * Defines
- *
- **********************************************************************
- */
-
- /* Define the available number of bytes available for the GUI */
- //#define GUI_NUMBYTES (1024*105)
- #define GUI_NUMBYTES (1024*100)
- /* Define the average block size */
- #define GUI_BLOCKSIZE 0x80
-
- /*********************************************************************
- *
- * 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)
- {
- #if 1 //使用芯片内部内存
- /* 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);
- #else//使用外部内存
- static U32 *aMemory;
- aMemory = (U32 *)EXT_SRAM_ADDR;
- /* Assign memory to emWin */
- GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
- GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
- #endif
- }
复制代码
2. LCD的配置 LCD的配置按照上面官方提供的驱动流程执行即可,下面是详细的代码。
- /*
- ****************************************************************************
- *
- * LCD_X_Config
- *
- * Purpose:
- * Called during the initialization process in order to set up the
- * display driver configuration.
- *
- ****************************************************************************
- */
- void LCD_X_Config(void)
- {
- /* 读取EEPROM中的参数 */
- ee_ReadBytes((uint8_t *)&g_tTPSL, 1024, sizeof(g_tTPSL));
- /* 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, g_tTPSL.usAdcX1, g_tTPSL.usAdcX2);
- GUI_TOUCH_Calibrate(GUI_COORD_Y, 0, 271, g_tTPSL.usAdcY1, g_tTPSL.usAdcY2);
- /* 查看是否需要切换X,Y*/
- if(g_tTPSL.XYChange == 1)
- {
- GUI_TOUCH_SetOrientation(GUI_SWAP_XY);
- }
- }
- else /* GPIX = 0 7 800*480 */
- {
- /* Display driver configuration */
- LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);
- LCD_SetVSizeEx (0, VXSIZE_PHYS, VYSIZE_PHYS);
- GUI_TOUCH_Calibrate(GUI_COORD_X, 0, XSIZE_PHYS - 1, g_tTPSL.usAdcX1, g_tTPSL.usAdcX2);
- GUI_TOUCH_Calibrate(GUI_COORD_Y, 0, YSIZE_PHYS - 1, g_tTPSL.usAdcY1, g_tTPSL.usAdcY2);
- /* 查看是否需要切换X,Y*/
- if(g_tTPSL.XYChange == 1)
- {
- GUI_TOUCH_SetOrientation(GUI_SWAP_XY);
- }
- }
- }
- 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);
- }
-
- }
复制代码
|