电容触摸屏调试要点:
1. 确定触摸IC的I2C设备地址
2. 根据数据手册确定I2C设备数据读写函数是否符合时序
3. 确保I2C能正常通信上报坐标点。
4. 确定TP的固件规定的上报的x,y坐标的最大值。
5. 调试上报给上层上报的数据
对于TP的调试,一般公司会要求TP原厂做多大的分辨率的TP固件,我接触到的这个TP是公司要求TP原厂做的固件为1280*800,并拿到了一份TP原厂给的TP源码,我的目的是让TP能够运用在UT4412BV02开发板上。
下面以笔者接触的GT928触摸屏为例分析触摸屏驱动。
1.首先确定TP与UT4412BV02开发板的硬件连接。
从原理图的连接我们可以得到TP的控制IO
GPX0_4 ------------- CTP-INT
CTSn2_33 /SDA-------------GPA1_2
RTSn2_33 /SCL------------- GPA1_3
TP原厂代码分析
注:下面分析的代码为调试好的代码,并在原厂提供的代码的基础上精简了很多。以便于学习。由于篇幅幅有限,下面只分析重点部分。
static const struct i2c_device_id goodix_ts_id[] = {
{ GTP_I2C_NAME, 0 },//初始化设备ID
};
static struct i2c_driver goodix_ts_driver = { //i2c驱动结够体的填充
.probe = goodix_ts_probe,
.remove = goodix_ts_remove,
.id_table = goodix_ts_id,
.driver = {
.name = GTP_I2C_NAME,
.owner = THIS_MODULE,
},
};
static int __devinit goodix_ts_init(void)
{
s32 ret;
GTP_DEBUG_FUNC();
GTP_INFO("GTP driver installing...");
goodix_wq = create_singlethread_workqueue("goodix_wq");
if (!goodix_wq)
{
GTP_ERROR("Creat workqueue failed.");
return -ENOMEM;
}
//I2C设备注册函数
ret = i2c_add_driver(&goodix_ts_driver);
return ret;
}
//I2C设备探测的关键函数
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
s32 ret = -1;
struct goodix_ts_data *ts;
u16 version_info;
printk("-------ut_goodix_ts_probe------- ");
//do NOT remove these logs
GTP_INFO("GTP Driver Version: %s", GTP_DRIVER_VERSION);
GTP_INFO("GTP Driver Built@%s, %s", __TIME__, __DATE__);
GTP_INFO("GTP I2C Address: 0x%02x", client->addr);
i2c_connect_client = client;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
{
GTP_ERROR("I2C check functionality failed.");
return -ENODEV;
}
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (ts == NULL)
{
GTP_ERROR("Alloc GFP_KERNEL memory failed.");
return -ENOMEM;
}
memset(ts, 0, sizeof(*ts));
INIT_WORK(&ts->work, goodix_ts_work_func);
ts->client = client;
spin_lock_init(&ts->irq_lock); // 2.6.39 later
i2c_set_clientdata(client, ts);
ts->gtp_rawdiff_mode = 0;
ret = gtp_request_io_port(ts);
if (ret < 0)
{
GTP_ERROR("GTP request IO port failed.");
kfree(ts);
return ret;
}
ret = gtp_i2c_test(client);
if (ret < 0)
{
GTP_ERROR("I2C communication ERROR!");
}
ret = gtp_read_version(client, &version_info);
if (ret < 0)
{
GTP_ERROR("Read version failed.");
}
// ret = gtp_init_panel(ts);
// if (ret < 0)
// {
// GTP_ERROR("GTP init panel failed.");
ts->abs_x_max = GTP_MAX_WIDTH; //X上报的最大值
ts->abs_y_max = GTP_MAX_HEIGHT;//Y上报的最大值
ts->int_trigger_type = GTP_INT_TRIGGER;//中断的触发方式
// }
// Create proc file system
gt91xx_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0666, NULL, &config_proc_ops);
if (gt91xx_config_proc == NULL)
{
GTP_ERROR("create_proc_entry %s failed ", GT91XX_CONFIG_PROC_FILE);
}
else
{
GTP_INFO("create proc entry %s success", GT91XX_CONFIG_PROC_FILE);
}
ret = gtp_request_input_dev(ts);
if (ret < 0)
{
GTP_ERROR("GTP request input dev failed");
}
ret = gtp_request_irq(ts);
if (ret < 0)
{
GTP_INFO("GTP works in polling mode.");
}
else
{
GTP_INFO("GTP works in interrupt mode.");
}
if (ts->use_irq)
{
gtp_irq_enable(ts);
}
return 0;
}
//当手指按下执行的上报坐标的函数。
static void gtp_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)
{
GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w);
#if GTP_ICS_SLOT_REPORT // 此宏为1,
input_mt_slot(ts->input_dev, id);
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
调试过程中主要修改红色的两行代码来确定上报的x,y的方向。
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
#else
input_report_key(ts->input_dev, BTN_TOUCH, 1);
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
input_mt_sync(ts->input_dev);
#endif
}
了解更多的信息在友坚开发板官网:http://www.urbetter.net http://www.urbetter.com.cn
更多问题请到友坚论坛进行发贴讨论:http://bbs.urbetter.com