Chinaunix首页 | 论坛 | 博客
  • 博客访问: 119376
  • 博文数量: 24
  • 博客积分: 616
  • 博客等级: 中士
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-01 10:54
文章分类
文章存档

2012年(24)

我的朋友

分类: LINUX

2012-07-30 11:21:47

程序添加了X,Y坐标的显示,以及检测到手按下输出数据,手离开停止输出数据功能。下一步准备对数据进行消抖处理,现在的程序发现在手离开屏幕的瞬间读取到的坐标会出现异常
 
一、驱动:
/*********************************
**        touch 驱动程序          **
*********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "s3c24xx-adc.h"
static void __iomem *base_addr;
#define ADCCON      (*(volatile unsigned long *)(base_addr + 0)) //ADC control
#define ADCTSC      (*(volatile unsigned long *)(base_addr + 0x04)) //ADC touch screen control
#define ADCDLY      (*(volatile unsigned long *)(base_addr + 0x08)) //ADC start or Interval Delay
#define ADCDAT0     (*(volatile unsigned long *)(base_addr + 0x0c)) //ADC conversion data 0
#define ADCDAT1     (*(volatile unsigned long *)(base_addr + 0x10)) //ADC conversion data 1
#define ADCUPDN     (*(volatile unsigned long *)(base_addr + 0x14)) //Stylus Up/Down interrupt status
long xp,yp;
int count;
#define AUTOPST      (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
       S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
#define DEVICE_NAME "touch_micro2440_drv"
static struct semaphore lock;
typedef struct {
 wait_queue_head_t wait;
 int channel;
 int prescale;
}ADC_DEV;
static struct clk *adc_clock;

static int OwnADC = 0;
static ADC_DEV adcdev;
static volatile int ev_adc = 0;
static int adc_data;
static int biaozhi_adc_start = 0;
 

#define PRESCALE_DIS        (0 << 14)
#define PRESCALE_EN         (1 << 14)
#define PRSCVL(x)           ((x) << 6)
#define ADC_INPUT(x)        ((x) << 3)
#define ADC_START           (1 << 0)
#define ADC_ENDCVT          (1 << 15)
#define WAIT4INT(x)  (((x)<<8) | \
       S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
       S3C2410_ADCTSC_XY_PST(3))
void adc_start(int ch,int prescale)
{
 ADCCON = PRESCALE_EN | PRSCVL(prescale); //| ADC_INPUT((ch)) ;
 ADCCON |= ADC_START;
}
static void touch_timer_fire(unsigned long data)
{
   unsigned long data0;
   unsigned long data1;
   int updown;
   data0 = ADCDAT0;
   data1 = ADCDAT1;
  updown = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));
  if (updown) {//按下态
     ADCCON=ADCCON|(1<<0);
     ADCTSC=(1<<3)|(1<<7)|(1<<6)|(1<<4)|(1<<2);//设置ADC处于等待中断模式、笔尖落下中断信号、YM开其他都关
   
  } else {//抬起态
     ADCCON=ADCCON&(~(1<<14))&(~(0xff<<6));
     ADCCON=ADCCON|(1<<14)|(0xff<<6);//使能预分频器,设置预分频数值
     ADCDLY=0x3fff;//设置ADC转换启动延时数值
     ADCTSC=(0<<8)|(1<<7)|(1<<6)|(1<<4)|0x03;//设置ADC处于等待中断模式、笔尖落下中断信号、YM开其他都关
  }
}
static irqreturn_t touch_adc_interupt_handler(int irq, void *dev_id)
{
  unsigned long data0;
   unsigned long data1;
    int updown;
   if (OwnADC)
  {
      data0 = ADCDAT0;
      data1 = ADCDAT1;
      updown = (!(data0 &(1<<15))) && (!(data1 & (1<<15)));
    xp = data0&0x3ff ;
      yp = data1&0x3ff ;
      count++;       
       ev_adc = 1;
      wake_up_interruptible(&adcdev.wait);
      if(count<4)
      {
         if(updown)
        {
           iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
          iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
       }
      }
      else
      {count=0;
       iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
      }
  }
 return IRQ_HANDLED;
}
static irqreturn_t touch_tc_interupt_handler(int irq, void *dev_id)
{
   unsigned long data0;
   unsigned long data1;
   int updown;
  OwnADC = 1;
  data0 = ADCDAT0;
  data1 = ADCDAT1;
  updown = (!(data0 &(1<<15))) && (!(data1 & (1<<15)));
  if (updown) {
   touch_timer_fire(0);
  } else {
   OwnADC = 0;
   ADCCON=ADCCON&(~(1<<14))&(~(0xff<<6));
     ADCCON=ADCCON|(1<<14)|(0xff<<6);//使能预分频器,设置预分频数值
     ADCDLY=0xffff;//设置ADC转换启动延时数值
     ADCTSC=(0<<8)|(1<<7)|(1<<6)|(1<<4)|0x03;//设置ADC处于等待中断模式、笔尖落下中断信号、YM开其他都关
  }
 return IRQ_HANDLED;
}
static ssize_t touch_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
   char str[50];
   long int value;
   size_t len;
  biaozhi_adc_start = 1;
  adc_start(adcdev.channel, adcdev.prescale);
  wait_event_interruptible(adcdev.wait, ev_adc);
  ev_adc = 0;
  value = xp;
  value=value<<16;
  value=value|yp;
  biaozhi_adc_start = 0;
  up(&lock);
   len = sprintf(str, "%d\n", value);//将value打印成一个字符串保存在str中
   if (count >= len) {
      int r = copy_to_user(buffer, str, len);
      return r ? r : len;
   } else {
  return -EINVAL;
   }
}
static int touch_open(struct inode *inode,struct file *file)
{
      //尝试打开互斥锁
       int ret;
       ret=down_trylock(&lock);
       if(ret!=0)
        return -EBUSY;
      //将中断加入等待队列
      init_waitqueue_head(&(adcdev.wait));
      //初始化adc采样通道及预分频参数
      adcdev.channel=0;
      adcdev.prescale=0xffff;
      return 0;
     
 } 
static int touch_close(struct inode *inodep,struct file *file)
{
     return 0;
}
static struct file_operations dev_fops={
 .owner=THIS_MODULE,
 .open=touch_open,
 .release=touch_close,
 .read=touch_read,
};
static struct miscdevice misc={
 .name=DEVICE_NAME,
 .minor=MISC_DYNAMIC_MINOR,
 .fops=&dev_fops,
};
static int __init touch_micro2440_init(void)
{
     int ret;
     //初始化锁
     init_MUTEX(&lock);
     //IO映射
     base_addr=ioremap(0x58000000,0x20);//0x58000000为ADC的首地址总共映射了6个寄存器
     //获取ADC时钟
     adc_clock=clk_get(NULL,"adc");
     clk_enable(adc_clock);
     //设置GPIO为触摸屏ADC功能
     s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
     s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
     s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);
     s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);
     //设置CPU关于触摸屏的相关寄存器
     ADCCON=ADCCON&(~(1<<14))&(~(0xff<<6));
     ADCCON=ADCCON|(1<<14)|(0xff<<6);//使能预分频器,设置预分频数值
     ADCDLY=0xffff;//设置ADC转换启动延时数值
     ADCTSC=(0<<8)|(1<<7)|(1<<6)|(1<<4)|0x03;//设置ADC处于等待中断模式、笔尖落下中断信号、YM开其他都关    
     //注册中断
     ret=request_irq(IRQ_ADC,touch_adc_interupt_handler,IRQF_SHARED|IRQF_SAMPLE_RANDOM,DEVICE_NAME,&adcdev);
     ret=request_irq(IRQ_TC,touch_tc_interupt_handler,IRQF_SAMPLE_RANDOM,DEVICE_NAME,&adcdev);
     //注册混杂设备
     ret=misc_register(&misc); 
     return ret;
}
void __exit touch_micro2440_exit(void)
{
    //1.注销中断
    free_irq(IRQ_ADC,&adcdev);
    free_irq(IRQ_TC,&adcdev);
    //2.取消寄存器映射
    iounmap(base_addr);
    //3.停止ADC时钟
    clk_disable(adc_clock);
    clk_put(adc_clock);
    adc_clock=NULL;
    //4.注销混杂设备
    misc_deregister(&misc);//注销混杂设备 
}
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("xubin");
module_init(touch_micro2440_init);
module_exit(touch_micro2440_exit);
 
二、应用程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void)
{
 fprintf(stderr, "press Ctrl-C to stop\n");
 int fd = open("/dev/touch_micro2440_drv", 0);
 if (fd < 0) {
  perror("open ADC device:");
  return 1;
 }
 for(;;) {
  char buffer[50];
  int len = read(fd, buffer, sizeof buffer -1);
  if (len > 0) {
   buffer[len] = '\0';
   long int value = -1;
   sscanf(buffer, "%d", &value);//将字符串buffer按照整数的形式存在value中
   printf("ADC Value x: %d\n", (short int) value);
   printf("ADC Value y: %d\n", (short int) (value>>16));
  } else {
   perror("read ADC device:");
   return 1;
  }
  usleep(20* 1000);
 }
 
 close(fd);
}
阅读(1446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~