完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转stemwin教程
本期教程开始带领大家学习STemWin的移植,对于初学者STemWin的移植不是必须要先学的,可以先学一些基本的应用,然后再来学习移植就方面很多了,考虑到教程正常的编排顺序,这里就把STemWin的移植放在了第二章。本章提供的移植方法可以自适应安富莱生产的3.0寸,4.3寸,5寸,7寸TFT屏。这里只讲STemWin在MDK上面的移植,在IAR上面的移植是类似的。开发板使用安富莱STM32-V5开发板,主芯片STM32F407IGT6。 2.1 关于STemWin移植的重要说明 2.2 移植前的准备工作 2.3 STemWin的裸机移植 2.4 STemWin带RTOS的移植 2.5 总结 2.1 关于STemWin移植的重要说明 关于STemWin的移植一定要明确以下几点: 1. emWin手册里面有这样一句话:“驱动接口的改变始于emWin V5。不再支持针对emWin V4 或更早版本开发的老显示驱动”。 2. 如果不使用V5以后版本的新特性,基本和以前的版本使用是一样的,也就是说,大家用V5以前版本实现的功能,直接升级到现有的版本,基本可以正常运行。 3. 尽管emWin提供了大部分屏的驱动,但是不能包含所有,这篇移植文档就因此而生。不管是emWin已经支持的,还是没有提供支持的,均可采用这种方法。 4. 本章教程提供了一个非常好的触摸滤波方法,此方法可以有效的滤除飞点。 5. 使用STemWin的库,一定得记得开启CRC,使用MDK安装目录里面的emWin库,一定得注册MDK的RL-ARM。 |
|
相关推荐
|
|
2.2 移植前的准备工作 这里分别讲一下MDK安装目录中emWin的移植和STemWin的移植,准备工作做好以后,剩下的移植步骤基本是一样的。只是使用的各自的库即可。 2.2.1 MDK安装目录中emWin移植 第一步:我们以MDK5.10中emWin5.22库进行说明。安装目录中有如下几个文件(路径:C:Keil5.10ARMPackKeilMDK-Middleware5.1.4emWin,如果使用的是MDK4.73等4.xx版本,路径:C:Keil4.73ARMSeggeremWin)。
在这里有一个问题要跟大家说明,emWin的官方手册中有这样一句话: 其实这个是针对SEGGER自己做的emWin源码而言的,SEGGER授权给其它厂商后,芯片厂商都对源码进行了优化,要不FPU的存在就没有意义了。上面的GUI_CM4F.lib文件就是KEIL公司对emWin中需要使用浮点的地方进行了优化。 |
|
|
|
|
|
2.2.2 STemWin移植
STemWin的移植准备工作比较简单,用户只需在初始化STemWin前使能CRC校验即可。STemWin的库文件如下: 这里面含有KEIL,IAR和GCC三个版本的库。而且还区分带OS和不带OS版本。本教程讲的是不带OS版本的移植,带OS版本的移植也很简单,用户只需添加相应的文件即可。 STemWin的下载地址:http://www.st.com/web/en/catalog/tools/PF259225# (版本1.1.2) Lib文件所在的路径:STemWin_Library_V1.1.2LibrariesSTemWinLibrary522Lib |
|
|
|
|
|
这几个文件从上往下依次进行一下简单的说明:
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_ti, j; uint16_tbuf[XPT2046_READ_TIMES]; uint16_tusSum; uint16_tusTemp; /* 读取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); returnusTemp; } /* ********************************************************************************************************* * 函 数 名: 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_tiX1, iY1; uint16_tiX2, iY2; uint16_tiX, 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; return1; } else { return0; } } /* ********************************************************************************************************* * 函 数 名: TOUCH_Scan * 功能说明: 触摸板事件检测程序。该函数被周期性调用,每ms调用1次. 见 bsp_Timer.c * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void TOUCH_SCAN(void) { uint8_ts_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_PIXELINDEXColorIndex; 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 { #ifemWin_Optimize s_ucRA8875BusyNow = 1; LCD_DrawLineV(x,y0, y1, LCD_COLORINDEX); s_ucRA8875BusyNow= 0; #else LCD_PIXELINDEXColorIndex; ColorIndex= LCD__GetColorIndex(); for (; y0 <= y1; y0++) { _SetPixelIndex(pDevice, x, y0,ColorIndex); } #endif } } l 矩形填充函数 /********************************************************************* * * _FillRect */ static void _FillRect(GUI_DEVICE * pDevice, intx0, 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的函数 /******************************************************************************************************* * * DrawBitmap 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); #ifGUI_SUPPORT_MEMDEV switch(Index) { case LCD_DEVDATA_MEMDEV: // TBD: Has to be adapted to the right memory device depending onthe used color depth! return (void *)&GUI_MEMDEV_DEVICE_16; } #else GUI_USE_PARA(Index); #endif returnNULL; } 优化好上面四个地方即可。 |
|
|
|
|
|
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 availablefor 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: * Calledduring the initialization process in order to set up the * available memory for the GUI. ********************************************************************** */ void GUI_X_Config(void) { #if 1 //使用芯片内部内存 /* 32bit aligned memory area */ staticU32 aMemory[GUI_NUMBYTES / 4]; /* Assign memory to emWin */ GUI_ALLOC_AssignMemory(aMemory,GUI_NUMBYTES); GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE); #else//使用外部内存 staticU32 *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: * Calledduring the initialization process in order to set up the * displaydriver configuration. * **************************************************************************** */ void LCD_X_Config(void) { /* 读取EEPROM中的参数 */ ee_ReadBytes((uint8_t*)&g_tTPSL, 1024, sizeof(g_tTPSL)); /* Setdisplay 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); } } |
|
|
|
|
|
2.4 STemWin带RTOS的移植 带系统和不带系统的区别就是添加一个驱动文件并添加RTOS相关文件即可,STemWin软件包里面提供了一个FreeRTOS的驱动文件,而MDK安装目录里面提供了好几款RTOS的驱动。所在路径如下: MDK4.73安装目录:C:Keil4.73ARMSeggeremWinSampleGUI_X STemWin软件包:STemWin_Library_V1.1.2LibrariesSTemWinLibrary522OS 用户更具自己使用的OS,并添加此驱动即可,下面是FreeRTOS的工程目录。 |
|
|
|
|
|
2.5 总结
整体来说,STemWin的移植不难,难的是底层驱动的优化,如何让它工作在最佳性能状态。这里有三个DEMO演示视频(分别是3.0寸,4.3寸和7寸的视频) |
|
|
|
|
|
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
852 浏览 1 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
592 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
705 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
926 浏览 2 评论
657 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12005 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 00:29 , Processed in 1.039364 second(s), Total 101, Slave 83 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号