ARM Linux S3C2440之ADC驱动实现


硬件描述:

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");  
  • 1
  • 2
  • 下一页

相关内容