我的嵌入式

有志者,事竟成!

Linux 驱动--ADC驱动 .

 

主机系统:Ubuntu 11.04

内核版本:Linux Kernel 2.6.39

硬件平台:FL2440

开发板系统:Linux Kernel 2.6.28

下面是用CPU轮寻的方式来判断AD转换完成的

  1. #include <linux/kernel.h>   
  2. #include <linux/module.h>   
  3.   
  4. #include <linux/fs.h>   
  5. #include <linux/device.h> /*创建设备节点*/  
  6. #include <linux/clk.h>   
  7. #include <linux/delay.h>/*延时函数*/  
  8.   
  9. #include <asm/io.h>   
  10. #include <asm/uaccess.h>   
  11.   
  12. #include <plat/regs-adc.h>   
  13. #include <mach/regs-clock.h>  
  14.   
  15. #define ADC_MAJOR 102   
  16. #define ADC_NAME "my_adc"   
  17. #define SUCCESS 0   
  18.   
  19. static int adc_open(struct inode *,struct file *);  
  20. static int adc_release(struct inode *,struct file *);  
  21. static int __init adc_init(void);  
  22. static int __exit adc_exit(void);  
  23. static ssize_t adc_read(struct file *,char *,size_t,loff_t *);  
  24.   
  25. volatile unsigned long adc_con;  
  26. unsigned long adc_dat0;  
  27. //#define adc_con       (unsigned long)ioremap(0x58000000,4)  
  28. //#define adc_dat0      (volatile unsigned long)ioremap(0x5800000c,4)  
  29. struct clk *adc_clk;   
  30.   
  31. struct file_operations  adc_ops =  
  32. {  
  33.     .owner  =   THIS_MODULE,  
  34.     .read       =   adc_read,  
  35.     .open   =   adc_open,  
  36.     .release    =   adc_release,  
  37. };  
  38.   
  39. static int __init adc_init(void)  
  40. {  
  41.     int ret;  
  42.     adc_clk = clk_get(NULL,"adc");//获取时钟  
  43.     clk_enable(adc_clk);//使能时钟  
  44.     ret=register_chrdev(ADC_MAJOR,ADC_NAME,&adc_ops); //注册设备  
  45.     if(ret<0)  
  46.     {  
  47.         printk("register device fail/n");  
  48.         return ret;  
  49.     }  
  50.     adc_con=(unsigned long)ioremap(0x58000000,4);  
  51.     adc_dat0=(volatile unsigned long)ioremap(0x58000000+S3C2410_ADCDAT0,4);  
  52.     if(adc_con&adc_dat0==0)  
  53.     {  
  54.         printk("Failed to ioremap/n");  
  55.         goto handle;  
  56.     }  
  57.     printk("Initialized.../n");  
  58.     return SUCCESS;  
  59. handle:  
  60.     unregister_chrdev(ADC_MAJOR,ADC_NAME);  
  61.     return -1;  
  62. }  
  63.   
  64. static int adc_open(struct inode * inode,struct file * file) //打开设备函数  
  65. {  
  66.       
  67.     return SUCCESS;  
  68. }  
  69.   
  70. static int adc_release(struct inode * inode,struct file * file) //关闭设备函数  
  71. {  
  72.     return SUCCESS;  
  73. }  
  74.   
  75. static ssize_t adc_read(struct file *file,  
  76.                             char * buffer,  
  77.                             size_t length,  
  78.                             loff_t * offset)//设备读取函数  
  79. {  
  80.     unsigned int buf;  
  81.     int tmp;  
  82.     int i;  
  83.     writew((1<<14)|(0x31<<6),adc_con);       //设置ADCCON  
  84.     writew((readw(adc_con) | 0x1),adc_con);  //启动AD转换  
  85.     while(readw(adc_con) & 0x1) ;              //启动转换后,等待启动位清零  
  86.     while(!(readw(adc_con) & 0x8000)) ;            //等待转换是否完毕  
  87.     //for(i=0;i<200000;i++) ;   
  88.     mdelay(100);  
  89.     buf=(readw(adc_dat0) & 0x3ff );                 //取出转换后得到的有效数据  
  90.   
  91.     copy_to_user(buffer, (char *)&buf, sizeof(buf));  
  92.     //printk("The value is %x/n",buf);   
  93.     return 2;  
  94.   
  95. }  
  96.   
  97. static int __exit adc_exit(void//驱动卸载函数  
  98. {  
  99.     iounmap(adc_con);  
  100.     iounmap(adc_dat0);  
  101.     unregister_chrdev(ADC_MAJOR,ADC_NAME);  
  102.     clk_disable(adc_clk);  
  103.     clk_put(adc_clk);  
  104.     printk("The adc is unintialized/n");  
  105.     return SUCCESS;  
  106. }  
  107.   
  108. module_init(adc_init);           
  109. module_exit(adc_exit);  
  110. MODULE_LICENSE("GPL");  

其中控制寄存器的第15未标明AD转换是否完成,当AD完成转换时,控制寄存器自动置一,但是由于数据存在延迟,当第15位置一的时候读出的数据并不稳定,需要在其后加个延迟的函数,在内核态使用的延迟函数包含头文件./linux/delay.h

mdelay(int x);延时x毫秒

udelay(int x);延时x微秒

ndelay(int x);延时x纳秒

 

测试函数如下:

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <sys/time.h>   
  4.   
  5. #define ADC_DEVICE  "/dev/my_adc"  
  6.   
  7. int main()  
  8. {  
  9.     int ret;  
  10.     unsigned int data;  
  11.     ret=open(ADC_DEVICE,0);  
  12.     if(ret<0)  
  13.     {  
  14.         printf("Open adc fail/n");  
  15.         return ret;  
  16.     }  
  17.     for(;;)  
  18.     {  
  19.         //printf("cnt=%d/n",cnt);  
  20.         read(ret,&data,sizeof(data));  
  21.         printf("The value is 0x%x/n",data);  
  22.     }  
  23.     close(ret);  
  24.     return 0;  
  25. }  

测试结果

 

阅读更多
个人分类: linux驱动
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭