模块加载后打印出水平和垂直方向的ad转换结果,没有做坐标的转换,只为学习一下touch screen接口的编程方法,代码记录如下:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct input_dev *ts_dev; //定时器用于处理长按和滑动 static struct ts_regs_t{ unsigned long adccon; unsigned long adctsc; unsigned long adcdly; unsigned long adcdat0; unsigned long adcdat1; unsigned long adcupdn; }; static volatile struct ts_regs_t *ts_regs; static volatile unsigned long *clkcon; static struct clk *adc_clk; static struct timer_list ts_timer; void enable_adc_clock(void){ (*clkcon) |= (1<<15); } void enter_wait4down_mode(void){ ts_regs->adctsc = 0xd3; //等待中断模式,检测触摸屏按下 } void enter_wait4up_mode(void){ ts_regs->adctsc = 0x1d3; //等待中断模式,检测触摸屏松开 } //进入测量xy坐标的工作模式 void enter_measure_xy_mode(void){ ts_regs->adctsc = (1<<3)|(1<<2); } //启动ac转换 void start_adc(void){ ts_regs->adccon |= (1<<0); } //adc中断处理函数 static irqreturn_t grh_handle_adc_irq(int irq, void *dev_id){ static int adc_count = 0; static int xv=0, yv=0; if(ts_regs->adcdat0 & (1<<15)){ enter_wait4down_mode(); adc_count = 0; xv = yv = 0; } else{ //多次取值取平均值 if(adc_count == 4){ printk(KERN_EMERG"count=%d x=%d y=%dr", adc_count, xv>>2, yv>>2); //上报事件 input_report_abs(ts_dev, ABS_X, xv>>2); input_report_abs(ts_dev, ABS_Y, yv>>2); input_report_abs(ts_dev, ABS_PRESSURE, 1); input_report_key(ts_dev, BTN_TOUCH, 1); input_sync(ts_dev); adc_count = 0; xv = yv = 0; enter_wait4up_mode(); mod_timer(&ts_timer, jiffies+HZ/100); //10ms } else{ adc_count ++; xv += (ts_regs->adcdat0)&0x3ff; yv += (ts_regs->adcdat1)&0x3ff; enter_measure_xy_mode(); start_adc(); } } return IRQ_HANDLED; } //tc中断处理函数 static irqreturn_t grh_handle_tc_irq(int irq, void *dev_id){ if(ts_regs->adcdat0 & (1<<15)){ //printk(KERN_EMERG"pen up!n"); enter_wait4down_mode(); } else{ //printk(KERN_EMERG"pen downn"); //enter_wait4up_mode(); enter_measure_xy_mode(); start_adc(); } return IRQ_HANDLED; } //定时器超时处理函数 static void grh_handle_timer_int(unsigned long num){ if(ts_regs->adcdat0 & (1<<15)){ //上报事件 input_report_abs(ts_dev, ABS_PRESSURE, 0); input_report_key(ts_dev, BTN_TOUCH, 0); input_sync(ts_dev); enter_wait4down_mode(); } else{ enter_measure_xy_mode(); start_adc(); } } static int ts_init(void){ ts_dev = input_allocate_device(); //设置能够产生哪些事件 set_bit(EV_KEY, ts_dev->evbit); set_bit(EV_ABS, ts_dev->evbit); set_bit(BTN_TOUCH, ts_dev->keybit); /*触摸屏按键事件*/ input_set_abs_params(ts_dev, ABS_X, 0, 0x3ff, 0, 0); /*设置绝对位移取值范围*/ input_set_abs_params(ts_dev, ABS_Y, 0, 0x3ff, 0, 0); /*设置绝对位移取值范围*/ input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0); /*设置压力的取值范围,只有0和1*/ /*注册*/ input_register_device(ts_dev); //ioremap ts_regs = ioremap(0x58000000, sizeof(struct ts_regs_t)); clkcon = ioremap(0x4C00000C, 4); //使能时钟,使得adc可以正常工作 adc_clk = clk_get(NULL, "adc"); if (!adc_clk) { printk(KERN_ERR "failed to get adc clock sourcen"); return -ENOENT; } clk_enable(adc_clk); /* bit[14] PRESCEN=1 使能预分频 bit[13:6] PRESCVL=49 预分频数值为49(pclk=50.625M) adcclk = 50.625M/50=1.0125MHz bit[2] STDBM=0 不进入等待模式 bit[1] READ_START=0 bit[0] ENABLE_START=0 */ ts_regs->adccon = (1<<14)|(49<<6); ts_regs->adcdly = 0xffff; //设定延时,保证数据的准确性 //注册中断 if( request_irq(IRQ_TC, grh_handle_tc_irq, IRQF_SAMPLE_RANDOM, "irq_tc", ts_dev) ){ printk(KERN_EMERG"allocate IRQ_TC error!n"); return -EIO; } if( request_irq(IRQ_ADC, grh_handle_adc_irq, IRQF_SHARED|IRQF_SAMPLE_RANDOM, "irq_adc", ts_dev) ){ printk(KERN_EMERG"allocate IRQ_ADC error!n"); return -EIO; } init_timer(&ts_timer); ts_timer.function = grh_handle_timer_int; add_timer(&ts_timer); enter_wait4down_mode();//等待中断模式,检测触摸屏按下 return 0; } static void ts_exit(void){ iounmap(ts_regs); iounmap(clkcon); free_irq(IRQ_TC, ts_dev); free_irq(IRQ_ADC, ts_dev); input_unregister_device(ts_dev); input_free_device(ts_dev); del_timer(&ts_timer); } module_init(ts_init); module_exit(ts_exit); MODULE_AUTHOR("GRH"); MODULE_VERSION("1.0"); MODULE_DESCRIPTION("TOUCH SCREEN DRIVER"); MODULE_LICENSE("GPL");
上一篇:mini2440 按键驱动异步信号通知模式 实验
下一篇:mini2440内核停在booting the kernel问题以及无法运行linuxrc问题的解决方法
推荐阅读最新更新时间:2024-11-12 11:22
设计资源 培训 开发板 精华推荐
- STM32746G-EVAL,评估板是基于ARM Cortex-M7内核的STM32F746NGH6微控制器的完整演示和开发平台
- 使用 ROHM Semiconductor 的 BD45242 的参考设计
- DC2620A-B,使用 LTC7106EDDB-1 7 位电流 DAC 和数字 PMBus 接口的演示板
- 【南京邮电校赛】BoostPFC
- ADM00640,基于 MCP6N16 仪表放大器的评估板
- ADR292ERZ-REEL 4.096V便携式设备稳压器典型应用电路
- 高效、低成本反激转换器,无需光耦反馈
- 8W、1.8V、3.3V、5V交流转直流多路输出高清电视电源
- #第五届立创电子设计大赛#带hall传感器的BLDC无刷电机的单电阻采样FOC矢量控制
- MIC94345-4YCS 1.2V 输出电压、500mA LDO 采用纹波阻断技术的典型应用