TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码

i.MX6ULL驱动开发13:电容触摸驱动实践(下)

2025-07-29
/
0 评论
/
3 阅读
/
正在检测是否收录...
07/29

在上一篇文章中,我们已经完成了i.MX6ULL电容触摸屏驱动的框架搭建和设备树配置。今天,我们将深入实现驱动核心功能,完成从硬件中断到用户空间坐标上报的完整流程。

中断处理机制实现

电容触摸屏通常采用中断方式通知SOC有触摸事件发生。在我们的驱动中,需要正确配置和实现中断处理函数:

c
static irqreturnt ft5x06tsinterrupt(int irq, void *devid)
{
struct ft5x06data *data = devid;
struct input_dev *input = data->input;
u8 buf[32];
int ret, i;

/* 读取触摸点数据 */
ret = ft5x06_read_data(data->client, buf, sizeof(buf));
if (ret < 0) {
    dev_err(&data->client->dev, "读取触摸数据失败\n");
    goto out;
}

/* 解析多点触控数据 */
for (i = 0; i < FT5X06_MAX_TOUCH_POINTS; i++) {
    u8 *touch = &buf[i * FT5X06_TOUCH_STEP + FT5X06_TOUCH_X_H];

    if (touch[0] & FT5X06_TOUCH_EVENT_FLAG_PRESS) {
        input_mt_slot(input, i);
        input_mt_report_slot_state(input, MT_TOOL_FINGER, true);

        /* 上报坐标 */
        input_report_abs(input, ABS_MT_POSITION_X, 
                       (touch[0] & 0x0F) << 8 | touch[1]);
        input_report_abs(input, ABS_MT_POSITION_Y,
                       (touch[2] & 0x0F) << 8 | touch[3]);
    } else if (touch[0] & FT5X06_TOUCH_EVENT_FLAG_RELEASE) {
        input_mt_slot(input, i);
        input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
    }
}

input_sync(input);

out:
return IRQ_HANDLED;
}

输入子系统集成

Linux输入子系统为触摸设备提供了标准接口,我们需要正确配置input_dev:

c
static int ft5x06tsprobe(struct i2cclient *client, const struct i2cdevice_id *id)
{
// ...初始化代码...

/* 设置输入设备 */
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev) {
    dev_err(&client->dev, "分配输入设备失败\n");
    return -ENOMEM;
}

input_dev->name = FT5X06_TS_NAME;
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;

/* 设置输入事件 */
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);

/* 设置多点触控参数 */
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
                    0, data->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
                    0, data->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
                    0, 255, 0, 0);
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR,
                    0, 255, 0, 0);

/* 注册输入设备 */
ret = input_mt_init_slots(input_dev, FT5X06_MAX_TOUCH_POINTS, 0);
if (ret) {
    dev_err(&client->dev, "初始化MT slots失败\n");
    return ret;
}

ret = input_register_device(input_dev);
if (ret) {
    dev_err(&client->dev, "注册输入设备失败\n");
    return ret;
}

// ...其他初始化...

}

设备树配置优化

完整的设备树节点配置应包括中断、复位引脚和电源管理:

dts
&i2c1 {
status = "okay";

ft5x06_ts: touchscreen@38 {
    compatible = "edt,edt-ft5x06";
    reg = <0x38>;
    interrupt-parent = <&gpio1>;
    interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
    reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
    touchscreen-size-x = <800>;
    touchscreen-size-y = <480>;
    touchscreen-inverted-x;
    touchscreen-swapped-x-y;
    wakeup-source;
};

};

TSLIB校准与测试

TSLIB是Linux下常用的触摸屏校准和测试工具集,我们需要在系统中配置和使用它:

  1. 首先确保内核配置支持evdev输入:
    CONFIG_INPUT_EVDEV=y

  2. 在目标板上安装TSLIB:
    bash opkg install tslib tslib-calibrate tslib-tests

  3. 配置环境变量:
    bash export TSLIB_TSDEVICE=/dev/input/event1 export TSLIB_CALIBFILE=/etc/pointercal export TSLIB_CONFFILE=/etc/ts.conf export TSLIB_PLUGINDIR=/usr/lib/ts

  4. 执行校准:
    bash ts_calibrate

  5. 测试触摸响应:
    bash ts_test

PM电源管理实现

为完善驱动,我们还需要实现电源管理功能:

c
static int __maybeunused ft5x06tssuspend(struct device *dev) { struct i2cclient *client = to_i2c_client(dev);
struct ft5x06_data *data = i2c_get_clientdata(client);

/* 禁用中断 */
disable_irq(client->irq);

/* 进入低功耗模式 */
ft5x06_write_reg(client, FT5X06_POWER_MODE_REG, FT5X06_POWER_MODE_SLEEP);

return 0;

}

static int __maybeunused ft5x06tsresume(struct device *dev) { struct i2cclient *client = to_i2c_client(dev);
struct ft5x06_data *data = i2c_get_clientdata(client);

/* 从低功耗唤醒 */
ft5x06_write_reg(client, FT5X06_POWER_MODE_REG, FT5X06_POWER_MODE_ACTIVE);

/* 重新初始化芯片 */
ft5x06_chip_init(client);

/* 启用中断 */
enable_irq(client->irq);

return 0;

}

调试技巧

在驱动开发过程中,有效的调试手段至关重要:

  1. 使用printk输出调试信息:
    c dev_dbg(&client->dev, "坐标: x=%d, y=%d\n", x, y);

  2. 通过sysfs导出调试接口:c
    static ssizet ft5x06regshow(struct device *dev, struct deviceattribute *attr, char *buf)
    {
    // 实现读取寄存器值
    }

static ssizet ft5x06regstore(struct device *dev, struct deviceattribute *attr,
const char *buf, size_t count)
{
// 实现写入寄存器值
}

static DEVICEATTR(reg, 0644, ft5x06regshow, ft5x06reg_store);

// 在probe函数中注册
devicecreatefile(&client->dev, &devattrreg);

  1. 使用内核事件跟踪:
    bash cat /sys/kernel/debug/tracing/trace_pipe

常见问题排查

  1. 触摸无反应



    • 检查I2C通信是否正常
    • 确认中断引脚配置正确
    • 验证电源供电稳定
  2. 坐标不准确



    • 重新运行ts_calibrate
    • 检查设备树中的屏幕尺寸参数
    • 确认是否设置了正确的xy反转标志
  3. 多点触控失效



    • 确认内核配置了CONFIGINPUTMULTITOUCH
    • 检查inputmtinit_slots调用是否正确
    • 验证固件支持多点触控

性能优化建议

  1. 调整中断触发方式,通常边缘触发比电平触发更高效
  2. 实现触摸点跟踪,减少input_sync调用次数
  3. 在非活动状态下降低采样率
  4. 使用DMA进行I2C数据传输(如果支持)
i.MX6ULLLinux驱动电容触摸屏input子系统中断处理多点触控设备树配置TSLIB校准
朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/34267/(转载时请注明本文出处及文章链接)

评论 (0)

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月

最新回复

  1. 强强强
    2025-04-07
  2. jesse
    2025-01-16
  3. sowxkkxwwk
    2024-11-20
  4. zpzscldkea
    2024-11-20
  5. bruvoaaiju
    2024-11-14

标签云