UCGUI中的中的设备驱动解析

UCGUI中支持的几种输入设备.
以前在多篇文章都有介绍过UCGUI中的消息处理机制, 其中将消息输入设备分成了两类:
1.按键式的键盘类输入设备.
键盘内设备的处理比较简单,UCGUI中也是采用了节约空间的微型设计方案, 只求可以正常处理设备消息即可; 具体的思路:向外提供一个键盘驱动接口, 让具体实现键盘输入设备驱动的用户, 在自己处理键盘输入驱动处调用此函数, 将得到的硬件键盘值传送给UCGUI, 即完成一次键盘事件,UCGUI就会在消息处理LOOP当中处理按键, 将其发发到UCGUI中的当前焦点窗体.
UCGUI中的键盘消息, 采用一个的全局键盘消息变量以及是否有按键的全局变量,如下所示:
static int _KeyMsgCnt; //是否有按键消息.
static struct {
   int Key;
   int PressedCnt;
} _KeyMsg; //启用win窗体管理时,记载当前键盘消息.
static int _Key;   //未启用窗体管理时,记载当前键盘消息.
键盘消息的驱动接口如下所示, 要使UCGUI中的键盘驱动起来, 有两种形式:一种是建立一个任务, 以一定的频率去检测并读取键盘;另一种是直接在驱动中读取键盘. 这两种都必须调用下面的UCGUI提供的键盘驱动接口来将从设备上读取到的键盘值传送给UCGUI.
[1].启用win窗体管理时, 使用_KeyMsg作为键盘消息记录变量, 在使用窗体管理模块时, 通过在消息LOOP当中调用GUI_PollKeyMsg()函数检测_KeyMsg, 并将收集到的键盘消息以WM_KEY传送到当前焦点窗体.
void GUI_StoreKeyMsg(int Key, int PressedCnt);//第一个参数为按键值, 第二个参数为该键状态,1为按下,0为弹起.
[2].未启用WIN窗体管理时, 使用_Key作为键盘消息记录变量, 没有使用窗体管理模块时, 用户在应用中通过调用GUI_WaitKey()或者GUI_GetKey()来读取按键值.
void GUI_StoreKey(int Key);
[注意:按键式输入设备在UCGUI中处理得相当简单, 仅用了一个全局变量而没有用到队列来缓冲键盘输入, 这有可能会造键盘输入的丢失,所以如果要求比严格的情况下, 最好可以自己建立一个数组来缓冲键盘输入值.]
2.滑动式的MOUSE类输入设备.
UCGUI中的滑动类输入设备可以具体分为两类,具体情况如下:
[1].两类设备均相同的使用相同的接口, 来最终向UCGUI传送从设备中读取的硬件消息.
//pointer input device类设备最终都调用这两个接口函数来设置及获取当前的消息.
void GUI_PID_StoreState(const GUI_PID_STATE *pState); //传送给UCGUI从设备层读取的pointer input device消息.
int   GUI_PID_GetState(GUI_PID_STATE *pState); //UCGUI中读取当前pointer input device消息.
[2].MOUSE设备,UCGUI提供了PS2串口MOUSE的驱动支持,并建立了一个基础的将MOUSE消息传送给UCGUI的API集,具体不同的MOUSE设备可以调用这套API接口来将接收到的MOUSE消息分发出去.
//基础MOUSE驱动接口.
void GUI_MOUSE_StoreState(const GUI_PID_STATE *pState);
int   GUI_MOUSE_GetState(GUI_PID_STATE *pState);
UCGUI中提示了串口的PS2的驱动,具体在GUI_MOUSE_DriverPS2.c文件当中, 参考一下那个驱动就可以很清楚的了解其它类型的MOUSE驱动应该如何写, 最终都是处理与硬件相关的部分后, 调用如下接口来传送消息.
[3].触摸屏设备, 除了读取设备的具体处理方法与Mouse不一样之外, 其收集后消息的传送与处理全部都是一样的, 均会被UCGUI处理成同一杰消息分发出去(WM_TOUCH). 相比起MOUSE设备, UCGUI中对于触摸屏的具体驱动接口稍微复杂一些. UCGUI中的触摸屏驱动须提供四个底层驱动接口函数, 这四个函数在GUI_TOUCH_Exec()中调用, 具体的实现必须由用户根据实际的触摸屏来写驱动.GUI_TOUCH_Exec()的功能就是读取触摸屏坐标, 并且传送到UCGUI当中(调用GUI_TOUCH_StoreStateEx()).
以下为UCGUI触摸屏提供的三层接口.
1.底层触摸屏驱动接口.
//触摸屏读的时候只能Y/X轴分别读, 所以UCGUI提供了两个函数, 用于开启读X轴还是读Y轴, 意即激活读X或者是激活读Y轴.
GUI_TOUCH_X_ActivateX() Prepares measurement for Y-axis.
GUI_TOUCH_X_ActivateY() Prepares measurement for X-axis.
//实际读取X或者是Y轴的坐标.
GUI_TOUCH_X_MeasureX() Returns the X-result of the A/D converter.
GUI_TOUCH_X_MeasureY() Returns the Y-result of the A/D converter
2.中间层触摸屏驱动接口.
void GUI_TOUCH_StoreStateEx(const GUI_PID_STATE *pState);
void GUI_TOUCH_StoreState(int x, int y);
int   GUI_TOUCH_GetState(GUI_PID_STATE *pState);
3.触摸屏高层的应用接口
void GUI_TOUCH_Exec(void);//读取触摸屏.
int   GUI_TOUCH_Calibrate(int Coord, int Log0, int Log1, int Phys0, int Phys1);//校正触摸屏.
void GUI_TOUCH_SetDefaultCalibration(void);     //设置默认的校正参数.
void GUI_TOUCH_GetCalData(int Coord, int* pMin,int* pMax); //获取校正参数.
三. UCGUI中的触摸屏校正分析.
问题: 关于触摸屏校准问题
我用串口打印出来来的触摸屏的坐标是AD转换后的值,还没有转换成LCD的坐标 我的LAD是320*240的,怎么校准呀,希望高手能够指点给我个例子.
深入的解析UCGUI中触摸屏坐标与LCD坐标的转换计算:
1.为什么要进行校正.
传统的鼠标是一种相对定位系统, 只和前一次鼠标的位置坐标有关, 而触摸屏则是一种绝对坐标系统. 通常应用程序中使用的LCD坐标是以像素为单位, 而从触摸屏中读出的是点的物理坐标,其坐标轴的方向、XY值的比例因子、偏移量、缩放因子都与LCD坐标不同, 所以必须将从驱动中读取的触摸屏绝对坐标转换成LCD的坐标, 然后才能正确处理触摸屏消息.
2.UCGUI中如何进行触摸屏校正.
UCGUI中可以用两种方法进行校正配置,一是配置一个宏的值;二是使用运行时校正支持,在触摸屏使用前进行校正,如下:
[1].使用配置宏进行UCGUI中的触摸屏校正.
以下为触摸屏驱动返回的触摸屏坐标系统相对于LCD坐标系统的范围值(可以理解为触摸屏的边界在LCD坐标系统中的坐标),这些值都是可以经过校正计算出来的,一般情况下也可以校正出来后通过如下宏进行默认的配置.如下:
#define GUI_TOUCH_AD_LEFT 30   //Minimum value returned by the A/D converter.
#define GUI_TOUCH_AD_RIGHT 220   //Maximum value returned by the A/D converter.
#define GUI_TOUCH_AD_TOP 30   //Minimum value returned by the A/D converter.
#define GUI_TOUCH_AD_BOTTOM 220   //Maximum value returned by the A/D converter.
[注:简单的可以理解为触摸屏四个边界在屏幕坐标系中的坐标值,触摸屏左上角(30,220),右下角(220,220)]
//触摸屏精度,其意义相当于LCD屏幕之解析度.
#define GUI_TOUCH_XSIZE LCD_XSIZE //Horizontal area covered by touch-screen.
#define GUI_TOUCH_YSIZE LCD_YSIZE //Vertical area covered by touch-screen.
[2].调用函数进行触摸屏运行时校正.
//参数意义依次为:要校正的坐标轴(0为校正x,1为较正y)/lcd点1坐标及点2坐标/触摸屏点1及点2坐标.
int GUI_TOUCH_Calibrate(int Coord, int Log0, int Log1, int Phys0, int Phys1) {
   int l0 = 0;
   int l1 = (Coord == GUI_COORD_X) ? LCD_XSIZE - 1 : LCD_YSIZE - 1;
   if (labs(Phys0 - Phys1) < 20) {
return 1;
   }
   if (labs(Log0 - Log1) < 20) {
return 1;
   }
   xyMinMax[Coord].Min = _Log2Phys(l0, Log0, Log1, Phys0, Phys1);  
   xyMinMax[Coord].Max = _Log2Phys(l1, Log0, Log1, Phys0, Phys1);
   return 0;
}
/*********************************************************************
*    _Log2Phys
*/
static int _Log2Phys(int l, I32 l0, I32 l1, I32 p0, I32 p1) {
   return p0+ ((p1 - p0) * (l - l0)) / (l1 - l0);
}
以上校正计算两个坐标系统偏移值Offset的原理如下,设Offset/K为触摸屏坐标系统相对LCD坐标系统的在X轴的偏移值即转换比率,触摸屏Xp,LCD坐标Xl.则根据待定系数法有:
Xp = Offset + X1*Kx;
亦即:
公式[1]. ffset = Xp + (0-X1)*Kx; //这个公式也就是_Log2Phys()中的求两坐标系统偏移的算法原理.
据此,触摸屏左边界GUI_TOUCH_AD_LEFT就是如此计算出来的,但要注意其右边界GUI_TOUCH_AD_RIGHT,则:
GUI_TOUCH_AD_RIGHT = Offset + LCD_XSIZE * Kx
即:
GUI_TOUCH_AD_RIGHT = Xp + (LCD_XSIZE-X1)*Kx
GUI_TOUCH_AD_LEFT = Xp + (0-X1)*Kx
同理可得:
GUI_TOUCH_AD_TOP = Yp + (0-Yl) * Ky
GUI_TOUCH_AD_BOTTOM = Yp + (LCD_YSIZE-Y1)*Ky
上面基本就讲清了GUI_TOUCH_Calibrate()这个校正函数的计算原理,用户可以调用这个函数进行运行时校正,只须提高一个点相应的两种坐标系统下面的坐标值,即可以计算出触摸屏边界相对于屏幕坐标系统的坐标.
公式[2]. Xl = (Xp - Offset)/Kx   //这个公式就是从触摸屏坐标转换成LCD坐标的原理.
这个公式将在第3点中说明.
3.触摸屏坐标与LCD屏幕坐标的转换计算.
[1].UCGUI中使用如下函数来进行转换, 其中xyMinMax数中存放的是触摸屏校正后的触摸屏边界相对屏幕坐标系统的坐标.
static int _AD2X(int adx);//Convert physical value into coordinates.
static int _AD2Y(int ady);//Convert physical value into (logical) coordinates.
static int _AD2X(int adx) {
   I32 r = adx - xyMinMax[GUI_COORD_X].Min;
   r *= GUI_TOUCH_XSIZE - 1;
   return r / (xyMinMax[GUI_COORD_X].Max - xyMinMax[GUI_COORD_X].Min);
}
static int _AD2Y(int ady) {
   I32 r = ady - xyMinMax[GUI_COORD_Y].Min;
   r *= GUI_TOUCH_YSIZE - 1;
   return r/(xyMinMax[GUI_COORD_Y].Max - xyMinMax[GUI_COORD_Y].Min);
}
由第3点推出一个公式[2]:
Xl = (Xp - Offset)/Kx //参见前面第2点所述
可以理解 _AD2X/_AD2Y这两个转换触摸屏坐标到屏幕LCD坐标的转换关系:
[1].xyMinMax[GUI_COORD_X].Min/xyMinMax[GUI_COORD_Y].Min触摸屏坐标相对屏幕LCD坐标系的偏移值OffSet.
[2].(GUI_TOUCH_YSIZE - 1)/(xyMinMax[GUI_COORD_Y].Max - xyMinMax[GUI_COORD_Y].Min)即为转换比率Kx.
四.UCGUI中的图形驱动分析.
相比于上面的触摸屏校正计算,UCGUI中的图形驱动没有什么计算方法问题,须要移值UCGUI时提供相应的图形驱动接口实现即可,但针对多种不同的LCD控制器,因为提供的功能强弱不同,所以差别还是比较大的,而且UCGUI中LCD控制器有大量的配置宏.
本文将对实际的LCD驱动为例来讲解UCGUI中的LCD的配置以及LCD驱动接口,从而让移值的用户能够更加明白移值过程.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值