首先电阻屏为什么需要校准,这是电气方面的知识,我也不懂,这里就不说了,这里主要讲讲自己在项目中是怎么通过应用程序来实现校准的,好记性不如烂笔头这里有一篇讲解触摸屏校准原理和优化的文章,道客巴巴上的,先看看了解怎么做 触摸屏校准原理与优化

通过一系列文章的了解,认识到要想真正做到实现校准,就必须能够更新android系统中的转换参数文件,看一些文章的介绍,不知道是因为版本或者平台,总感觉和我的系统版本不一样,该有的文件都找不到,这里我使用的是freescale53,android2.3.7平台

系统烧写后第一次启动的时候会有一个需要实现校准的过程,是在一个进程中做到的,文件目录system/core/ts_calibrator,分析这个文件主要分为检查文件,校准读取,画十字,计算并写入驱动:

首先在init.rc文件中我们能够会执行ts_calibrator进程,并在这里处于阻塞状态,等待用户触击屏幕

on boot
# basic network initifup lohostname localhostdomainname localdomainmkdir /data/system 0775 system systemexec /sbin/ts_calibrator

在ts_calibrator.c中,首先会检测有没有校准文件,如果没有需要重新生成,如果存在该文件就读出该文件中的数据并写入到驱动中生效(这个文件我们也可以自己生成并写入比较准确的数据,这样子开机的时候就不用校准)

property_get("ro.calibration", runme, "");if (runme[0] != '1')return 0;/* open log */log_fd = open(log, O_WRONLY | O_CREAT | O_TRUNC);if (check_conf())do_calib = 0;
/* check conf file */if (stat(cf_file, &s) == 0) {/* conf file already existed */cf_fd = open(cf_file, O_RDWR);if (cf_fd >= 0) {buffer = calloc(1, s.st_size + 1);read(cf_fd, buffer, s.st_size);ret = sscanf(buffer, "%d\n%d\n%d\n%d\n%d\n%d\n%d",&data[0], &data[1], &data[2],&data[3], &data[4], &data[5],&data[6]);if (ret == 7) {free(buffer);/* write to driver */write_conf(data);close(cf_fd);return 1;}log_write("Failed to get datas from conf file: %d\n", ret);free(buffer);close(cf_fd);}//else可以做自己的处理}

校准读取:系统采用3点校准,连续三次读取触摸点的物理坐标,其中显示屏的坐标是已知的

static void get_input(int *px, int *py)
{int rd, i;struct input_event ev[64];int step = 0;while (1) {/* read ts input 这里会一直读取,知道松手跳出循环*/rd = read(ts_fd, ev, sizeof(struct input_event) * 64);if (rd < (int) sizeof(struct input_event)) {log_write("Read input error\n");continue;}for (i = 0; i < (int)(rd / sizeof(struct input_event)); i++) {switch (ev[i].type) {case EV_SYN:/*在这里跳出循环*/if (step)return;case EV_KEY:if (ev[i].code == BTN_TOUCH && ev[i].value == 0)/* get the final touch */step = 1;break;case EV_ABS:if (ev[i].code == REL_X)*px = ev[i].value;else if (ev[i].code == REL_Y)*py = ev[i].value;break;default:break;}}}}

计算并写入驱动:

static void do_calibration(void)
{/*-------------省略-------------*//* check ok, calulate the result 这里的算法与以上文章讲解的基本一致*/delta = (tx[0] - tx[2]) * (ty[1] - ty[2])- (tx[1] - tx[2]) * (ty[0] - ty[2]);delta_x[0] = (dx[0] - dx[2]) * (ty[1] - ty[2])- (dx[1] - dx[2]) * (ty[0] - ty[2]);delta_x[1] = (tx[0] - tx[2]) * (dx[1] - dx[2])- (tx[1] - tx[2]) * (dx[0] - dx[2]);delta_x[2] = dx[0] * (tx[1] * ty[2] - tx[2] * ty[1]) -dx[1] * (tx[0] * ty[2] - tx[2] * ty[0]) +dx[2] * (tx[0] * ty[1] - tx[1] * ty[0]);delta_y[0] = (dy[0] - dy[2]) * (ty[1] - ty[2])- (dy[1] - dy[2]) * (ty[0] - ty[2]);delta_y[1] = (tx[0] - tx[2]) * (dy[1] - dy[2])- (tx[1] - tx[2]) * (dy[0] - dy[2]);delta_y[2] = dy[0] * (tx[1] * ty[2] - tx[2] * ty[1]) -dy[1] * (tx[0] * ty[2] - tx[2] * ty[0]) +dy[2] * (tx[0] * ty[1] - tx[1] * ty[0]);cal_val[0] = delta_x[0];cal_val[1] = delta_x[1];cal_val[2] = delta_x[2];cal_val[3] = delta_y[0];cal_val[4] = delta_y[1];cal_val[5] = delta_y[2];cal_val[6] = delta;/*这里将校准后的参数保存至文件并写入驱动生效*/save_conf(cal_val);write_conf(cal_val);
}

上面列举的代码涉及主要的流程

在后面的工作中我也尝试这些做,但是遇到了一下内容:

1.在校准实现后,通过同样的read函数读取出的不是触摸屏的物理坐标,而是显示屏的坐标,这完全没用

2.上面的情况出现后就必须需要还原驱动中的参数为初始值,通过参看驱动文件可以找到,在一个.h文件中,但是就初始值重新写入驱动后,相当于破坏了android系统触摸时间上报数据的正确性,这时候应用程序控件的触发函数失效

3.如果在应用程序进行阻塞读取,容易造成程序挂掉

出现上述情况后基本解决方法如下

在进入校准程序后,把驱动校准参数初始化,在系统底层建立线程阻塞读取物理坐标,这个时候需要与应用程序实现交互,变更十字叉的位置,由于需要频繁的读写系统文件,在这里使用JNI技术来实现,并通过AndroidRuntime::createJavaThread创建线程监听设备节点,并实现上报来与应用程序交互(常规的线程做不到这一点)

首先介绍JNI知识,这里记录自己遇到的问题,详细的网上有很多文章

1.如何生成.h文件

在java文件中声明这些本地函数,在编译过程序后将会生成对应的class文件,假设路径如下bin/classes/com/android/jni/JNITest.class

进入classes目录,使用javah命令   javah -d xxx/jni(存放目录) -jni com.android.jni.JNITest将会生成对应的头文件

private native void tsInit();
private native void tsOver();
private native String getTS();

编写对应的cpp文件

#include <utils/Log.h>
#include "com_android_settings_Calibration.h"
#include "JNIHelp.h"
#include "jni.h"
#include "android_runtime/AndroidRuntime.h"
#include "ts_input.h"
#include <string.h>
#include <pthread.h>namespace android{/*这里如果没有加上这个名字空间会导致AndroidRuntime::getJNIEnv()编译报错*/extern "C" int ts_init(TSbacks *pTSbacks);
extern "C" int ts_over();
extern "C" void get_input();static jobject mCallbacksObj = NULL;static jmethodID method_reportTS;static int ret;
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {if (env->ExceptionCheck()) {LOGE("An exception was thrown by callback '%s'.", methodName);LOGE_EX(env);env->ExceptionClear();}
}
/*上报函数*/
static void callback(int i)
{JNIEnv* env = AndroidRuntime::getJNIEnv();ret = i;env->CallVoidMethod(mCallbacksObj, method_reportTS, ret);checkAndClearExceptionFromCallback(env, __FUNCTION__);}
/*确保上报成功的线程*/
static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
{return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
}TSbacks sTSCallbacks = {callback,create_thread_callback,
};  JNIEXPORT void JNICALL Java_com_android_settings_Calibration_tsInit(JNIEnv *env, jobject obj)
{if(mCallbacksObj == NULL)mCallbacksObj = env->NewGlobalRef(obj);/*建立对象的句柄,在以后的反调中使用*/ts_init(&sTSCallbacks);/*传递参数,填充结构体*/}JNIEXPORT void JNICALL Java_com_android_settings_Calibration_tsOver(JNIEnv *env, jobject obj)
{LOGI("---------Hello World JNITest!---------");  ts_over();}JNIEXPORT jstring JNICALL Java_com_android_settings_Calibration_getTS(JNIEnv *env, jobject obj)
{LOGI("---------Hello World JNITest!---------");get_input();return env->NewStringUTF("Hello JNITest!");}static JNINativeMethod gMethods[] = {{"tsInit",       "()V",                (void *)Java_com_android_settings_Calibration_tsInit},{"tsOver",      "()V",                (void *)Java_com_android_settings_Calibration_tsOver},{"getTS",       "()Ljava/lang/String;",       (void *)Java_com_android_settings_Calibration_getTS}}; /*注册对应的函数列表*/
int register_com_android_jnitest(JNIEnv* env) {static const char* const kClassName ="com/android/settings/Calibration";jclass clazz;/* look up the class */clazz = env->FindClass(kClassName);if (clazz == NULL) {LOGE("Can't find class %s\n", kClassName);return -1;}else {LOGE("I can find class %s\n", kClassName);method_reportTS = env->GetMethodID(clazz, "reportTS", "(I)V");         }return jniRegisterNativeMethods(env, kClassName, gMethods, NELEM(gMethods));   }/* This function will be call when the library first be load.* You can do some init in the libray. return which version jni it support.*/
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)/*这个函数首先执行*/
{JNIEnv *env = NULL;LOGI("JNI_OnLoad!");if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {LOGE("ERROR: GetEnv failed");return -1;}register_com_android_jnitest(env);return JNI_VERSION_1_4;
}}

其中ts_input.cpp函数实现上述的ts_init(&sTSCallbacks)等函数

void get_input(int n)
{int rd, i;struct input_event ev[64];int step = 0;while (1) {LOGI("while-------------2----------------");/* read ts input */rd = read(ts_fd, ev, sizeof(struct input_event) * 64);if (rd < (int) sizeof(struct input_event)) {LOGI("Read input error");continue;}for (i = 0; i < (int)(rd / sizeof(struct input_event)); i++) {switch (ev[i].type) {case EV_SYN:if (step){LOGI("-------------return-------------");return;}    case EV_KEY:if (ev[i].code == BTN_TOUCH && ev[i].value == 0)/* get the final touch */step = 1;LOGI("--------------key-------------");break;case EV_ABS:if (ev[i].code == REL_X){tx[n] = ev[i].value;LOGI("-----ev[i].value---*px-----%d------", ev[i].value);}      else if (ev[i].code == REL_Y){    ty[n] = ev[i].value;LOGI("----ev[i].value----*py-----%d------", ev[i].value);}   break;default:break;}}}}static void *ts_thread(void *arg)
{for(n = 0; n < 3;){get_input(n);if(check_cali(n)){ n++;ts_state->callbacks.ts_cb(1);/*实现上报*/}elsets_state->callbacks.ts_cb(0);}    do_calulate();return NULL;
}int ts_init(TSbacks *pTSbacks)
{//init the ts_9052 driver to get the locationwrite_conf(data);struct stat s;int i;int x,y;for (i = 0; ; i++) {/* open touchscreen input dev */char ts_dev[256];char name[256] = "Unknow";sprintf(ts_dev, "%s%d", input_dev, i);if (stat(ts_dev, &s) != 0) {LOGI("can not find ts device");return 0;}ts_fd = open(ts_dev, O_RDWR);if (ts_fd < 0) {LOGI("Failed to open %s", ts_dev);continue;}ioctl(ts_fd, EVIOCGNAME(sizeof(name)), name);LOGI("%s: get name: %s", ts_dev, name);if (strncmp(name, dev_name, strlen(dev_name)) == 0) {break;} else {LOGI("%s: not %s", ts_dev, dev_name);close(ts_fd);continue;}}get_conf();    ts_state->callbacks = *pTSbacks;            ts_state->thread = ts_state->callbacks.create_thread_cb("da9052", ts_thread, ts_state);return 0;
}int ts_over()
{return close(ts_fd);}

在java文件中再对对应的情况进行处理

public void reportTS(int i){if(0 == i){    Intent intent = new Intent(ACTION_WRONG);mContext.sendBroadcast(intent);}else if(1 == i){n++;if(n != 3){Intent intent = new Intent(ACTION_OK);mContext.sendBroadcast(intent);}else if(3 == n){Intent intent = new Intent(ACTION_FINISH);mContext.sendBroadcast(intent);}}}

这里就能对应用程序中的十字叉UI进行交互从而实现触摸校准。

经过这些流程的处理,不禁对网上一些触摸程序产生怀疑,真不知是怎么实现触摸的,随意下了个apk确实没什么影响

这里对文件的读写需要权限,就不知道在应用程序中需要声明什么,可以有修改文件的权限,就到这里。

Android电阻触摸屏校准相关推荐

  1. RK3288 10.1寸电阻触摸屏调试与校准软件的运行

    作者:Dennis 电话:13349909990(微信同号) 邮箱:dennis@we-signage.com 说明:本文所提供的技术方案适用于 恒耀源科技有限公司 RK3288主板以及使用该主板的所 ...

  2. [转]Android 触摸屏校准

    Android 触摸屏校准 话接上回,我们发现了手工利用 tslib 校验触摸屏的缺点.那么这一回 我们就来一次稍微高级一点的校验吧. 我们其实只需要相对的 x,y 以及lcd的 x,y 就可以把校验 ...

  3. STM32F407 TFT电阻触摸屏 四点校准法

    STM32F407 TFT电阻触摸屏 四点校准法 提示:STM32F407在使用3.2英寸TFT电阻触摸屏时,应该对其进行校准. 一.算法说明 电阻触摸屏由触摸屏(TS)和LCD屏上下两层组成. 采用 ...

  4. tsc2007电阻触摸屏调试

    #触摸屏调试 开发环境:ubuntu12.04LTS Android核心板型号:Samsung6818 电阻触摸屏型号:tsc2007 作者:@happyguy96 && @ccxx0 ...

  5. android系统触摸屏虚拟按键

     (一)虚拟按键的描述可以见 韩超和梁泉的 <Android系统级深入开发--移植与调试>的第八章: 虚拟按键(Virtual Key)是Eclair版本开始增加的新特性.Virtual  ...

  6. android电容触摸屏的驱动及其上层工作原理,android 电容屏(一):电容屏基本原理篇...

    关键词:android  电容屏 tp  ITO 平台信息: 内核:linux2.6/linux3.0 系统:android/android4.0 平台:S5PV310(samsung exynos ...

  7. 禾瑞亚USB接口电阻触摸屏控制卡QNX 6.5 RTOS操作系统x86架构驱动安装与配置方法

    禾瑞亚USB接口电阻触摸屏控制卡QNX 6.5 RTOS操作系统x86架构驱动安装与配置方法 前提条件:安装QNX 6.5 RTOS操作系统的主板的USB接口必须能够被操作系统识别,否则连接不到触摸屏 ...

  8. 【手拉手 带你准备电赛】原来你是这样的触摸屏(电阻触摸屏)

    在我们的生活中,触摸屏可以说是无处不在.在各种触控面板我们都可以看到触摸屏的身影,一些产品也因为有了触摸屏而价值大涨.接下来,小蛋糕带你深入了解触摸屏. 触摸屏可以分为电阻式触摸屏和电容式触摸屏,在这 ...

  9. linux内核关闭触摸屏校准,触摸屏校正原理

    1,触摸屏校准通用方法 主要采用以下公式,实现触摸屏校正,其中XL, YL是显示屏坐标,XT, YT是触摸屏坐标, XL = XT*A+YT*B+C; YL = XT*D+YT*E+F;    公式( ...

最新文章

  1. 商汤科技总裁张文谈人工智能: 未来10年到20年会有巨大爆发 下一个井喷是AI+教育
  2. C++ MFC界面读写USB HID设备数据程序
  3. AI开发者大会:2020年7月3日09:30--09:50司罗《为商业搭建语言桥梁》
  4. STM32开发 -- 蓝牙开发详解(1)
  5. 织梦CMS AJAX分页,可自定义typeid,调取任意内容
  6. 如何优化myeclipse.
  7. springcloud生产环境一般怎么部署_生产环境遇到这些ogg报错该怎么处理?
  8. 第一台全自动电子计算机,关于世界上第一台电子计算机ENIAC的叙述错误的是() senny全自动微电脑水位控制仪...
  9. Java基础知识总结(2021版)
  10. 看黑马程序员视频学习之节点操作之复制节点
  11. jQuery 身份证验证
  12. 伯努利分布、泊松分布
  13. 招聘管理系统软件java源码_基于Spring Boot的java开源招聘源码-铭阳招聘管理系统...
  14. Android 怎么防止多并发请求?比如说一个页面需要请求多个接口,可以跟后台网络交互能做哪些性能优化
  15. Virtualbox 学习 — network setting
  16. [ app.json 文件内容错误] app.json: window.navigationBarTextStyle 字段需为 black,white【已解决】
  17. 我研究我自己!苏炳添博士重磅论文:我怎么跑这么快?
  18. python面向对象-2
  19. Structured Streaming 编程模型
  20. 曾鸣:取势、明道、立理、优术

热门文章

  1. Js做的城市三级联动
  2. 汉语树库/CoNLL格式,依存句法分析语料
  3. 5W字讲解最新大数据面试题
  4. 关于用户生命周期分析的总结
  5. 【深度之眼cs231n第七期】笔记(四)
  6. linux装好了启动不了系统,Linux系统不能启动怎么办
  7. 论文阅读笔记之手术器械分类的注意约束自适应核选择网络(SKA-ResNet)(一)
  8. Flutter 必须知道的布局规则
  9. 咸鱼怎么翻身?非计算机专业26岁转行Java,坚持了三年终于年薪36W+
  10. keystone对接ldap