【Linux驱动】----TP驱动

一、输入子系统

核心层: Linux_Dir/drivers/input/input.c(提供最核心函数)
设备事件层: Linux_Dir/drivers/input/evdev.c(提供handler)
提供输入设备产生的原始数据并上报给应用程序,这适用于
所有输入设备, 该触摸屏也不例外
编写基于输入子系统的驱动时只需:
1.分配input_dev
2.设置能产生什么事件和这类事件的哪些事件
3. input_register_device注册
4. 硬件操作
在这里插入图片描述

输入子系统需要提供文件读写等函数,在输入子系统中"input.c"中的File_operations结构体中,发现只存在".open"函数

static const struct file_operations input_fops = {
    
    
    .owner = THIS_MODULE,
    .open = input_open_file,
};

在"input_open_file"函数中会发现它依赖其他文件如“evdev.c,keyboard.c”等文件注册的“input_handler”结构(这些结构中提供了 read,write 等函数)。

static int input_open_file(struct inode *inode, struct file *file)
{
    
    
    struct input_handler *handler = input_table[iminor(inode) >> 5];
    const struct file_operations *old_fops, *new_fops = NULL;
    int err;

       .....
    old_fops = file->f_op;
    file->f_op = new_fops;

    err = new_fops->open(inode, file);

    if (err) {
    
    
        fops_put(file->f_op);
        file->f_op = fops_get(old_fops);
    }
    fops_put(old_fops);
    return err;
}

在这里插入图片描述
触摸屏也是用上面这一套框架来操作的。右边需要一个“evdev.c”文件。左边要分配一个
“input_dev”结构。接着就看上图的硬件设备左边的过程:
分配一个“input_dev”结构体 --> 设置这个"input_dev"结构体 --> 注册这个"input_dev"
结构体 --> 硬件相关的操作。

二、触摸屏硬件原理

在这里插入图片描述

在这里插入图片描述

三、s3c2440 AD控制器

  • A/D converter freq. = 50MHz/(49+1) = 1MHz
  • Conversion time = 1/(1MHz / 5cycles) = 1/200KHz = 5 us
    需要设置合适的时钟给触摸屏模块,在实验设为1MHz
    驱动程序需要通过clk_get和clk_enable使能ADC模块设置adccon的第bit6为49,使得触摸屏时钟为1MHZ
	clk = clk_get(NULL, "adc");
	clk_enable(clk);

自动的X/Y坐标转换模式,把X坐标存入寄存器ADCDAT0,把Y坐标存入ADCDAT1,驱动程序中可以读
ADCDAT0/1的BIT15获得 转换后的X/Y坐标

等待触摸笔按下或者松开模式,可以通过判断ADCTSC的BIT8是否被设置来知道是等待松开还是等待按下

四、触摸屏使用流程

1.能产生哪类事件

	set_bit(EV_KEY, s3c_ts_dev->evbit); //设置input_dev的evdev数组中的EV_KEY位
    set_bit(EV_ABS, s3c_ts_dev->evbit);//设置input_dev的evdev数组中的EV_ABS位

2.设置产生这类事件的哪些件

    set_bit(BTN_TOUCH, s3c_ts_dev->keybit);

    input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
    input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
    input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);

BIN_TOUCH: 触摸"按键"事件
ABS_X/ABS_Y: X/Y绝对位移
ABS_PRESSURE: 绝对位移压力事件

3.硬件操作

    s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));//ioremap寄存器
    
    s3c_ts_regs->adcdly = 0xffff;//设置ADCDLY为最大值, 这使得电压稳定后再发出IRQ_TC中断
    
    request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
    request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);

五、代码参考

https://gitee.com/change-ly/linux_drv

猜你喜欢

转载自blog.csdn.net/weixin_45281868/article/details/127129766