歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

OK6410之ADC驅動程序

參考
mini6410 實現 linux adc驅動詳解--muge0913版  http://www.linuxidc.com/Linux/2011-12/49243.htm

/*之前自己根據裸機程序改的,給ADC寄存器地址,不行
*調試了幾天,原因是" Unable to handle kernel paging request at virtual address 0x7E00B000 "
* 後來,還是按照人家的來吧!結果成功了*/

平台:Ubuntu 10.04     arm內核linux2.6.28

驅動程序

  1. #include <linux/kernel.h>     
  2. #include <linux/module.h>     
  3. #include <linux/slab.h>     
  4. #include <linux/input.h>     
  5. #include <linux/init.h>     
  6. #include <linux/errno.h>     
  7. #include <linux/serio.h>     
  8. #include <linux/delay.h>     
  9. #include <linux/clk.h>     
  10. #include <linux/sched.h>     
  11. #include <linux/cdev.h>     
  12. #include <linux/miscdevice.h>   
  13.   
  14.   
  15. #include <asm/io.h>     
  16. #include <asm/irq.h>     
  17. #include <asm/uaccess.h>     
  18.   
  19. #include <plat/regs-adc.h>    
  20. #include <mach/map.h>    
  21.      
  22. static void __iomem * base_addr;    
  23. static struct clk *adc_clock;    
  24.   
  25. /*#define ADCCON_BASE      (0x7E00B000)     
  26. #define ADCCON           (*(volatile unsigned *)(ADCCON_BASE+0x00))    // ADC control     
  27. #define ADCTSC           (*(volatile unsigned *)(ADCCON_BASE+0x04))    // ADC touch screen control     
  28. #define ADCDLY           (*(volatile unsigned *)(ADCCON_BASE+0x08))    // ADC start or Interval Delay     
  29. #define ADCDAT0          (*(volatile unsigned *)(ADCCON_BASE+0x0C))   // ADC conversion data 0     
  30. #define ADCDAT1          (*(volatile unsigned *)(ADCCON_BASE+0x10))   // ADC conversion data 1     
  31. #define ADCUPDN          (*(volatile unsigned *)(ADCCON_BASE+0x14))  // Stylus Up/Down interrupt status     
  32. #define PRESCALE_DIS        (0 << 14)     
  33. #define PRESCALE_EN         (1 << 14)     
  34. #define PRSCVL(x)           ((x) << 6)     
  35. #define ADC_INPUT(x)        ((x) << 3)     
  36. #define ADC_START           (1 << 0)     
  37. #define ADC_ENDCVT          (1 << 15)   */  
  38.   
  39. /*ADC寄存器地址*/  
  40. #define __ADCREG(name)  (*(volatile unsigned long *)(base_addr + name))    
  41. #define ADCCON          __ADCREG(S3C_ADCCON)    // ADC control    
  42. #define ADCTSC          __ADCREG(S3C_ADCTSC)    // ADC touch screen control    
  43. #define ADCDLY          __ADCREG(S3C_ADCDLY)    // ADC start or Interval Delay    
  44. #define ADCDAT0         __ADCREG(S3C_ADCDAT0)   // ADC conversion data 0    
  45. #define ADCDAT1         __ADCREG(S3C_ADCDAT1)   // ADC conversion data 1    
  46. #define ADCUPDN         __ADCREG(S3C_ADCUPDN)   // Stylus Up/Down interrupt status    
  47.    
  48.   
  49. /*根據s3c6410的文檔,設置相應的ADC控制器位*/  
  50. #define PRESCALE_DIS        (0 << 14)    
  51. #define PRESCALE_EN         (1 << 14)    
  52. #define PRSCVL(x)           ((x) << 6)    
  53. #define ADC_INPUT(x)        ((x) << 3)    
  54. #define ADC_START           (1 << 0)    
  55. #define ADC_ENDCVT          (1 << 15)    
  56.    
  57. #define DEVICE_NAME  "adc_dev"     
  58.   
  59. static int adc_init()    
  60. {    
  61.     printk("<0>adc_init sucessed!\n");  
  62.       unsigned int preScaler = 0XFF;    
  63.        printk("<0>111111111!\n");  
  64.     ADCCON  = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);    
  65.     ADCCON |= ADC_START;     
  66.     printk("<0>2222222222!\n");  
  67.     return 0;  
  68.   
  69. }    
  70. static int adc_open(struct inode *inode ,struct file *filp)    
  71. {    
  72.   printk("adc_open!\n");  
  73.    adc_init();    
  74.    return 0;    
  75. }    
  76. static int adc_release(struct inode *inode,struct file *filp)    
  77.  {    
  78.     return 0;    
  79.  }    
  80.  static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)    
  81.  {    
  82.      printk("<0>adc_read!\n");  
  83.      int ret=0;  
  84.      ADCCON |= ADC_START;     
  85.     while(ADCCON & 0x01);//check if Enable_start is low     
  86.     while(!(ADCCON &0x8000));/*檢查轉換是否結束*/    
  87.       ret = ADCDAT0 & 0x3ff;    //重點,與參考的不同,我覺得這樣才是正確的  
  88.      copy_to_user(buff,(char *)&ret,sizeof(ret));  
  89.   
  90.      return sizeof(ret);  
  91.  }    
  92.    
  93.  static struct file_operations dev_fops =    
  94.  {    
  95.     .owner = THIS_MODULE,    
  96.      .open = adc_open,    
  97.      .release = adc_release,    
  98.      .read = adc_read,    
  99.  };    
  100.      
  101.  static struct miscdevice misc =    
  102.  {    
  103.     .minor = MISC_DYNAMIC_MINOR,    
  104.     .name = DEVICE_NAME,    
  105.     .fops = &dev_fops,    
  106.  };    
  107.    
  108.  static int __init dev_init()    
  109.  {    
  110.    int ret;    
  111.      
  112.    
  113.     base_addr =ioremap(0x7E00B000,0X20);//地址映射     
  114.     printk("<0>ioremap sucessed!\n");  
  115.      if(base_addr == NULL)    
  116.    {    
  117.        printk(KERN_ERR"failed to remap\n");    
  118.        return -ENOMEM;    
  119.    }    
  120.    
  121.     adc_clock = clk_get(NULL,"adc");//激活adc時鐘模塊     
  122.     printk("<0>clk_get sucessed!\n");  
  123.     if(!adc_clock)    
  124.     {    
  125.       printk(KERN_ERR"failed to get adc clock\n");    
  126.       return -ENOENT;    
  127.     }    
  128.    clk_enable(adc_clock);    
  129.    
  130.      
  131.    ret = misc_register(&misc);//混雜設備注冊     
  132.    printk("dev_init return ret:%d\n",ret);    
  133.     return ret;    
  134. }    
  135. static void __exit dev_exit()    
  136. {    
  137.     iounmap(base_addr);//取消映射     
  138.        
  139.   if(adc_clock)//disable adc clock取消adc時鐘     
  140.    {    
  141.      clk_disable(adc_clock);    
  142.         clk_put(adc_clock);    
  143.     adc_clock =NULL;    
  144.    }    
  145.    misc_deregister(&misc);//注銷混雜設備     
  146.        
  147. }    
  148. module_init(dev_init);    
  149. module_exit(dev_exit);    
  150.    
  151. MODULE_LICENSE("GPL");    
  152. MODULE_AUTHOR("MUGE0913");    

應用程序:

  1. #include <stdio.h>     
  2. #include <fcntl.h>     
  3. #include <unistd.h>     
  4.    
  5. int main()    
  6. {    
  7.     int fp,adc_data,i;  
  8.     int ret;  
  9.     fp = open("/dev/adc_dev",O_RDWR);    
  10.     if(fp<0)  
  11.         printf("open failed!\n");  
  12.     printf("open sucessed!\n");  
  13.       
  14.    for(i=0;i<100;i++)    
  15.    {    
  16.        ret = read(fp,&adc_data,sizeof(adc_data));    
  17.        printf("read sucessed!\n");  
  18.        if(ret<0)  
  19.      {  
  20.         printf("read ADC failed!\n");  
  21.         return -1;  
  22.        }  
  23.        else  
  24.               printf("Read ADC value is: %d\n",adc_data);    
  25.        sleep(1);    
  26.     }    
  27.    close(fp);    
  28.    return 0;    
  29.  }    

運行結果:

Copyright © Linux教程網 All Rights Reserved