版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、我的触摸屏驱动源代码 /*C头文件*/#include "au_types.h"#define DEVICE_NAME "tpanel"#define IRQ_1 7#define GPIO_1_PORT
2、; GPIO_1#define GPIO_1_PORT_ADDR GPIO_1_BASE/ 触摸屏返回值结构体typedef struct uint32 pressure; uint32 x; uint32 y;TS_RET;/ 校准值结构体typedef struct int32 x; int32 y;TS_POINT;static TS_POINT T
3、sPoint10;#define TS_IOC_MAGIC 0xd9#define CALIBRATE _IOW(TS_IOC_MAGIC, 1, sizeof(TsPoint)#define CALIBRATE_START _IOW(TS_IOC_MAGIC, 2, sizeof(uint8)/ 以下为触摸屏控制器管脚设置#define ADS7843_CSS() writew(0xff, (GPIO_1
4、_PORT_ADDR + 0x200) / cs = 1 (p1.7)#define ADS7843_CSC() writew(0x00, (GPIO_1_PORT_ADDR + 0x200) / cs = 0#define ADS7843_DCLKS() writew(0xff, (GPIO_1_PORT_ADDR + 0x40) / dclk = 1(p1.4)#define ADS7843_DCLKC() wr
5、itew(0x00, (GPIO_1_PORT_ADDR + 0x40) / dclk = 0#define ADS7843_DINS() writew(0xff, (GPIO_1_PORT_ADDR + 0x20) / din = 1(p.3)#define ADS7843_DINC() writew(0x00, (GPIO_1_PORT_ADDR + 0x20) / din = 0#define ADS7843
6、_DOUTR() readw(GPIO_1_PORT_ADDR + 0x10) / dout p1.2/ ADS7843控制字 #define AIN_X 0xD4#define AIN_Y
7、60; 0x94/ ADS7846控制字/#define AIN_X 0xD0 /#define AIN_Y 0x90 /#define DELAY_200NS
8、0; 200 / 操作时序控制宏(即延时控制值)#define DELAY_200NS 400 / 操作时序控制宏(即延时控制值)#define PEN_DOWN 1 &
9、#160; / 笔按下#define PEN_UP 2 / 笔抬起#define PEN_FLEETING 4 / 笔拖拽#define
10、;MAX_TS_BUF 16 / 最大缓冲区数#define BUF_HEAD (TsDev.bufTsDev.head) / 取队列头值#define BUF_TAIL (TsDev.bufTsDev.tail)
11、160; / 取队列尾值#define INCBUF(x, mod) (+(x) & (mod)-1) / 位移加一#define TS_TIMER_DELAY (HZ/28) / 定时时长为36ms/#define TS_TIMER_DELAY (HZ/15
12、)#define TS_TIMER_DELAY1 (HZ/10) / 定时时长为100ms/*C源代码*/#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/kernel.h> &
13、#160; / printk#include <linux/fs.h> / file结构#include <linux/init.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/poll.h>#include <linux/interr
14、upt.h>#include <linux/devfs_fs_kernel.h>#include <linux/timer.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/ioctl.h>#include "hi_gpio.h"#include "touch_screen.h"#define _CA
15、LIBRATE_ 1 / 使用校准参数,否则使用固定的校准值/ 以下为触摸屏较正用#define SCREEN_WIDTH 800#define SCREEN_HEIGHT 460#define NR_EQUATIONS 6#define LSHIFT(x) (x)<<10)#define RSHIFT(x)
16、 (x)>>12)static int VarsNR_EQUATIONS*4;static int CalibrateOk = FALSE; / 是否校准过#define Vars1 Vars#define Vars2 (Vars + NR_EQUATIONS)#define Vars3 (Vars + NR_EQUATIONS * 2)#define Vars4 (Vars + NR_EQUATIONS * 3)/ 触摸屏设备结构体typedef struct
17、0;uint32 penStatus; TS_RET bufMAX_TS_BUF; uint32 head, tail; wait_queue_head_t wq; spinlock_t lock;TS_DEV;static TS_DEV TsDev;static struct timer_list ts_timer; &
18、#160; / 定义定时器变量static uint32 touch_screen_major = 0; / 触摸屏设备号static uint8 Ready = 1;/* 名称:DelayNo()* 功能:短软件延时。* 入口参数:i 延时参数,值越大,延时越久* 出口参数:无*/void DelayNo(uint32 i) for(; i>0; i-);/* 名称:TestDelayNo()* 功能:测试短软件延时,以便于产生
19、正确的时序。* 入口参数:无* 出口参数:无*/void TestDelayNo(void) while(1) ADS7843_DCLKS(); DelayNo(DELAY_200NS); ADS7843_DCLKC(); &
20、#160; DelayNo(DELAY_200NS); /* 名称:ADS7843_IOInit()* 功能:初始化ADS7843的控制I/O,CS=1,DCLK=0,DIN=0。* 入口参数:无* 出口参数:无*/void ADS7843_IOInit(void) ADS7843_CSS(); / CS = 1 ADS7843_DCLKC();
21、 / DCLK = 0 ADS7843_DINC(); / DIN = 0 DelayNo(DELAY_200NS);/* 名称:ADS7843_IRQR()* 功能:ADS7843的PENIRQ引脚测量,返回当前此引脚的电平值。* 入口参数:无* 出口参数:返回为0表示PENIRQ为低电平状态,否则
22、为高电平。*/uint8 ADS7843_IRQR(void) uint8 dat3; uint8 val; DelayNo(1); val = readw(GPIO_1_PORT_ADDR + 0x80); if(val) dat0 = 1; else dat0 = 0; /DelayNo(1); val = readw(GPIO_1_PORT_ADDR + 0x80);
23、; if(val) dat1 = 1; else dat1 = 0; /DelayNo(1); val = readw(GPIO_1_PORT_ADDR + 0x80); if(val) dat2 = 1; else dat2 = 0; /DelayNo(1); if(dat0 + dat1 + dat2) > 1) return(1);
24、0; else return(0); /* 名称:ADS7843_WriteRead()* 功能:对ADS7843进行读写操作。操作按照ADS7843的规定,* 24Clocks,先写8位控制数据,然后读取12位的转换结果。* 入口参数:data 控制数据* 出口参数:返回值为读出的数据*/ void ADS7843_WriteRead(uint8 data, uint16 *ret) uint8 i;
25、60;uint16 ret_dat; data = data | 0x80; / 设置S位 ADS7843_IOInit(); ADS7843_CSC(); / CS = 0 for(i=0; i<8; i+) if( (data&0x80) != 0 ) ADS7843_DINS()
26、; / DIN = 1 else ADS7843_DINC(); / DIN = 0 DelayNo(DELAY_200NS); ADS7843_DCLKS(); / DCLK = 1 DelayNo(DELAY_200NS);
27、 ADS7843_DCLKC(); / DCLK = 0 data = data<<1; ADS7843_DINC(); / DIN = 0 DelayNo(DELAY_200NS * 3); ADS7843_DCLKS(); / DCLK = 1 DelayNo(DELAY_200NS);
28、ADS7843_DCLKC(); / DCLK = 0 ret_dat = 0; for(i=0; i<12; i+) ret_dat = ret_dat<<1; DelayNo(DELAY_200NS); ADS7843_DCLKS(); / DC
29、LK = 1 if( ADS7843_DOUTR() != 0 ) ret_dat = ret_dat | 1; DelayNo(DELAY_200NS); ADS7843_DCLKC(); / DCLK = 0 if(i = 6)
30、60;DelayNo(DELAY_200NS * 2); for(i=0; i<3; i+) DelayNo(DELAY_200NS); ADS7843_DCLKS(); / DCLK = 1 DelayNo(DELAY_200NS); ADS7843_DCLKC(); / DCLK = 0
31、0; DelayNo(DELAY_200NS); ADS7843_CSS(); / CS = 1 *ret = ret_dat;/* 名称: DoGaussianElimination* 功能:* * 入口参数:* 出口参数:*/ static uint8 DoGaussianElimination(int* x, const TS_POINT* src_pts, const TS_POINT* dst_pts)
32、 int x12, x23, y12, y23, nx12, nx23, ny12, ny23; int numerator, denominator1, denominator2; x12 = (src_pts0.x - src_pts1.x); x23 = (src_pts1.x - src_pts2.x); y12 = (src_pts0.y - src_pts1.y); y23 = (
33、src_pts1.y - src_pts2.y); nx12 = (dst_pts0.x - dst_pts1.x); nx23 = (dst_pts1.x - dst_pts2.x); ny12 = (dst_pts0.y - dst_pts1.y); ny23 = (dst_pts1.y - dst_pts2.y); denominator1 = x12*y23 - x23*y12;
34、60; if (denominator1 = 0) return FALSE; denominator2 = y12*x23 - y23*x12; if (denominator2 = 0) return FALSE;
35、160; numerator = nx12*y23 - nx23*y12; x 0 = LSHIFT (numerator) / denominator1; numerator = nx12*x23 - nx23*x12; x 1 = LSHIFT (numerator) / denominator2; x 2 = LSHIFT (dst_pts 0.x) - x 0 * src_pts 0.x - x 1 * s
36、rc_pts 0.y; numerator = ny12*y23 - ny23*y12; x 3 = LSHIFT (numerator) / denominator1; numerator = ny12*x23 - ny23*x12; x 4 = LSHIFT (numerator) / denominator2; x 5 = LSHIFT (dst_pts 0.y) - x
37、3 * src_pts 0.x - x 4 * src_pts 0.y; return TRUE;/* 名称: SetMouseCalibrationParameters* 功能:* * 入口参数:* 出口参数:*/ static uint8 SetMouseCalibrationParameters(const TS_POINT* src_pts, const TS_POINT* dst_pts) TS_POINT my_src_pts 3; TS_PO
38、INT my_dst_pts 3; my_src_pts0 = src_pts0; my_src_pts1 = src_pts1; my_src_pts2 = src_pts4; my_dst_pts0 = dst_pts0; my_dst_pts1 = dst_pts1; my_dst_pts2 = dst_pts4; if (!DoGauss
39、ianElimination(Vars1, my_src_pts, my_dst_pts) return FALSE; my_src_pts0 = src_pts1; my_src_pts1 = src_pts2; my_src_pts2 = src_pts4; my_dst_pts0 = ds
40、t_pts1; my_dst_pts1 = dst_pts2; my_dst_pts2 = dst_pts4; if (!DoGaussianElimination(Vars2, my_src_pts, my_dst_pts) return FALSE; my_src_pts0 = src_pt
41、s2; my_src_pts1 = src_pts3; my_src_pts2 = src_pts4; my_dst_pts0 = dst_pts2; my_dst_pts1 = dst_pts3; my_dst_pts2 = dst_pts4; if (!DoGaussianElimination(Vars3, my_src_pts, my_dst_pts)
42、; return FALSE; my_src_pts0 = src_pts0; my_src_pts1 = src_pts3; my_src_pts2 = src_pts4; my_dst_pts0 = dst_pts0; my_dst_pts1 = dst_pts3; &
43、#160; my_dst_pts2 = dst_pts4; if (!DoGaussianElimination(Vars4, my_src_pts, my_dst_pts) return FALSE; #if 0 printf("Vars:"); int i; for (i=0; i<4*NR_EQUATION
44、S; i+) if (i>0 && !(i%4) printf("n"); printf("%dt", Varsi); printf("n");#endif return TRUE;/* 名称: DoMouseCalibrate* 功能: 校准* * 入口参数:* 出口参数:*/ int32 DoMou
45、seCalibrate(uint16 * x0, uint16 * y0) #ifdef _CALIBRATE_ / 使用校准参数,否则使用固定的校准值 int x = *x0; int y = *y0; int x1, y1, x2, y2, x3, y3, x4, y4; printk("src: x:%4d y:%4dn", x, y); x1 = Vars10 * x + Vars11
46、 * y + Vars12; y1 = Vars13 * x + Vars14 * y + Vars15; x2 = Vars20 * x + Vars21 * y + Vars22; y2 = Vars23 * x + Vars24 * y + Vars25; x3 = Vars30 * x + Vars31 * y + Vars32; y3 = Vars33 * x + Vars34 * y + Vars35;&
47、#160; x4 = Vars40 * x + Vars41 * y + Vars42; y4 = Vars43 * x + Vars44 * y + Vars45; x = RSHIFT(x1 + x2 + x3 + x4); y = RSHIFT(y1 + y2 + y3 + y4); if (x < 0) x = 0; else if (x > SCREEN_WIDTH) x = SCR
48、EEN_WIDTH; if (y < 0) y = 0; else if (y > SCREEN_HEIGHT) y = SCREEN_HEIGHT; *x0 = x; *y0 = y; printk("des: x:%4d y:%4dn", x, y);#else #define TOUCH_LEFT (709) /1
49、00 #define TOUCH_TOP (1093) /400 #define TOUCH_RIGHT (3369) /100 #define TOUCH_BOTTOM (3215) /700 int32 ScaleX = (TOUCH_RIGHT - TOUCH_LEFT) * 10 / 600; /10倍 int32 ScaleY = (TOUCH_BOTTOM - TOUCH_TOP) * 10
50、/ 300; /10倍 int32 x, y; x = *x0; y = *y0; x = (x-TOUCH_LEFT)*10 / ScaleX + 100; y = (y-TOUCH_TOP)*10 / ScaleY + 100; if (x<0) x = 0; if (x>SCREEN_WIDTH) x = SCREEN_WIDTH; if (y<0) y
51、= 0; if (y>SCREEN_HEIGHT) y = SCREEN_HEIGHT; *x0 = x; *y0 = y; printk("*x:%dt y%dn", x, y);#endif return TRUE;/* 名 称:get_lcd_xy* 功 能:读取触摸屏上触摸点的坐标。*
52、160; 程序会一直等待,直到有触摸输入。* 入口参数:x 用于保存触摸点x坐标(LCD)的变量指针* y 用于保存触摸点y坐标(LCD)的变量指针* 出口参数:无* 说 明:先通测量y轴的触摸输入,判断是否有触摸动作。如果有,则进行数据采集,* 并进行去极值平均滤
53、波处理。最后还要判断触摸输入是否合法,只有* 当触摸输入合法时才返回。*/int32 get_lcd_xy(uint16 *vx, uint16 *vy) static uint8 i, temp; static uint16 vx_dat = 0; static uint16 vy_dat = 0; static u
54、int16 x_max_data = 0; static uint16 x_min_data = 0; static uint16 y_max_data = 0; static uint16 y_min_data = 0; static uint32 x_sum = 0; static uint32 y_sum = 0; / 屏校准后不读取拖动状态的数据,只有按下和抬起有发送给GUI if (TsD
55、ev.penStatus = PEN_FLEETING) && (CalibrateOk = TRUE) return -1; while(1) / 进行数据采集 ADS7843_WriteRead(AIN_X, &vx_dat); x_ma
56、x_data = vx_dat; x_min_data = vx_dat; x_sum = vx_dat; ADS7843_WriteRead(AIN_Y, &vy_dat); y_max_data = vy_dat; y_min_data = vy_dat; y_sum = vy_dat; for (i = 1; i <
57、; 21; i+) udelay(100); temp = ADS7843_IRQR(); if (temp != 0) break; ADS7843_WriteRead(AIN_X, &vx_dat); if (vx_dat > x_max_data)
58、0; x_max_data = vx_dat; if (vx_dat < x_min_data) x_min_data = vx_dat; x_sum += vx_dat; ADS7843_WriteRead(AIN_Y, &vy_da
59、t); if (vy_dat > y_max_data) y_max_data = vy_dat; if (vy_dat < y_min_data) y_min_data = vy_dat; y_sum += vy_dat; &
60、#160;#if 1 / 去极值求平均值 /* if (x_max_data - x_min_data) > 200) return -1; if (y_max_data - y_min_data) > 200) return -1; */ if (i < 3)
61、 return -1; *vx = (x_sum - x_max_data - x_min_data) / (i-2); *vy = 4096 - (y_sum - y_max_data - y_min_data) / (i-2); /printk("1.x:%d y:%d i = %dn", *vx, *vy, i); printk("1.x:%d y:%d
62、n", *vx, *vy); #else / 取极值求平均值 *vx = (x_max_data + x_min_data) / 2; *vy = 4096 - (y_max_data + y_min_data) / 2; printk("2.x:%d y:%dn", *vx, *vy); #endif #ifdef _CALIBRATE_ / 使用校准参
63、数校准,否则使用固定参数校准 if (CalibrateOk = TRUE) DoMouseCalibrate(vx, vy); / 触摸屏校准 #else DoMouseCalibrate(vx, vy); #endif return 0;
64、160; /* Function: ts_put_value Description: 将采样到的数据填充到队列中并唤醒进程来读取 Input: 1. x 横坐标 2. y 纵坐标 Output: 无 Return: 无 Others:*/static void ts_put_value(uint16 x, uint16 y) BUF_H
65、EAD.x = x; BUF_HEAD.y = y; BUF_HEAD.pressure = TsDev.penStatus; TsDev.head = INCBUF(TsDev.head, MAX_TS_BUF); Ready = 1; wake_up_interruptible(&(TsDev.wq);/* Function: ts_get_value Description: 从队列中读取采样到的数据 Input: 无 Out
66、put: 1. 采样到的值 Return: 成功-采样到值的字节数,失败= -1 Others:*/static uint32 ts_get_value(TS_RET *ts_ret) /printk("touchscreenko ts_get_value_1n"); if (TsDev.head != TsDev.tail) ts_ret->x = BUF_TAIL.x; ts_ret->y =
67、BUF_TAIL.y; ts_ret->pressure = BUF_TAIL.pressure; TsDev.tail = INCBUF(TsDev.tail, MAX_TS_BUF); /printk("touchscreenko ts_get_value_2n"); return sizeof(TS_RET); else Ready = 0; ret
68、urn -1; /* Function: gpio_init Description: GPIO初始化 Input: 无 Output: 无 Return: 无 Others:*/void gpio_init(void) int32 tmp; / 设置GPIO1方向 gpio_dirgetbyte(GPIO_1_PORT, &tmp); printk(&
69、quot;gpio_init-:0x%xn",GPIO_1_PORT); tmp |= 0x98; / 设置gpio1的3,4,7为输出 tmp &= 0xDB; / 设置gpio1的2,5为输入 gpio_dirsetbyte(GPIO_1_PORT, tmp); / 设置GPIO1中的5为中断口
70、60;gpio_interruptset_byte( GPIO_1_PORT, 0x20,0,0,1 / SENSE_BOTH, / SENSE_LEVEL,
71、60; / EVENT_FALLING_EDGE ); / 屏蔽GPIO1.5中断 tmp = 0x20; gpio_interruptdisable_byte(GPIO_1_PORT, tmp); / 清除GPIO1.5中断标志 gpio_interruptclear_byte(GPIO_1_PORT,tmp); / 使能GPIO1.5中断 gpio_interruptenable_byte(GPIO_1_P
72、ORT,tmp);/* Function: ts_interrupt Description: 触摸屏中断处理 Input: 无 Output: 无 Return: 无 Others:*/static irqreturn_t ts_interrupt(int32 irq, void *dev_id, struct pt_regs *reg) int32 handled = 0; uint8
73、 current_irq; int32 tmp; printk(KERN_NOTICE "ENTER INTE"); tmp = 0x20; gpio_interruptdisable_byte(GPIO_1_PORT, tmp); / 查询该管脚中断是否匹配上 current_irq = readw(GPIO_1_PORT_ADDR + GPIO_RIS); current_irq = current_irq &a
74、mp; tmp; / 读取中断管脚上的电平 tmp = ADS7843_IRQR(); if (current_irq = 0 | tmp != 0) / 中断没匹配上或中断管脚上的电平不为低则不处理 tmp = 0x20; gpio_interruptclear_byte(GPIO_1_PORT, tmp); gpio_interruptenable_byte(GPIO_1_PORT, tmp); else
75、 /printk("pen_downn"); TsDev.penStatus = PEN_DOWN; / 笔状态置为按下 ts_timer.expires = jiffies + TS_TIMER_DELAY; add_timer(&ts_timer); / 启动定时器 /printk("ts_interruptn&quo
76、t;); handled = 1; return IRQ_RETVAL(handled);/* Function: ts_timer_handler Description: 定时器处理 Input: 无 Output: 无 Return: 无 Others:*/static void ts_timer_handler(unsigned long data) int3
77、2 temp; static uint16 x = 0; static uint16 y = 0; / 读取中断管脚上的电平 temp = ADS7843_IRQR(); if (temp = 0) / 去抖处理 /printk("PEN_FLEETINGn"); temp = get_lcd_xy(&x, &y);
78、; / 读取触摸屏的值 if (temp = 0) ts_put_value(x, y); / 把笔状态与触摸屏的值加入到队列中 TsDev.penStatus = PEN_FLEETING; / 下一个状态改为拖拽 ts_timer.expires = jiffies + TS_TIME
79、R_DELAY1; add_timer(&ts_timer); else if (TsDev.penStatus != PEN_UP) del_timer(&ts_timer); if (TsDev.penStatus = PEN_FLEETING) TsDev.penStatus = PEN_UP; ts_put_value(x, y); / 把抬笔状态加入到队列中 TsDev.penStatus = PEN_UP; temp = 0x20; gpio_interruptclear_byte(GPIO_1_PORT, temp); gpio_
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论