linux adc驱动 视频,ARM-Linux驱动--ADC驱动(中断方式)

原标题:ARM-Linux驱动--ADC驱动(中断方式)

硬件平台:FL2440

内核版本:2.6.28

主机平台:Ubuntu 11.04

内核版本:2.6.39

原创作品,转载请标明出处:http://blog.csdn.net/yming0221/archive/2011/06/26/6568937.aspx

这个驱动写了好久,因为原来的Linux内核编译的时候将 驱动编译进内核了,而触摸屏驱动里的ADC中断在注册的时候类型选择的是

IRQF_SAMPLE_RANDOM,不是共享类型,所以,自己写的 在每次open的时候,总提示ADC中断注册失败。

解决方案:

重新配置内核,选择触摸屏驱动以模块的形式编译,而不是直接编译进内核,这样Linux在启动的时候不会自动加载触摸屏驱动,当然,IRQ_ADC中断号不会被占用。这样可以测试自己写的ADC驱动了。

以下是驱动源代码:

view plainprint?

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ADC_MAJOR 102

#define ADC_NAME "my_adc"

#define SUCCESS 0

static int adc_open(struct inode *,struct file *);

static int adc_release(struct inode *,struct file *);

static int __init adc_init(void);

static int __exit adc_exit(void);

static ssize_t adc_read(struct file *,char *,size_t,loff_t *);

volatile unsigned long adc_con;

unsigned long adc_dat0;

int flag;//等待任务完成标志

unsigned long buf;//存放转换完成的数据

//声明等待队列

DECLARE_WAIT_QUEUE_HEAD(adc_wait);

struct clk *adc_clk;

static irqreturn_t adc_interrupt(int irq,void * dev_id)//中断处理程序

{

if(flag==0)

{

buf=(readw(adc_dat0) & 0x3ff );//读取转换完成的数据

flag=1;

wake_up_interruptible(&adc_wait);//唤醒等待其上的进程

printk("Read value is %ld/n",buf);

}

return IRQ_HAND ;

}

struct file_operations adc_ops =

{

.owner = THIS_MODULE,

.read = adc_read,

.open = adc_open,

.release = adc_release,

};

static int __init adc_init(void)

{

int ret;

adc_clk = clk_get(NULL,"adc");//获取时钟

clk_enable(adc_clk);//使能时钟

ret=register_chrdev(ADC_MAJOR,ADC_NAME,&adc_ops); //注册设备

if(ret<0)

{

printk("register device fail/n");

return ret;

}

adc_con=(unsigned long)ioremap(0x58000000,4);

adc_dat0=(volatile unsigned long)ioremap(0x58000000+S3C2410_ADCDAT0,4);

if( !(adc_con & adc_dat0) )

{

printk("Fai to ioremap/n");

goto handle;

}

printk("Initialized.../n");

return SUCCESS;

handle:

unregister_chrdev(ADC_MAJOR,ADC_NAME);

return -1;

}

static int adc_open(struct inode * inode,struct file * file) //打开设备函数

{

//注册中断

int ret;

//disable_irq(IRQ_ADC);

//enable_irq(IRQ_ADC);

ret=request_irq(IRQ_ADC,adc_interrupt,IRQF_SHARED,ADC_NAME,1);//注册中断 IRQ_ADC在 mach/irqs.h中定义

if(ret<0)

{

printk("IRQ %d can not request/n",IRQ_ADC);

return ret;

}

return SUCCESS;

}

static int adc_release(struct inode * inode,struct file * file) //关闭设备函数

{

free_irq(IRQ_ADC,1);//释放中断

return SUCCESS;

}

static ssize_t adc_read(struct file *file,

char * buffer,

size_t length,

loff_t * offset)//设备读取函数

{

writew((1<<14)|(0x31<<6),adc_con); //设置ADCCON

writew((readw(adc_con) | 0x1),adc_con); //启动AD转换

wait_event_interruptible(adc_wait,flag);

flag=0;

}

static int __exit adc_exit(void) //驱动卸载函数

{

iounmap(adc_con);

iounmap(adc_dat0);

unregister_chrdev(ADC_MAJOR,ADC_NAME);

clk_disable(adc_clk);

clk_put(adc_clk);

printk("The adc is unintialized/n");

return SUCCESS;

}

module_init(adc_init);

module_exit(adc_exit);

MODULE_LICENSE("GPL");

Makefile文件:

view plainprint?

obj-m := adc.o

KERNELDIR ?= / /linux-2.6.28.7-2440

PWD := $(shell pwd)

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -f *.o *.ko *.order *.symvers read

read:

arm-linux-gcc -o read read_adc.c

以下是测试代码:

view plainprint?

#include

#include

#include

#define ADC_DEVICE "/dev/my_adc"

int main()

{

int ret;

unsigned int data;

ret=open(ADC_DEVICE,0);

if(ret<0)

{

printf("Open adc fail/n");

return ret;

}

for(;;)

{

//printf("cnt=%d/n",cnt);

read(ret,&data,sizeof(data));

//printf("The value is %d/n",data);

}

close(ret);

return 0;

}

首先新建设备:

mknod /dev/my_adc c 102 32

然后插入驱动 insmod adc.ko

运行测试程序./read

结果如下:

6c8601b3b6b52c5bee706268e86bcb04.png

可以看出,调节ad转换器上的旋钮,看到AD转换值的变化,说明驱动工作正常。

责任编辑:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值