免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2527 | 回复: 2
打印 上一主题 下一主题

mini6410 实现 linux adc驱动详解--muge0913版 . [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-11 16:24 |只看该作者 |倒序浏览
mini6410 实现 linux adc驱动详解--muge0913版 .












在嵌入式学习中嵌入式linux驱动占据着十分重要的地位,它不仅牵扯到操作系统、linux内核知识,同时作为开发者你必须了解面对的硬件体系结构和工作原理。在这本人muge0913对linux ad开发做了详细的介绍。


此文章仅供技术交流请勿商用。转载请注明出处:

http://blog.csdn.net/muge0913/article/details/7059241





一、ad转换器介绍

   在这里我们先从adc的工作原理出发,由浅入深的学习,对于已经掌握adc硬件知识的阅读者可跳过此部分。

adc的基础知识我们可直接参考郭天祥老师的教材,免积分下载地址:

http://download.csdn.net/detail/muge0913/3903535





二、ARM中ad转换器介绍

   这里我们以arm11为例:

①简介:


.


   10-bit/12-bit的CMOSADC(模数转换器)是一个8通道模拟输入的回收型设备。5MHz的A / D转换时钟,最高转换率的1MSPS转换到10-bit/12-bit二进制数字编码的模拟输入信号。A / D转换片上采样和保持功能。支持省电模式。

②特性:


③配置:如果简单的驱动ad,只配置ADCCON寄存器即可,如要实现触摸屏的工能则要其他寄存器


注:在下面代码中我们由此部分的注释

三、linux中的adc驱动程序及注释
  1. view plaincopy to clipboardprint?
  2. 01.#include <linux/kernel.h>   
  3. 02.#include <linux/module.h>   
  4. 03.#include <linux/slab.h>   
  5. 04.#include <linux/input.h>   
  6. 05.#include <linux/init.h>   
  7. 06.#include <linux/errno.h>   
  8. 07.#include <linux/serio.h>   
  9. 08.#include <linux/delay.h>   
  10. 09.#include <linux/clk.h>   
  11. 10.#include <linux/sched.h>   
  12. 11.#include <linux/cdev.h>   
  13. 12.#include <linux/miscdevice.h>   
  14. 13.  
  15. 14.  
  16. 15.#include <asm/io.h>   
  17. 16.#include <asm/irq.h>   
  18. 17.#include <asm/uaccess.h>   
  19. 18.  
  20. 19.#include <mach/map.h>   
  21. 20.#include <mach/regs-clock.h>   
  22. 21.#include <mach/regs-gpio.h>   
  23. 22.#include <plat/regs-adc.h>   
  24. 23.static void __iomem * base_addr;  
  25. 24.static struct clk *adc_clock;  
  26. 25.  
  27. 26.  
  28. 27.#define __ADCREG(name)  (*(volatile unsigned long *)(base_addr + name))   
  29. 28.#define ADCCON          __ADCREG(S3C_ADCCON)    // ADC control   
  30. 29.#define ADCTSC          __ADCREG(S3C_ADCTSC)    // ADC touch screen control   
  31. 30.#define ADCDLY          __ADCREG(S3C_ADCDLY)    // ADC start or Interval Delay   
  32. 31.#define ADCDAT0         __ADCREG(S3C_ADCDAT0)   // ADC conversion data 0   
  33. 32.#define ADCDAT1         __ADCREG(S3C_ADCDAT1)   // ADC conversion data 1   
  34. 33.#define ADCUPDN         __ADCREG(S3C_ADCUPDN)   // Stylus Up/Down interrupt status   
  35. 34.  
  36. 35.#define PRESCALE_DIS        (0 << 14)   
  37. 36.#define PRESCALE_EN         (1 << 14)   
  38. 37.#define PRSCVL(x)           ((x) << 6)   
  39. 38.#define ADC_INPUT(x)        ((x) << 3)   
  40. 39.#define ADC_START           (1 << 0)   
  41. 40.#define ADC_ENDCVT          (1 << 15)   
  42. 41.  
  43. 42.#define DEVICE_NAME "adc_dev"   
  44. 43.static int adc_init()  
  45. 44.{  
  46. 45.    unsigned int preScaler = 0XFF;  
  47. 46.    ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);  
  48. 47.    ADCCON |= ADC_START;   
  49. 48.    return 0;  
  50. 49.}  
  51. 50.static int adc_open(struct inode *inode ,struct file *filp)  
  52. 51.{  
  53. 52.    adc_init();  
  54. 53.    return 0;  
  55. 54.}  
  56. 55.static int adc_release(struct inode *inode,struct file *filp)  
  57. 56.{  
  58. 57.    return 0;  
  59. 58.}  
  60. 59.static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)  
  61. 60.{  
  62. 61.    ADCCON |= ADC_START;   
  63. 62.    while(ADCCON & 0x01);//check if Enable_start is low   
  64. 63.    while(!(ADCCON &0x8000));/*检查转换是否结束*/  
  65. 64.    return (ADCDAT0 & 0x3ff);  
  66. 65.}  
  67. 66.  
  68. 67.static struct file_operations dev_fops =  
  69. 68.{  
  70. 69.    .owner = THIS_MODULE,  
  71. 70.    .open = adc_open,  
  72. 71.    .release = adc_release,  
  73. 72.    .read = adc_read,  
  74. 73.};  
  75. 74.  
  76. 75.static struct miscdevice misc =  
  77. 76.{  
  78. 77.    .minor = MISC_DYNAMIC_MINOR,  
  79. 78.    .name = DEVICE_NAME,  
  80. 79.    .fops = &dev_fops,  
  81. 80.};  
  82. 81.  
  83. 82.static int __init dev_init()  
  84. 83.{  
  85. 84.    int ret;  
  86. 85.  
  87. 86.  
  88. 87.    base_addr =ioremap(SAMSUNG_PA_ADC,0X20);//地址映射   
  89. 88.    if(base_addr == NULL)  
  90. 89.    {  
  91. 90.        printk(KERN_ERR"failed to remap\n");  
  92. 91.        return -ENOMEM;  
  93. 92.    }  
  94. 93.  
  95. 94.    adc_clock = clk_get(NULL,"adc");//激活adc时钟模块   
  96. 95.    if(!adc_clock)  
  97. 96.    {  
  98. 97.        printk(KERN_ERR"failed to get adc clock\n");  
  99. 98.        return -ENOENT;  
  100. 99.    }  
  101. 100.    clk_enable(adc_clock);  
  102. 101.  
  103. 102.  
  104. 103.    ret = misc_register(&misc);//混杂设备注册   
  105. 104.    printk("dev_init return ret:%d\n",ret);  
  106. 105.    return ret;  
  107. 106.}  
  108. 107.static void __exit dev_exit()  
  109. 108.{  
  110. 109.    iounmap(base_addr);//取消映射   
  111. 110.      
  112. 111.    if(adc_clock)//disable adc clock取消adc时钟   
  113. 112.    {  
  114. 113.        clk_disable(adc_clock);  
  115. 114.        clk_put(adc_clock);  
  116. 115.        adc_clock =NULL;  
  117. 116.    }  
  118. 117.    misc_deregister(&misc);//注销混杂设备   
  119. 118.      
  120. 119.}  
  121. 120.module_init(dev_init);  
  122. 121.module_exit(dev_exit);  
  123. 122.  
  124. 123.MODULE_LICENSE("GPL");  
  125. 124.MODULE_AUTHOR("MUGE0913");  
  126. #include <linux/kernel.h>
  127. #include <linux/module.h>
  128. #include <linux/slab.h>
  129. #include <linux/input.h>
  130. #include <linux/init.h>
  131. #include <linux/errno.h>
  132. #include <linux/serio.h>
  133. #include <linux/delay.h>
  134. #include <linux/clk.h>
  135. #include <linux/sched.h>
  136. #include <linux/cdev.h>
  137. #include <linux/miscdevice.h>


  138. #include <asm/io.h>
  139. #include <asm/irq.h>
  140. #include <asm/uaccess.h>

  141. #include <mach/map.h>
  142. #include <mach/regs-clock.h>
  143. #include <mach/regs-gpio.h>
  144. #include <plat/regs-adc.h>
  145. static void __iomem * base_addr;
  146. static struct clk *adc_clock;


  147. #define __ADCREG(name)        (*(volatile unsigned long *)(base_addr + name))
  148. #define ADCCON                        __ADCREG(S3C_ADCCON)        // ADC control
  149. #define ADCTSC                        __ADCREG(S3C_ADCTSC)        // ADC touch screen control
  150. #define ADCDLY                        __ADCREG(S3C_ADCDLY)        // ADC start or Interval Delay
  151. #define ADCDAT0                        __ADCREG(S3C_ADCDAT0)        // ADC conversion data 0
  152. #define ADCDAT1                        __ADCREG(S3C_ADCDAT1)        // ADC conversion data 1
  153. #define ADCUPDN                        __ADCREG(S3C_ADCUPDN)        // Stylus Up/Down interrupt status

  154. #define PRESCALE_DIS                (0 << 14)
  155. #define PRESCALE_EN                        (1 << 14)
  156. #define PRSCVL(x)                        ((x) << 6)
  157. #define ADC_INPUT(x)                ((x) << 3)
  158. #define ADC_START                        (1 << 0)
  159. #define ADC_ENDCVT                        (1 << 15)

  160. #define DEVICE_NAME "adc_dev"
  161. static int adc_init()
  162. {
  163.         unsigned int preScaler = 0XFF;
  164.         ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);
  165.         ADCCON |= ADC_START;
  166.         return 0;
  167. }
  168. static int adc_open(struct inode *inode ,struct file *filp)
  169. {
  170.         adc_init();
  171.         return 0;
  172. }
  173. static int adc_release(struct inode *inode,struct file *filp)
  174. {
  175.         return 0;
  176. }
  177. static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)
  178. {
  179.         ADCCON |= ADC_START;
  180.         while(ADCCON & 0x01);//check if Enable_start is low
  181.         while(!(ADCCON &0x8000));/*检查转换是否结束*/
  182.         return (ADCDAT0 & 0x3ff);
  183. }

  184. static struct file_operations dev_fops =
  185. {
  186.         .owner = THIS_MODULE,
  187.         .open = adc_open,
  188.         .release = adc_release,
  189.         .read = adc_read,
  190. };

  191. static struct miscdevice misc =
  192. {
  193.         .minor = MISC_DYNAMIC_MINOR,
  194.         .name = DEVICE_NAME,
  195.         .fops = &dev_fops,
  196. };

  197. static int __init dev_init()
  198. {
  199.         int ret;


  200.         base_addr =ioremap(SAMSUNG_PA_ADC,0X20);//地址映射
  201.         if(base_addr == NULL)
  202.         {
  203.                 printk(KERN_ERR"failed to remap\n");
  204.                 return -ENOMEM;
  205.         }

  206.         adc_clock = clk_get(NULL,"adc");//激活adc时钟模块
  207.         if(!adc_clock)
  208.         {
  209.                 printk(KERN_ERR"failed to get adc clock\n");
  210.                 return -ENOENT;
  211.         }
  212.         clk_enable(adc_clock);


  213.         ret = misc_register(&misc);//混杂设备注册
  214.         printk("dev_init return ret:%d\n",ret);
  215.         return ret;
  216. }
  217. static void __exit dev_exit()
  218. {
  219.         iounmap(base_addr);//取消映射
  220.        
  221.         if(adc_clock)//disable adc clock取消adc时钟
  222.         {
  223.                 clk_disable(adc_clock);
  224.                 clk_put(adc_clock);
  225.                 adc_clock =NULL;
  226.         }
  227.         misc_deregister(&misc);//注销混杂设备
  228.        
  229. }
  230. module_init(dev_init);
  231. module_exit(dev_exit);

  232. MODULE_LICENSE("GPL");
  233. MODULE_AUTHOR("MUGE0913");
复制代码
四、测试程序
  1. view plaincopy to clipboardprint?
  2. 01.#include <stdio.h>   
  3. 02.#include <fcntl.h>   
  4. 03.#include <unistd.h>   
  5. 04.  
  6. 05.int main()  
  7. 06.{  
  8. 07.    int fp,adc_data,i;  
  9. 08.    fp = open("/dev/adc_dev",O_RDWR);  
  10. 09.    for(i=0;i<100;i++)  
  11. 10.    {  
  12. 11.    adc_data = read(fp,NULL,0);  
  13. 12.    printf("%d\n",adc_data);  
  14. 13.    sleep(1);  
  15. 14.    }  
  16. 15.    close(fp);  
  17. 16.    return 0;  
  18. 17.}  
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <unistd.h>

  22. int main()
  23. {
  24.         int fp,adc_data,i;
  25.         fp = open("/dev/adc_dev",O_RDWR);
  26.         for(i=0;i<100;i++)
  27.         {
  28.         adc_data = read(fp,NULL,0);
  29.         printf("%d\n",adc_data);
  30.         sleep(1);
  31.         }
  32.         close(fp);
  33.         return 0;
  34. }
复制代码
五、运行效果


0_1323489100BWue.png (40.31 KB, 下载次数: 19)

0_1323489100BWue.png

1.png (3.65 KB, 下载次数: 9)

1.png

11.png (21.11 KB, 下载次数: 14)

11.png

22.png (36.41 KB, 下载次数: 14)

22.png

论坛徽章:
0
2 [报告]
发表于 2011-12-22 18:49 |只看该作者
学习鸟  谢谢分享

论坛徽章:
0
3 [报告]
发表于 2012-11-11 18:41 |只看该作者
多路接入如何处理?通道选择如何处理?不同通道性能要求不同如何配置?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP