程序添加了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);
}
阅读(1456) | 评论(0) | 转发(0) |