电容触摸屏
2011-01-14 15:36
1.Kconfig文件
增加宏定义
2.Makefile文件
增加编译处理
3.添加程序源码
Touch screen remote control design document
2010年11月08日 星期一 13:08
Touch screen remote control design document
1. 开发板环境
a) Mini2440 开发板。Arm9 处理器+64M SRAM + 64M Flash +3.5’ 触摸屏LCD
b) Linux 2.6.32 kernel,支持多点触摸触摸屏+Qtopia 2.2.20 图形用户界面系统
c) AVR 单片机+加速度传感器+红外一体化接收头+红外发射二极管
2. 主机开发环境
a) Vmware 6.0 安装 Fedora 10 系统,按照友善之臂mini2440 使用手册来建立开发环境。最好在安装fedora 10的过程中将所有的可选项全部安装,以免后续开发过程中遇到不可预知的问题。Fedora 10默认不能以root用户登陆图形用户界面,需要以普通用户登陆之后在命令终端中su切换到root用户,然后修改文件/etc/pam.d/gdm。将auth required pam_succeed_if.so user != root quiet 这句注销。
b) 按照友善之臂用户手册建立交叉开发环境。安装arm-linux-gcc4.3.2,arm-qtopia, x86-qtopia, root-qtopia, linux-2.6.32-friendlyarm 到系统中。安装的过程中有一个问题是,不能够同时编译arm-qtopia和x86-qtopia,如果这样做,会发生不可预知的错误。典型问题是qt2的designer打开后是透明的,无法操作。
c) 遥控器解码目前采用FPGA平台来完成的,所以主机具有FPGA开发环境(quartus 9.0)
d) 红外发射与加速度传感器的手势操作室通过AVR单片机完成的,所以主机具有AVR单片机开发环境(Keil 4)
3. 图形界面编码
a) Arm-qtopia 文件夹中安装了qt2,在qt2的bin目录下执行 designer 就可以进入qt的图形开发界面。你可以图形化的创建自己的UI,可以直接建立各个控件之间或者控件与主窗口之间的信号与槽的链接。一般而言,做QT界面的嵌入式开发,都会涉及到几个基本的问题,那就是 类的继承、虚函数、构造函数的重载。通过designer设计的界面保存后会生成相应的源文件,这些文件用户编辑是无效的,因为重新生成后所有用户的更改都会消失。 所以最有效的方式是用户通过继承主窗口类,然后在子类中通过虚函数来实现与父类函数的交互调用。代码编写完毕后,需要设置当前的环境变量(调用友善已经提供的适用于arm平台的脚本就可以),编写工程文件 *.pro ,编写快捷方式 *.desktop。最后编译生成arm平台的可执行文件,查看Makefile的DESTDIR 和 TARGET 可以知道目标文件被生成在哪里。 同时通过 file 命令查看文件类型。将可执行文件拷贝到开发板的/opt/Qtopia/bin目录下,将 *.desktop 拷贝到开发板的/opt/Qtopia/apps/Applications就可以在开发板的Applications目录下看到相应的文件快捷方式。附录一阐明 .pro文件格式与 .desktop文件格式。
b) X86-qtopia 是嵌入式界面的PC模拟平台,利用 qvfb来模拟arm平台上的qtopia系统。开发过程就是普通的qt开发,利用qt2的designer来做界面或者自己手写代码。同样编写 pro文件与 desktop文件,设置环境变量(X86平台的脚本),编译生成x86平台的可执行文件,拷贝至 Qtopia安装目录下的 image/opt/Qtopia/bin 将 desktop文件拷贝至Qtopia安装目录下的 image/opt/Qtopia/apps/Applications目录下,然后回到x86-qtopia的根目录,执行脚本run就可以利用qvfb启动模拟器。主要是为了方便开发软件而做了这样一个pc的模拟。
c) 遥控器的界面V1.0采用的是qt designer设计,可以给控件加载不同的背景效果来美化界面。遥控器的基本功能实现,但是由于qt designer的控件相对较少,对于嵌入式开发平台能够使用的控件就更加不足,所以v1.0界面比较死板,button都是矩形,不能创建不规则形状的控件,采用图片做界面的背景会使得程序的响应非常之慢。所以V1.0的界面就此搁置。
遥控器界面V2.0使用QT加皮肤的方法来使得界面更加美观。参考资料为IBM文档库中的《使用QT制作Skin》。附录二贴出原文以保存。程序源文件中已经给出比较详细的注释,在此不分析源代码,主要就是修改上述链接中提供的方法来实现。界面程序同时还打开串口与单片机通信,调用蜂鸣器实现按键发声。所用代码为友善之臂提供的example中的相关代码。有一定修改,有注释。在本程序中,使用CON3与单片机通信。设置波特率115200 Bd,数据位8bits, 停止位 1bit,无校验,无流控制。在图形界面编码中遇到几个典型的问题:一是嵌入式C开发中 volatile 关键字的使用时为了强制编译器每次使用到volatile变量时都从变量原始地址取值,防止编译器的自动优化。这样一个关键字的使用是区别C程序员与嵌入式程序员的首要因素。第二个典型问题是在C++代码中调用C库函数的头文件,一般会使用 extern C 关键字来告诉编译器正在使用C头文件。第三个典型问题是函数的作用域问题以及C函数与C++函数重名的问题。在C++的类的成员函数中要使用C头文件定义的函数需要使用 :: 作用域符号,例如要使用C函数 close()关闭蜂鸣器,则应该使用 ::close() 的调用方式来告诉编译器当前cpp文件中这个函数是定义在 extern C 包含的C头文件中的,而不是C++头文件中定义的close。
程序编写调试完毕后,执行如下操作:
i. 将可执行文件拷贝到开发板的/opt/Qtopia/bin
ii. 将.desktop拷贝到开发板的/opt/Qtopia/apps/Applications
iii. 将skin文件夹拷贝到开发板的/opt/Qtopia/pics/remote/
重启开发板就可以在Applications目录下看到自定义的快捷方式。另外,根据qtopia系统的架构,可以自己创建一个目录来存放自己的desktop文件。例如: 在/opt/Qtopia/目录下建立文件夹 SEU, 同时拷贝 Applications目录下的隐藏文件 .directory 到 SEU文件夹下,然后修改 .directory 文件,重启就可以看到SEU的分类目录。
4 红外信号编解码
a) 暂无
5 I2C 电容触摸屏驱动
a) I2C通信协议在这里使用100K的通信速率,其他不做介绍。linux系统下编写I2C驱动,主要有两种方式,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux I2C驱动体系结构来完成。本文采用利用linux I2C体系结构来完成驱动。主要工作就是向linux I2C体系结构注册触摸屏设备,然后在中断服务程序中向input子系统上报多点触摸的坐标以及手势参数等等。关于I2C体系结构详见文章《实例解析linux内核I2C体系结构》 原文链接为
http://www.embedu.org/Column/Column190.htm 和
http://www.embedu.org/Column/Column213.htm
b) 友善之臂更新的linux-2.6.32的内核中已经做好了 I2C的适配器的硬件驱动和适配器的algorithm。在源文件 linux-2.6.32.2/drivers/i2c/busses/i2c-s3c2410.c中完全实现。所以要驱动此I2C电容触摸屏,只需要编写触摸屏的设备驱动即可。参考内核自带的I2C触摸屏的驱动
linux-2.6.32.2/drivers/input/touchscreen/migor_ts.c来编写,只不过这个触摸屏是单点触摸屏。我们要做多点触摸,所以必须使用2.6.32的内核中已经做好的支持多点触摸的input子系统。参考链接为:《Linux的I2C 设备驱动 -- mini2440 上i2c接口触摸屏驱动》
http://www.lupaworld.com/home.php?mod=space&uid=273398&do=blog&id=149486
在创建和配置I2C 设备linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c中,应添加代码为:
#include <linux/i2c.h>
/*I2C touch screen devices*/
/*bus configuration*/
static struct s3c2410_platform_i2c i2c_ts_cfg __initdata = http://koffuxu.blog.51cto.com/1063541/{
.flags = 0,
.slave_addr = 0x02, // 7 bit address
.frequency = 100*1000, // 100 kHz
.sda_delay = 2,
};
/* I2C device name is "cypress_ts", 7 bits address is 0x02, interruput is eint20 */
static struct i2c_board_info i2c_ts_devices[] __initdata = http://koffuxu.blog.51cto.com/1063541/{
// I2C_BOARD_INFO("cypress_ts", 0x02),
{
.type = "cypress_ts",
.addr = 0x02,
.irq = IRQ_EINT20, },
{ }
};
在如下初始化函数中初始化I2C设备,注册I2C触摸屏
static void __init mini2440_machine_init(void)
{
………………
/* i2c touch screen devices */
s3c_i2c0_set_platdata(&i2c_ts_cfg);
i2c_register_board_info(0, i2c_ts_devices, ARRAY_SIZE(i2c_ts_devices));
/****************************/
………………
}
c) Input子系统简单介绍如下:参见文章《linux内核input子系统解析》原文链接为:http://www.embedu.org/Column/Column289.htm 同时可以分析2.6.32系统内核源文件。上文只讲述了子系统的结构和工作原理,但是对于多点触摸input子系统没有过多解释,参考linux自带的document Multi-touch (MT) Protocol可知,本系统的多点触摸的上报机制应该如下所示:
1. ABS_MT_TRACKING_ID
2. ABS_MT_POSITION_X
3. ABS_MT_POSITION_Y
4. SYN_MT_REPORT
5. ABS_MT_TRACKING_ID
6. ABS_MT_POSITION_X
7. ABS_MT_POSITION_Y
8. SYN_MT_REPORT
9. SYN_REPORT
参考文档《29内核输入子系统多点上报机制实现》
http://blog.csdn.net/tjd0227/archive/2010/06/13/5669620.aspx
d) 附录四会给出修改好的 cypress_ts.c 源文件,即为I2C触摸屏的设备驱动。除此之外,还需要修改Kconfig文件和Makefile文件以使得能够在menuconfig中选中我们的I2C触摸屏驱动并编译生成模块或者直接编译进内核。具体操作为:修改linux-2.6.32.2/drivers/input/touchscreen/Kconfig文件,添加如下代码:
config TOUCHSCREEN_CYPRESS
tristate "Cypress I2C touchscreen"
depends on I2C
help
Say Y here to enable cypress i2c touchscreen support.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called cypress_ts.
修改linux-2.6.32.2/drivers/input/touchscreen/Makefile文件,添加如下代码:
obj-$(CONFIG_TOUCHSCREEN_CYPRESS) += cypress_ts.o
e) 连接I2C触摸屏到mini2440上,利用GPIO口或者CAMERA接口(CON20)的 I2C信号线即可。在此利用CON20,连接SCL到I2CSCL,SDA到I2CSDA,VCC到VDD3.3V,GND到GND,连接INT到EINT20(利用20号中断,在i2c_ts_devices[] __initdata中定义了设备名,器件地址,中断号)
f) 重新编译内核,拷贝生成的模块文件 cypress_ts.ko 到开发板下执行,即可以在开发板上创建设备 /dev/input/event1 给I2C电容触摸屏。编写测试程序,读取触摸屏上报给event1的数据值。简单程序为:
static int fd_cypress_ts = -1;
static struct input_event ev_ts;
fd_cypress_ts = open(“/dev/input/event1”, O_RDONLY);
read(fd_cypress_ts, &ev_ts, sizeof(ev_ts));
while(1){
printf(“%d %d %d”, ev_ts.type, ev_ts.code, ev_ts.value);
}
附录一 pro文件格式, desktop文件格式
1. 项目文件
项目文件(*.pro)用于生成 Makefile 文件,详细介绍可以参考《qmake 使用手册》(qmake-manual.html);
#示例文件
TEMPLATE = app
DESTDIR = /home/helloapp
HEADERS += hello.h
SOURCES += hello.cpp
SOURCES += main.cpp
DEFINES += QT_DLL
CONFIG += qt warn_on release
如果条目是单值的,比如template或者目的目录,我们是用“=”,但如果是多值条目,我们使用“+=”来为这个类型添加现有的条目。使用“=”会用新值替换原有的值,例如,如果我们写了DEFINES=QT_DLL,其它所有的定义都将被删除。
2. main.cpp
main.cpp文件格式的详细介绍见“qtopia2.1官方文档\html\mainfunc.html”;形式如下:
QTOPIA_ADD_APPLICATION(NAME,IMPLEMENTATION)
QTOPIA_MAIN
IMPLEMENTATION – 应用程序主窗口类
NAME - “可执行文件名”
3. desktop文件
Exec =example - 可执行文件名
Icon =Example - 图标文件名
Name[] =Example - 显示的快捷图标的标题
原文连接:http://blog.csdn.net/daysummer/archive/2007/03/30/1546804.aspx
附录二 《使用QT制作Skin》
软件界面的风格变化可以通过两种机制完成,一种是通过设置主题(Themes),它使用 界面库本身所具有的对界面组件(Components)的控制能力切换显示风格;另外一种是 通过提供不同系列的图片来切换显示界面,即这里所讲的 Skin。
制作表皮有几个重要的因素值得考虑:
1. 使用无边界的窗口
在 XWindow 下,无边界的窗口是指不受窗口管理器管理的边界不规则的窗口。由于 不受窗口管理器管理管理,所以软件窗口界面没有附加的标题条(Title Bar)等。 在Qt中,建立无边界窗口的最简单的方法 是设置 QWidget 的 WFlags 的值是 WStyle_NoBorder。它定义在 qnamespace.h 中。 不规则窗口的特点则要求对整个 窗口使用图像掩码。使用 X 窗口形状的扩展(X Shape Extension)来达到要求。在 Qt 中可以直接使用,
QBitmap bm;
bm = *(Pixmaps[MASK]);
setMask(bm);
setBackgroundPixmap(*Pixmaps[BACKGROUND]);
2. 窗口的移动
由于上述窗口不受窗口管理器的管理的特性,所以移动窗口需要特殊处理,一般的 方法是截取根Widget的鼠标按钮事件,自己处理鼠标点击和移动的事件。
void SkinDemo::mouseMoveEvent(QMouseEvent *e)
{
QPoint newpos = e->globalPos();
QPoint upleft = pos0 + newpos - last;
move(upleft);
}
void SkinDemo::mousePressEvent(QMouseEvent *e)
{
last = e->globalPos();
pos0 = e->globalPos() - e->pos();
}
这里我们取得的鼠标位置是绝对位置,即相对于根窗口的位置,同时也记录下窗口 左上角的位置,当鼠标移动时,取得新的绝对位置,则窗口左上角 的新位置应该 是原来位置与鼠标移动的位置之差。
3. 按钮的制作
对于表皮中的图像按钮,设置它的父类是 QButton,这种按钮由两幅图片构成, 一幅图片是正常状态(Normal),一幅图片是按钮按下时的状态(Activated)。有时 也可以设置成四种状态,即增加禁止状态(Disabled)和鼠标指针进入时的状态 (Hovered)。
在例子( qt-skin-example.tar.gz)中,我们重新定义了鼠标按下和鼠标移动的事件处理 函数, 并且含有按钮的所有信息,主工作区的所有信息等。主工作区的信息是它的 位置和尺寸,主窗口的信息是它所使用的背景图片和图片的掩码(用来制造不规则窗 口),所以整个主窗口的大小可以由图片的尺寸来决定。几个按钮的信息包含它们的 位置,它们的大小由图片的大小来决定。
原文链接:http://www.ibm.com/developerworks/cn/linux/guitoolkit/qt/skin/index.html
附录三 I2C触摸屏参数
a) 总体特性
i. 电容型触摸屏
ii. 大小为3.5”,分辨率为240x320
iii. 采用Cypress的触摸屏控制器cy8ctmg110
iv. 支持单点、两点触摸及手势识别
v. 扫描速度0.5ms
vi. 采用I2C通信协议
b) 管脚分配
i. 1.VDD ( 2.40-5.25 V)
ii. 2.GND
iii. 3.INT (当按下触摸屏时输出低电平,平时为高电平)
iv. 4.SCLK (I2C时钟线)
v. 5.SDATA (I2C信号线)
vi. 6.NC (未用)
c) 通信协议
i. 采用标准I2C通信协议
ii. 从器件地址为0X02
iii. 数据共11字节,地址为0X00-0X0a
iv. 当INT从高电平变成低电平时表示触摸屏被按下,此时可读出这11个地址的数据。
d) 数据格式
i. Y1+X1+Y2+X2+STATUS+GESTURE
ii. (X1,Y1)(X2,Y2)分别为按下的两点的坐标,当只有一点按下时(X1,Y1)为其坐标。这些数据均为16位。
iii. STATUS是8位的状态数据,0表示未按下,1表示一个点按下,2表示两个点按下。
iv. GESTURE是16位的手势数据。
1. Gesture Gesture Code
2. No Gesture 0x00
3. Single-Touch Pan-Up 0x01
4. Single-Touch Pan-Right 0x02
5. Single-Touch Pan-Down 0x03
6. Single-Touch Pan-Left 0x04
7. Single-Touch Rotate-CW 0x05
8. Single-Touch Rotate-CCW 0x06
9. Single-Touch Click 0x07
10. Multi-Touch Pan-Up 0x08
11. Multi-Touch Pan-Right 0x09
12. Multi-Touch Pan-Down 0x0A
13. Multi-Touch Pan-Left 0x0B
14. Zoom In 0x0C
15. Zoom Out 0x0D
16. Single-Touch Double Click 0x0E
17. Multi-Touch Click 0x0F