硬件描述:

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");