歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> ARM Linux S3C2440之ADC驅動實現

ARM Linux S3C2440之ADC驅動實現

日期:2017/3/1 10:30:00   编辑:Linux編程

硬件描述:

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. #define DEVICE_NAME "ADC_DEV"
  15. struct ADC_DEV {
  16. wait_queue_head_t wait;
  17. int ch;
  18. int pres;
  19. int data;
  20. int flag;
  21. };
  22. static struct ADC_DEV adc_dev;
  23. static void __iomem *ADC_REG_BASE;
  24. static struct clk *adc_clk;
  25. #define ADCCON (*(volatile unsigned long *)(ADC_REG_BASE + S3C2410_ADCCON))
  26. #define ADCDAT0 (*(volatile unsigned long *)(ADC_REG_BASE + S3C2410_ADCDAT0))
  27. #define START_ADC(ch,pres) ADCCON = (0x01 | 0x01<<14 | ch<<3 | pres<<6)
  28. static ssize_t adc_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
  29. {
  30. START_ADC(adc_dev.ch, adc_dev.pres); //啟動ADC轉換
  31. wait_event_interruptible(adc_dev.wait,adc_dev.flag); //等待ADC轉換完成
  32. adc_dev.flag = 0;
  33. copy_to_user(buf,(char*)&adc_dev.data,sizeof(adc_dev.data));
  34. return (sizeof(adc_dev.data));
  35. }
  36. static int adc_open(struct inode *in, struct file *fp)
  37. {
  38. adc_dev.ch = 0x02; //輸入通道2
  39. adc_dev.pres = 0xff; //prescale : 0 ~255 可選
  40. adc_dev.data = 0;
  41. adc_dev.flag = 0;
  42. init_waitqueue_head(&(adc_dev.wait));
  43. return 0;
  44. }
  45. static irqreturn_t adc_done_handler(int irq, void *dev_id)
  46. {
  47. adc_dev.data = ADCDAT0 & 0x3ff;
  48. adc_dev.flag = 1;
  49. wake_up_interruptible(&adc_dev.wait); //喚醒等待事件
  50. return IRQ_HANDLED;
  51. }
  52. static struct file_operations dev_fops = {
  53. .owner = THIS_MODULE,
  54. .open = adc_open,
  55. .read = adc_read,
  56. };
  57. static struct miscdevice misc = {
  58. .minor = MISC_DYNAMIC_MINOR,
  59. .name = DEVICE_NAME,
  60. .fops = &dev_fops,
  61. };
  62. static int __init dev_init(void)
  63. {
  64. int ret;
  65. ADC_REG_BASE = ioremap(S3C2410_PA_ADC,0x14); //物理地址映射
  66. adc_clk = clk_get(NULL,"adc");
  67. if (!adc_clk) {
  68. return -ENOENT;
  69. }
  70. clk_enable(adc_clk); //開啟adc 時鐘,系統開機時默認是關閉的
  71. ret = request_irq(IRQ_ADC,adc_done_handler,IRQF_SHARED,DEVICE_NAME,&adc_dev); //分配中斷線
  72. if (ret) {
  73. iounmap(ADC_REG_BASE);
  74. return ret;
  75. }
  76. ret = misc_register(&misc); //注冊設備
  77. return ret;
  78. }
  79. static void __exit dev_exit(void)
  80. {
  81. misc_deregister(&misc);
  82. }
  83. module_init(dev_init);
  84. module_exit(dev_exit);
  85. MODULE_LICENSE("GPL");
  86. MODULE_AUTHOR("itspy");
  87. MODULE_DESCRIPTION("adc driver test");
Copyright © Linux教程網 All Rights Reserved