ARM Linux S3C2440之ADC驱动实现

2024-06-11  

硬件描述:

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:

  1. #include    

  2. #include    

  3. #include    

  4. #include    

  5. #include    

  6. #include        

  7. #include       

  8. #include    

  9. #include    

  10. #include    

  11. #include    

  12. #include    

  13. #include    

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


应用程序adc_test:


  1. #include    

  2. #include    

  3. #include    

  4. #include    

  5. #include            

  6.   

  7. int main(void)  

  8. {  

  9.     int fd;  

  10.     char buf[4];  

  11.     int i,res,adc_data;  

  12.   

  13.     if ((fd = open("/dev/ADC_DEV",O_RDONLY)) < 0) {  

  14.             printf("open adc_dev failedn");  

  15.         return 1;  

  16.     }  

  17.    printf("adc_test result:n");  

  18.     for (i= 0; i< 5; i++) {  

  19.         if ((res =read(fd, buf, 4)) != 4) {  

  20.             printf("read adc_dev failed n");  

  21.             return 1;  

  22.         }   

  23.         else {  

  24.             adc_data = buf[0] + (int)(buf[1]<<8);  

  25.             printf("adc value = %d (%.2f V) n",adc_data, adc_data/1024.0*3.3);  

  26.         }  

  27.     }  

  28.     close(fd);  

  29.   

  30.     return 0;  

  31. }  

测试结果:

[root@www.linuxidc.com /]# ./adc_test 
adc_test result:
adc value = 740 (2.38 V) 
adc value = 744 (2.40 V) 
adc value = 744 (2.40 V) 
adc value = 744 (2.40 V)


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。