ARM Linux S3C2440之ADC驱动实现

来源:互联网 发布:北航 软件考研 编辑:程序博客网 时间:2024/04/29 22:43

参考:http://www.linuxidc.com/Linux/2012-02/54967.htm

硬件描述:

S3c2440有一个10-bit的CMOS ADC 模数转换器,支持8个模拟通道输入,10位的分辨率,最高速度可达500KSPS(500 千次/每秒)。

 

 

从图中可知:模拟ADC,包含了2部分功能,一部分是触屏功能,另一部分就是普通ADC功能,分别可以产生INT_TC和INT_ADC 两个中断。8个AIN模拟输入(A[3:0],YM,YP,XM,XP)通过一个8路模拟开关MUX进行通道片选。 ADC模块共有20个寄存器。对于普通ADC转换,使用ADCCON 和 ADCDAT0即可完成控制。ADCCON用于控制设置,ADCDAT0保存了转换结果。

驱动程序ADC_DEV.ko:

 


[cpp]
1.#include <linux/errno.h>  
2.#include <linux/init.h>  
3.#include <linux/kernel.h>  
4.#include <linux/module.h>  
5.#include <linux/clk.h>  
6.#include <asm/io.h>      
7.#include <asm/irq.h>     
8.#include <linux/interrupt.h>  
9.#include <mach/regs-clock.h>  
10.#include <plat/regs-adc.h>  
11.#include <linux/miscdevice.h>  
12.#include <linux/fs.h>  
13.#include <linux/uaccess.h>  
14. 
15.#define DEVICE_NAME "ADC_DEV"  
16. 
17.struct ADC_DEV { 
18.    wait_queue_head_t wait; 
19.    int ch; 
20.    int pres; 
21.    int data; 
22.    int flag; 
23.}; 
24. 
25.static struct ADC_DEV adc_dev; 
26. 
27.static void __iomem *ADC_REG_BASE; 
28.static struct clk *adc_clk; 
29. 
30.#define ADCCON                  (*(volatile unsigned long *)(ADC_REG_BASE + S3C2410_ADCCON))  
31.#define ADCDAT0                 (*(volatile unsigned long *)(ADC_REG_BASE + S3C2410_ADCDAT0))   
32.#define START_ADC(ch,pres)    ADCCON = (0x01 | 0x01<<14 | ch<<3 | pres<<6)  
33. 
34.     
35.static ssize_t adc_read(struct file *fp,  char __user *buf,  size_t count,  loff_t *ppos) 
36.{ 
37.    START_ADC(adc_dev.ch, adc_dev.pres);              //启动ADC转换  
38.    wait_event_interruptible(adc_dev.wait,adc_dev.flag);   //等待ADC转换完成  
39.    adc_dev.flag = 0; 
40.     
41.    copy_to_user(buf,(char*)&adc_dev.data,sizeof(adc_dev.data)); 
42. 
43.    return (sizeof(adc_dev.data)); 
44.} 
45.static int adc_open(struct inode *in, struct file *fp) 
46.{ 
47.    adc_dev.ch = 0x02;        //输入通道2  
48.    adc_dev.pres = 0xff;       //prescale : 0 ~255 可选  
49.    adc_dev.data = 0; 
50.    adc_dev.flag = 0; 
51.    init_waitqueue_head(&(adc_dev.wait));     
52.     
53.    return 0; 
54.} 
55.static irqreturn_t adc_done_handler(int irq, void *dev_id) 
56.{ 
57.    adc_dev.data = ADCDAT0 & 0x3ff; 
58.    adc_dev.flag = 1; 
59.    wake_up_interruptible(&adc_dev.wait);      //唤醒等待事件  
60. 
61.    return IRQ_HANDLED; 
62.} 
63. 
64.static struct file_operations dev_fops = { 
65.    .owner = THIS_MODULE, 
66.    .open  = adc_open, 
67.    .read  = adc_read, 
68.}; 
69. 
70.static struct miscdevice misc = { 
71.    .minor = MISC_DYNAMIC_MINOR, 
72.    .name  = DEVICE_NAME, 
73.    .fops  = &dev_fops, 
74.}; 
75. 
76.static int __init dev_init(void) 
77.{ 
78.    int ret; 
79. 
80.    ADC_REG_BASE = ioremap(S3C2410_PA_ADC,0x14);    //物理地址映射  
81.    adc_clk = clk_get(NULL,"adc"); 
82.    if (!adc_clk) { 
83.        return -ENOENT; 
84.    } 
85.    clk_enable(adc_clk);            //开启adc 时钟,系统开机时默认是关闭的  
86.     
87.    ret = request_irq(IRQ_ADC,adc_done_handler,IRQF_SHARED,DEVICE_NAME,&adc_dev);   //分配中断线  
88.    if (ret) { 
89.       iounmap(ADC_REG_BASE); 
90.       return ret; 
91.    } 
92.     
93.    ret = misc_register(&misc);      //注册设备  
94. 
95.    return ret; 
96.} 
97. 
98. 
99.static void __exit dev_exit(void) 
100.{ 
101.    misc_deregister(&misc); 
102.} 
103. 
104.module_init(dev_init); 
105.module_exit(dev_exit); 
106. 
107.MODULE_LICENSE("GPL"); 
108.MODULE_AUTHOR("itspy"); 
109.MODULE_DESCRIPTION("adc driver test"); 

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-02/54967.htm