[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);
}
}
大家根据自己的屏,配置屏的大小和触摸校准就可以了。到这里移植就算结束了。
[STemWin教程入门篇]第二期:emWin5.xx的详细移植步骤的更多相关文章
- [STemWin教程入门篇] 第一期:emWin介绍
转自:http://bbs.armfly.com/read.php?tid=1544 SEGGER公司介绍 了解emWin之前,先了解一下SEGGER这家公司,了解生产商才能对emWin有更加全面的认 ...
- CE修改器使用教程 [入门篇]
Cheat Engine 一般简称CE,是一个开放源代码的作弊软件,其功能包括:内存扫描.十六进制编辑器.调试工具,Cheat Engine 自身附带了外挂制作工具,可以用它直接生成外挂工具,CE可以 ...
- JqueryEasyUI教程入门篇
什么是jQueryEasyUI? JqueryUI是一组基于jQuery的UI插件集合 学习jQueryEasyUI的条件? 必须掌握Jquery的基本语法知识 jQueryEasyUI的特点? 1. ...
- [转]JqueryEasyUI教程入门篇
什么是jQueryEasyUI? JqueryUI是一组基于jQuery的UI插件集合 学习jQueryEasyUI的条件? 必须掌握Jquery的基本语法知识 jQueryEasyUI的特点? 1. ...
- OpenCV学习教程入门篇<一、介绍>
OpenCV,是Inter公司开发的免费开源专门因为图像处理和机器视觉的C/C++库,英文全称是Open Source Computer Vision. 1. 可视化语言Matlab与OpenCV都能 ...
- shell教程<入门篇>
由于我平时的工作环境是linux,所以无可避免的经常使用命令行模式和shell脚本,而且有些命令行每天都要输好多遍,比如ssh登录之类的,所以干脆把平时常用的命令都写成脚本文件,所以特意开了一个she ...
- 转:jQuery LigerUI 使用教程表格篇(3) 复选框、多表头、分组、汇总和明细
阅读目录 复选框 多表头 分组 汇总 明细 复选框 grid可以设置复选框模式进行多选,只需要简单的配置 checked:true 获取选中行 如果要获取选中的行,可以用getSelecteds方法: ...
- SQLAlchemy 教程 —— 基础入门篇
SQLAlchemy 教程 -- 基础入门篇 一.课程简介 1.1 实验内容 本课程带领大家使用 SQLAlchemy 连接 MySQL 数据库,创建一个博客应用所需要的数据表,并介绍了使用 SQLA ...
- Android Studio2.0 教程从入门到精通Windows版 - 入门篇
http://www.open-open.com/lib/view/open1468121363300.html 本文转自:深度开源(open-open.com)原文标题:Android Studio ...
随机推荐
- LeetCode 实现 Trie (前缀树)
题目链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree/ 题目大意: 略. 分析: 字典树模板. 代码如下: class Tr ...
- Cocos2d-x之物理引擎
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 在很多的游戏设计中一般都会涉及和模拟到真实的物理世界.然而游戏中模拟真实世界的物理会很复杂.使用已经写好的物理引擎会用很大的帮助和便利. ...
- Codeforces The Child and Toy
The Child and Toy time limit per test1 second On Children's Day, the child got a toy from Delayyy as ...
- python学习笔记--类(一)
# 类是为了代码重用 class First: #类 pass #实例 = 类名() obj = First() # 类是一种产生实例的工厂# 类和模块的差异在于,内存中特定的模块只有一个实例(所以我 ...
- 将一个对象赋值给另一个对象(使用element CheckBox中length报错)
注意两个对象相似(比如form表单),千万不要直接赋值(会把对象的属性也变化),很容易漏掉一些属性.比如此次CheckBox报length的错误,就是因为用于存放checkbox复选框选项的数组进过赋 ...
- powerdesigner级联删除
在Reference Properties属性窗口的Integrity属性页中选中Delete Constraint的Cascade;选中Update Constraint的Cascade.
- Hdu-3333 Turning Tree (离线树状数组/线段树)
Hdu-3333 Turning Tree 题目大意:先给出n个数字.面对q个询问区间,输出这个区间不同数的和. 题解:这道题有多重解法.我另一篇博客写了分块的解法 HDU-3333 Turing ...
- React 滚动事件
代码: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UT ...
- 关于LCN分布式事务框架
基于LCN框架解决分布式事务 LCN官网 https://www.txlcn.org/ "LCN并不生产事务,LCN只是本地事务的搬运工" 兼容 dubbo.springcloud ...
- java中的成员变量、类变量,成员方法、类方法 属性和方法区别
成员变量:包括实例变量和类变量,用static修饰的是类变量,不用static修饰的是实例变量,所有类的成员变量可以通过this来引用. 类变量:静态域,静态字段,或叫静态变量,它属于该类所有实例共有 ...