Linux3.4.2的触摸屏驱动分析与编写 您所在的位置:网站首页 linux触屏驱动安装 Linux3.4.2的触摸屏驱动分析与编写

Linux3.4.2的触摸屏驱动分析与编写

2022-03-27 06:26| 来源: 网络整理| 查看: 265

开发环境: 开发板:JZ2440V3 CPU:samsunS3C2440 内核:Linux3.4.2 编译工具:arm-linux-gcc 4.3.2 LCD:4.3存液晶屏AT043TN24 参考文献: 2_触摸屏驱动程序之编写驱动 (100ask.net)

触摸屏使用过程:

触摸屏某点被按下,产生INT_TC中断; 在中断处理程序中,打开定时器 定时器时间到,启动ADC转换,得到x和y坐标; ADC结束,产生ADC中断; 、在ADC中断处理函数里,上报(input_event),启 抬起,松开屏幕 1、编写基本框架(s3c_ts.c) #include #include #include #include #include #include #include #include #include #include #include #include static struct input_dev *s3c_ts_dev; static int s3c_ts_init(void) { /* 1. 分配一个input_dev结构体 */ s3c_ts_dev = input_allocate_device(); /* 2. 设置 */ /* 2.1 能产生哪类事件 */ set_bit(EV_KEY, s3c_ts_dev->evbit); set_bit(EV_ABS, s3c_ts_dev->evbit); /* 2.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); /* 3. 注册 */ input_register_device(s3c_ts_dev); /* 4. 硬件相关的操作 */ /* 4.1 使能时钟(CLKCON[15]) */ /* 4.2 设置S3C2440的ADC/TS寄存器 */ return 0; } static void s3c_ts_exit(void) { input_unregister_device(s3c_ts_dev); input_free_device(s3c_ts_dev); } module_init(s3c_ts_init); module_exit(s3c_ts_exit); MODULE_LICENSE("GPL"); 2、分析内核自带触摸屏驱动

先打开JZ2440开发板原理图,查看触摸屏的四根引脚(TSYM、TSYP、TSXM、TSXP)分别接在ADC的——AIN4、5、6、7上面。

image-20210724162954342

通过S3C2440手册搜索发现,这些引脚不需要配置什么寄存器就可以使用。

看一下内核自带的触摸屏驱动(drivers/input/touchscreen/s3c2410_ts.c),找到probe函数,看做了什么事情,

ts.clock = clk_get(dev, "adc"); if (IS_ERR(ts.clock)) { dev_err(dev, "cannot get adc clock source\n"); return -ENOENT; } clk_enable(ts.clock);

这里有个使能时钟的函数:

Tips:在内核启动的时候,为了省电,会把一些不相关的模块给关掉。

怎么关?就是通过设置CLKCON寄存器或者是(Clock Gating Control Register),我们在要用任何模块之前必须把对应的位置1(打开模块时钟)。

内核中,就是通过clk_get 和clk_enable使能模块时钟的。

然后,再看芯片手册上的ADC和触摸屏接口那一章:

The 10-bit CMOS ADC (Analog to Digital Converter) is a recycling type device with 8-channel analog inputs. It converts the analog input signal into 10-bit binary digital codes at a maximum conversion rate of 500KSPS with 2.5MHz A/D converter clock. A/D converter operates with on-chip sample-and-hold function and power down mode is supported. Touch Screen Interface can control/select pads (XP, XM, YP, YM) of the Touch Screen for X, Y position conversion. Touch Screen Interface contains Touch Screen Pads control logic and ADC interface logic with an interrupt generation logic. 这里说的就是这里面有个10位的mos ADC转换器,有8路信道。在ADC工作频率为2.5MHz时,最大转换频率是500KSPS,同时,因为Power Supply Voltage: 3.3V (最大输入电压是3.3v ),所以如果ADC的输入电压是3.3V的话,输出就是10个1(0x3ff),如果是0V的话,输出就是0。每个刻度就是3.3v/10位 10位的话就是1024 就是3.3V/1024 最小刻度是3mv

然后是我们的ADC转换时间

image-20210724170349732

如果PCLK是50MHZ,而ADC最大工作频率是2.5MZ,所以要设置分频系数,把这个频率给降低下来

然后下面就是它提供的例子 the prescaler value is 49, ADC的工作频率就是A/D converter freq. = 50MHz/(49+1) = 1MHz .

转换时间就需要Conversion time = 1/(1MHz / 5cycles) = 1/200kHz = 5us (1MHZ的5个周期 就是5us )

再看下接口模式:

正常的转换模式(Normal Conversion Mode):正常转换模式就是一般的ADC操作,比如说你想测量某个电压。

分离的xy坐标转换模式(Separate X/Y Position Conversion Mode) :这种模式分为两个部分。一种是测量X坐标,一种是测量Y坐标。

进入X或Y坐标模式需要采取的措施是:

1.设置0x69到TSCONn寄存器

2.通过设置TSADCCONn开始转换

3.X坐标转换结束后能被中断给通知

4.从TSDATXn读出坐标转换数据

自动(连续)的XY转换模式(Auto (Sequential) X/Y Position Conversion Mode):当你进入这个模式之后,它会自动的帮你即转换x坐标也转换Y坐标

等待中断模式,就是等待按下产生中断模式:若想在我们按下触摸屏后让它产生中断,就要进入该模式。当触摸笔按下的时候,触摸屏会产生INT_PENn这个中断。

怎么进入这个模式呢?设置rADCTSC=0xd3 就可以了。 3、硬件相关代码编写 3.1 使能时钟 //函数体外定义全局变量clk struct clk* clk; /* 4.1 使能时钟(CLKCON[15]) */ clk = clk_get(NULL, "adc"); clk_enable(clk); 3.2 设置S3C2440的ADC控制寄存器 //函数体外定义寄存器结构体 struct s3c_ts_regs { unsigned long adccon; unsigned long adctsc; unsigned long adcdly; unsigned long adcdat0; unsigned long adcdat1; unsigned long adcupdn; }; //仅在本文件内使用的静态寄存器指针变量 static volatile struct s3c_ts_regs *s3c_ts_regs; //在初始化函数内对寄存器结构体进行地址映射 s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs)); 3.3 设置ADC控制寄存器 ADCCON image-20210725154619162

PRESCEN(bit[14]) : =1 A/D converter prescaler enable

PRSCVL(bit[13:6]): =49 A/D converter prescaler value,最大值为2.5MHz,在此我们取1MHz,所以ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz

SEL_MUX(bit[5:3]):模拟信号输入信道选择,若为普通的AD转换,则可在此选择AIN0-3,我们先不设

STDBM(bit[2]):省电模式选择位,默认为0,我们用的是非省电模式,所以在此可不用设置

READ_START(bit[1]):通过读操作自动启动AD转换,我们在此不选该功能

ENABLE_START(bit[0]): 通过置1手动开启AD转换(转换完成后自动清零),先设为0

s3c_ts_regs->adccon = (1 < > S3C2410/S3C2440 touchscreens 4.2 使用新内核启动并加载自己的触摸屏驱动 //Uboot命令行 tftp 30000000 uImage 或者 nfs 30000000 虚拟机IP:网络文件系统目录/uImage bootm 30000000 //新内核启动后的命令行下 insmod s3c_ts.ko

按下/松开触摸屏进行测试

//新内核启动后的命令行下 pen down pen up # # pen down pen up 5、拓展——按下时启动ADC,显示坐标

修改触摸屏中断处理函数,当触摸屏被按下时,进入TC中断处理函数,自动测量模式并启动ADC转换;

AD转换完成后产生ADC中断,并在中断处理函数中完成相应任务(例如显示x、y点坐标)后,进入等待触摸屏松开模式。

5.1 修改触摸屏(TC)中断处理函数 //触摸屏中断处理函数V2.0 static irqreturn_t pen_down_up_irq(int irq, void *dev_id) { if (s3c_ts_regs->adcdat0 & (1 ERR_LIMIT)) return 0; avr_x = (x[1] + x[2])/2; avr_y = (y[1] + y[2])/2; det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]); det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]); if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT)) return 0; return 1; } 6.3.2 修改adc中断处理函数 static irqreturn_t adc_irq(int irq, void *dev_id) { static int cnt = 0; static int x[4], y[4]; int adcdat0, adcdat1; /* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */ adcdat0 = s3c_ts_regs->adcdat0; adcdat1 = s3c_ts_regs->adcdat1; if (s3c_ts_regs->adcdat0 & (1evbit); /* 2.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); /* 3. 注册 */ input_register_device(s3c_ts_dev); /* 4. 硬件相关的操作 */ /* 4.1 使能时钟(CLKCON[15]) */ clk = clk_get(NULL, "adc"); clk_enable(clk); /* 4.2 设置S3C2440的ADC/TS寄存器 */ s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs)); /* bit[14] : 1-A/D converter prescaler enable * bit[13:6]: A/D converter prescaler value, * 49, ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz * bit[0]: A/D conversion starts by enable. 先设为0 */ s3c_ts_regs->adccon = (1adcdat0 & (1adcdat0 & (1fd, EVIOCGVERSION, &version) >= 0) && 55 (version == EV_VERSION) && 56 (ioctl(ts->fd, EVIOCGBIT(0, sizeof(bit) * 8), &bit) >= 0) && 57 (bit & (1 fd, EVIOCGBIT(EV_ABS, sizeof(absbit) * 8), &absbit) >= 0) && 59 (absbit & (1


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有