3. 电容屏的实验数据
假设你的开发板上电容屏对应的设备节点是/dev/input/event0,执行以下命令:
hexdump /dev/input/event0
然后用一个手指点击触摸屏,得到类似如下的数据:
在上面的数据中,为了兼容老程序,它也上报了ABS_X、ABS_Y数据,电阻触摸屏就是使用这类型的数据。所以基于电阻屏的程序,也可以用在电容屏上。
使用两个手指点击触摸屏时,得到类似如下的数据:
为了兼容老程序,它也上报了ABS_X、ABS_Y数据,但是只上报第1个触点的数据。
这里讲解了一般的电阻屏和电容屏会上报那些数据,这些数据一般来说比较复杂。而解决这些复杂的数据,一般来说要用到库。下面就会讲到用库解决这些问题。
1.5 tslib
前面我们讲解了不用库,而是使用open icotl等函数直接调用驱动函数去读取数据。下面咱们使用库去读取数据。
tslib是一个触摸屏的开源库,可以使用它来访问触摸屏设备,可以给输入设备添加各种“filter”(过滤器,就是各种处理),地址是:请点击。
编译tslib后,可以得到libts库,还可以得到各种工具:较准工具、测试工具。
使用GIT下载所有源码后,本节源码位于如下目录:
01_all_series_quickstart\ 04_嵌入式Linux应用开发基础知识\source\11_input\ 02_tslib\
1.5.1 tslib框架分析
tslib的主要代码如下:
核心在于“plugins”目录里的“插件”,或称为“module”。这个目录下的每个文件都是一个module,每个module都提供2个函数:read、read_mt,前者用于读取单点触摸屏的数据,后者用于读取多点触摸屏的数据。
要分析tslib的框架,先看看示例程序怎么使用,我们参考ts_test.c和ts_test_mt.c,前者用于一般触摸屏(比如电阻屏、单点电容屏),后者用于多点触摸屏。
一个图就可以弄清楚tslib的框架:
调用ts_open后,可以打开某个设备节点,构造出一个tsdev结构体。
然后调用ts_config读取配置文件的处理,假设/etc/ts.conf内容如下:
module_raw input module pthres pmin=1 module dejitter delta=100 module linear
每行表示一个“module”或“moduel_raw”。
对于所有的“module”,都会插入tsdev.list链表头,也就是tsdev.list执行配置文件中最后一个“module”,配置文件中第一个“module”位于链表的尾部。
对于所有的“module_raw”,都会插入tsdev.list_raw链表头,一般只有一个“module_raw”。
注意:tsdev.list中最后一个“module”会指向ts_dev.list_raw的头部。
无论是调用ts_read还是ts_read_mt,都是通过tsdev.list中的模块来处理数据的。这写模块是递归调用的,比如linear模块的read函数如下:
linear模块的read_raw函数如下:
因为是递归调用,所有最先使用input模块读取设备节点得到原始数据,再依次经过pthres模块、dejitter模块、linear模块处理后,才返回最终数据。
1.5.2 交叉编译、测试tslib
使用GIT下载所有源码后,本节源码位于如下目录:
01_all_series_quickstart\ 04_嵌入式Linux应用开发基础知识\source\11_input\ 02_tslib\tslib-1.21.tar.xz
本节会涉及这些内容:交叉编译tslib,运行自带的测试程序,后面会自己写一个简单的测试程序。
1.交叉编译tslib
参考:
《第2篇 环境搭建、Linux基本操作、工具使用》
《7.3 配置交叉编译工具链》
《第4篇 嵌入式Linux应用开发基础知识》
《6.4 交叉编译程序:以freetype为例》
先配置工具链:
// 对于STM32MP157,命令如下 export ARCH=arm export CROSS_COMPILE=arm-buildroot-linux-gnueabihf- export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin // 对于IMX6ULL,命令如下 export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf- export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin
交叉编译tslib:
// 对于STM32MP157,命令如下 ./configure --host=arm-buildroot-linux-gnueabihf --prefix=/ make make install DESTDIR=$PWD/tmp // 对于IMX6ULL,命令如下 ./configure --host=arm-linux-gnueabihf --prefix=/ make make install DESTDIR=$PWD/tmp
确定工具链中头文件、库文件目录:
// 对于STM32MP157,命令如下 echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v - // 对于IMX6ULL,命令如下 echo 'main(){}'| arm-linux-gnueabihf-gcc -E -v -
把头文件、库文件放到工具链目录下:
// 对于STM32MP157,命令如下 cd tslib-1.21/tmp/ cp include/* /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include cp -d lib/*so* /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/ // 对于IMX6ULL,命令如下 cd tslib-1.21/tmp/ cp include/* /home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include cp -d lib/*so* /home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
2. 测试tslib
把库文件放到单板上:运行程序要用。先在开发板上使用NFS挂载Ubuntu的目录,再把前面编译出来的tslib-1.21/tmp/部分文件复制到板子上,示例命令如下:
cp /mnt/tslib-1.21/tmp/lib/*so* -d /lib cp /mnt/tslib-1.21/tmp/bin/* /bin cp /mnt/tslib-1.21/tmp/etc/ts.conf -d /etc
对于IMX6ULL,首先需要关闭默认的qt gui程序,才可以执行ts_test_mt测试命令,关闭qt命令如下所示:
mv /etc/init.d/S07hmi /root reboot
在单板上执行测试程序:
ts_test_mt
1.5.3 自己写一个测试程序
使用GIT下载所有源码后,本节源码位于如下目录:
01_all_series_quickstart\ 04_嵌入式Linux应用开发基础知识\source\11_input\ 02_tslib\mt_cal_distance.c
1. 接口函数深入分析
前面演示过,用两个手指点击屏幕时,可以得到类似下面的数据:
驱动程序使用slot、tracking_id来标识一个触点;当tracking_id等于-1时,标识这个触点被松开了。
触摸屏可能支持多个触点,比如5个:tslib为了简化处理,即使只有2个触点,ts_read_mt函数也会返回5个触点数据,可以根据标志位判断数据是否有效。
ts_read_mt函数原型如下:
假设nr设置为1,max_slots设置为5,那么读到的数据保存在:samp[0][0]、samp[0][1]、samp[0][2]、samp[0][3]、samp[0][4]中。 假设nr设置为2,max_slots设置为5,那么督导的数据保存在:samp[0][0]、samp[0][1]、samp[0][2]、samp[0][3]、samp[0][4]和samp[1][0]、samp[1][1]、samp[1][2]、samp[1][3]、samp[1][4]中。
ts_sample_mt结构体如下:
2. 编写代码
实现一个程序,不断打印2个触点的距离。
思路:假设是5点触摸屏,调用一次ts_read_mt可以得到5个新数据;使用新旧数据进行判断,如果有2个触点,就打印出距离。
代码实现