努力成为 linux kernel hacker 的人李万鹏原创作品,为梦而战。转载请标明
出处
http://blog.csdn.net/woshixingaaa/archive/2011/05/18/6429002.asp
x
S3C2440 内部 ADC 结构图:
对于 s3c2440 来说,实现 A/D 转换比较简单,主要应用的是 ADC 控制寄存器
ADCCON 和 ADC 转换数据寄存器 ADCDAT0。寄存器 ADCDAT0 的低 10 位用
于存储 A/D 转换后的数据。寄存器 ADCCON 的第 15 位用于标识 A/D 转换是否
结束。第 14 位用于使能是否进行预分频,而第 6 位到第 13 位则存储的是预分
频数值,因为 A/D 转换的速度不能太快,所以要通过预分频处理才可以得到正
确的 A/D 转换速度,如我们想要得到 A/D 转换频率为 1MHz,则预分频的值应
为 49。第 3 位到第 5 位
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示的是 A/D 转换的通道选择。第 2 位可以实现 A/D 转
换的待机模式。第 1 位用于是否通过读取操作来使能 A/D 转换的开始。第 0 位
则是在第 1 位被清零的情况下用于开启 A/D 转换。
驱动代码:
1. #include
2. #include
3. #include
4. #include
5. #include
6. #include
7. #include
8. #include
Object 1Object 2Object 3Object 4Object 5Object 6Object 7Object 8Object 9Object 10Object 11Object 12Object 13Object 14Object 15Object 16Object 17Object 18Object 19Object 20Object 21Object 22Object 23Object 24Object 25Object 27Object 28Object 29Object 30Object 31Object 32Object 33Object 34Object 35Object 37Object 38Object 39Object 40Object 41Object 42Object 43 Object 44Object 45
Object 46
Object 47
Object 48
Object 49Object 53
Object 55Object 56Object 57Object 58Object 59 Object 60Object 61Object 62Object 63Object 64Object 65Object 66
Object 67
Object 68
Object 69Object 70Object 71Object 72Object 73Object 74Object 75Object 76Object 77Object 78Object 79Object 80Object 81Object 82Object 83Object 84Object 85Object 86Object 87Object 88Object 89Object 90Object 91Object 92Object 93Object 94Object 95
Object 26
Object 36
9. #include
10.#include
11.#include
12.#include
13.#include
14.#include
15.#include
16.#include
17.#define ADC_MINOR 100
18.#define ADC_NAME "lwp-adc"
19.struct clk *adc_clk;
20.int adc_base;
21.int adc_finish = 0;
22.static int adc_data;
23.DECLARE_WAIT_QUEUE_HEAD(adc_wait);
24.
25.static irqreturn_t adc_interrupt(int irq, void *dev_id){
26. if(!adc_finish){
27. adc_data = readl(adc_base + S3C2410_ADCDAT0) & 0x3ff; //ad 转换结束会产生中断,
此时读取 S3C2410_ADCDAT0 的 0~9 位,来获取数据
28. adc_finish = 1;
29. wake_up_interruptible(&adc_wait); //唤醒等待其上的进程
30. }
31. return IRQ_HANDLED;
32.}
33.
34.int myadc_open(struct inode *inode, struct file *file){
35. int ret;
36. ret = request_irq(IRQ_ADC, adc_interrupt, IRQF_SHARED, ADC_NAME, 1); //这里注册中断,
ad 转换结束通知 cpu 有两种方式,一种靠 cpu 轮询标志位,一种靠中断
37. if(ret){
38. printk("IRQ %d can't get/n", IRQ_ADC);
39. return -1;
40. }
41. return 0;
42.}
43.
44.int myadc_close(struct inode *inode, struct file *file){
45. return 0;
46. return -ENOENT;
47.}
48.
49.void start_adc(){ //开始 ad 转换
50. int tmp;
51. tmp = 0xff<<6 | 1<<14; //设置预分频使能,值为 255,使用通道 AIN0
52. writel(tmp ,adc_base + S3C2410_ADCCON);
53. tmp = readl(adc_base + S3C2410_ADCCON);
54. tmp |= 1<<0; //使能 AD 转换
55. writel(tmp, adc_base + S3C2410_ADCCON);
56.}
57.
58.ssize_t myadc_read(struct file *filp, char __user *buff, size_t count, loff_t *offp){
59. start_adc(); //要读数据开始 adc 转换
60. wait_event_interruptible(adc_wait, adc_finish); //等待转换结束
61. adc_finish = 0;
62. copy_to_user(buff, (char *)&adc_data, sizeof(adc_data)); //将获得的数据拷贝到用户空间,
数据会在中断程序中获得
63. return sizeof(adc_data);
64.}
65.
66.static struct file_operations adc_ops = {
67. .owner = THIS_MODULE,
68. .open = myadc_open,
69. .release = myadc_close,
70. .read = myadc_read,
71.};
72.
73.static struct miscdevice adc_misc = {
74. .name = ADC_NAME,
75. .minor = ADC_MINOR,
76. .fops = &adc_ops,
77.};
78.
79.static int __init my_adc_init(void){
80. unsigned int ret;
81. adc_clk = clk_get(NULL,"adc"); //由于 ad 转换需要时钟,所以这里获取时钟
82. if(!adc_clk){
83. printk(KERN_ERR "fail to find adc clk resource!/n");
84. ret = -1;
85. goto err_clk;
86. }
87. clk_enable(adc_clk); //使能 adc 的时钟
88. adc_base = ioremap(S3C2410_PA_ADC, 20); //获得 ADC 控制寄存器的虚拟地址
89. if(adc_base == 0){
90. printk(KERN_ERR "fail to ioremap!/n");
91. ret = -1;
92. goto err_nomap;
93. }
94. ret = misc_register(&adc_misc); //注册这个 adc 为混杂设备
95. if(IS_ERR(ret)){
96. goto err_register;
97. }
98. return 0;
99.
100.err_register:
101. iounmap(adc_base);
102.err_nomap:
103. clk_disable(adc_clk);
104. clk_put(adc_clk);
105.err_clk:
106. return ret;
107.}
108.
109.static void __exit my_adc_exit(void){
110. misc_deregister(&adc_misc);
111. free_irq(IRQ_ADC, 1);
112. iounmap(adc_base);
113. clk_disable(adc_clk);
114. clk_put(adc_clk);
115.}
116.
117.module_init(my_adc_init);
118.module_exit(my_adc_exit);
119.MODULE_AUTHOR("liwanpeng");
120.MODULE_LICENSE("GPL");
测试代码:
1. #include
2. #include
3. #include
4.
5. int main(int argc, char **argv)
6. {
7. int fd;
8. fd = open("/dev/lwp-adc", 0);
9. if(fd < 0)
10. {
11. printf("Open ADC Device Faild!/n");
12. exit(1);
13. }
14. while(1)
15. {
16. int ret;
17. int data;
18. ret = read(fd, &data, sizeof(data));
19. if(ret != sizeof(data))
20. {
21. if(errno != EAGAIN)
22. {
23. printf("Read ADC Device Faild!/n");
24. }
25. continue;
26. }
27. else
28. {
29. printf("Read ADC value is: %d/n", data);
30. }
31. }
32. close(fd);
33. return 0;
34.}
实验效果:
分享到: