mini6410 實現 linux adc驅動詳解--muge0913版 .

←手機掃碼閱讀     火星人 @ 2014-03-03 , reply:0

mini6410 實現 linux adc驅動詳解--muge0913版 .

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驅動程序及註釋view plaincopy to clipboardprint?
01.#include    
02.#include    
03.#include    
04.#include    
05.#include    
06.#include    
07.#include    
08.#include    
09.#include    
10.#include    
11.#include    
12.#include    
13.  
14.  
15.#include    
16.#include    
17.#include    
18.  
19.#include    
20.#include    
21.#include    
22.#include    
23.static void __iomem * base_addr;  
24.static struct clk *adc_clock;  
25.  
26.  
27.#define __ADCREG(name)  (*(volatile unsigned long *)(base_addr + name))   
28.#define ADCCON          __ADCREG(S3C_ADCCON)    // ADC control   
29.#define ADCTSC          __ADCREG(S3C_ADCTSC)    // ADC touch screen control   
30.#define ADCDLY          __ADCREG(S3C_ADCDLY)    // ADC start or Interval Delay   
31.#define ADCDAT0         __ADCREG(S3C_ADCDAT0)   // ADC conversion data 0   
32.#define ADCDAT1         __ADCREG(S3C_ADCDAT1)   // ADC conversion data 1   
33.#define ADCUPDN         __ADCREG(S3C_ADCUPDN)   // Stylus Up/Down interrupt status   
34.  
35.#define PRESCALE_DIS        (0 << 14)   
36.#define PRESCALE_EN         (1 << 14)   
37.#define PRSCVL(x)           ((x) << 6)   
38.#define ADC_INPUT(x)        ((x) << 3)   
39.#define ADC_START           (1 << 0)   
40.#define ADC_ENDCVT          (1 << 15)   
41.  
42.#define DEVICE_NAME "adc_dev"   
43.static int adc_init()  
44.{  
45.    unsigned int preScaler = 0XFF;  
46.    ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);  
47.    ADCCON |= ADC_START;   
48.    return 0;  
49.}  
50.static int adc_open(struct inode *inode ,struct file *filp)  
51.{  
52.    adc_init();  
53.    return 0;  
54.}  
55.static int adc_release(struct inode *inode,struct file *filp)  
56.{  
57.    return 0;  
58.}  
59.static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)  
60.{  
61.    ADCCON |= ADC_START;   
62.    while(ADCCON & 0x01);//check if Enable_start is low   
63.    while(!(ADCCON &0x8000));/*檢查轉換是否結束*/  
64.    return (ADCDAT0 & 0x3ff);  
65.}  
66.  
67.static struct file_operations dev_fops =  
68.{  
69.    .owner = THIS_MODULE,  
70.    .open = adc_open,  
71.    .release = adc_release,  
72.    .read = adc_read,  
73.};  
74.  
75.static struct miscdevice misc =  
76.{  
77.    .minor = MISC_DYNAMIC_MINOR,  
78.    .name = DEVICE_NAME,  
79.    .fops = &dev_fops,  
80.};  
81.  
82.static int __init dev_init()  
83.{  
84.    int ret;  
85.  
86.  
87.    base_addr =ioremap(SAMSUNG_PA_ADC,0X20);//地址映射   
88.    if(base_addr == NULL)  
89.    {  
90.        printk(KERN_ERR"failed to remap\n");  
91.        return -ENOMEM;  
92.    }  
93.  
94.    adc_clock = clk_get(NULL,"adc");//激活adc時鐘模塊   
95.    if(!adc_clock)  
96.    {  
97.        printk(KERN_ERR"failed to get adc clock\n");  
98.        return -ENOENT;  
99.    }  
100.    clk_enable(adc_clock);  
101.  
102.  
103.    ret = misc_register(&misc);//混雜設備註冊   
104.    printk("dev_init return ret:%d\n",ret);  
105.    return ret;  
106.}  
107.static void __exit dev_exit()  
108.{  
109.    iounmap(base_addr);//取消映射   
110.      
111.    if(adc_clock)//disable adc clock取消adc時鐘   
112.    {  
113.        clk_disable(adc_clock);  
114.        clk_put(adc_clock);  
115.        adc_clock =NULL;  
116.    }  
117.    misc_deregister(&misc);//註銷混雜設備   
118.      
119.}  
120.module_init(dev_init);  
121.module_exit(dev_exit);  
122.  
123.MODULE_LICENSE("GPL");  
124.MODULE_AUTHOR("MUGE0913");  
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


#include
#include
#include

#include
#include
#include
#include
static void __iomem * base_addr;
static struct clk *adc_clock;


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

#define PRESCALE_DIS                (0 << 14)
#define PRESCALE_EN                        (1 << 14)
#define PRSCVL(x)                        ((x) << 6)
#define ADC_INPUT(x)                ((x) << 3)
#define ADC_START                        (1 << 0)
#define ADC_ENDCVT                        (1 << 15)

#define DEVICE_NAME "adc_dev"
static int adc_init()
{
        unsigned int preScaler = 0XFF;
        ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);
        ADCCON |= ADC_START;
        return 0;
}
static int adc_open(struct inode *inode ,struct file *filp)
{
        adc_init();
        return 0;
}
static int adc_release(struct inode *inode,struct file *filp)
{
        return 0;
}
static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)
{
        ADCCON |= ADC_START;
        while(ADCCON & 0x01);//check if Enable_start is low
        while(!(ADCCON &0x8000));/*檢查轉換是否結束*/
        return (ADCDAT0 & 0x3ff);
}

static struct file_operations dev_fops =
{
        .owner = THIS_MODULE,
        .open = adc_open,
        .release = adc_release,
        .read = adc_read,
};

static struct miscdevice misc =
{
        .minor = MISC_DYNAMIC_MINOR,
        .name = DEVICE_NAME,
        .fops = &dev_fops,
};

static int __init dev_init()
{
        int ret;


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

        adc_clock = clk_get(NULL,"adc");//激活adc時鐘模塊
        if(!adc_clock)
        {
                printk(KERN_ERR"failed to get adc clock\n");
                return -ENOENT;
        }
        clk_enable(adc_clock);


        ret = misc_register(&misc);//混雜設備註冊
        printk("dev_init return ret:%d\n",ret);
        return ret;
}
static void __exit dev_exit()
{
        iounmap(base_addr);//取消映射
       
        if(adc_clock)//disable adc clock取消adc時鐘
        {
                clk_disable(adc_clock);
                clk_put(adc_clock);
                adc_clock =NULL;
        }
        misc_deregister(&misc);//註銷混雜設備
       
}
module_init(dev_init);
module_exit(dev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("MUGE0913");四、測試程序view plaincopy to clipboardprint?
01.#include    
02.#include    
03.#include    
04.  
05.int main()  
06.{  
07.    int fp,adc_data,i;  
08.    fp = open("/dev/adc_dev",O_RDWR);  
09.    for(i=0;i<100;i++)  
10.    {  
11.    adc_data = read(fp,NULL,0);  
12.    printf("%d\n",adc_data);  
13.    sleep(1);  
14.    }  
15.    close(fp);  
16.    return 0;  
17.}  
#include
#include
#include

int main()
{
        int fp,adc_data,i;
        fp = open("/dev/adc_dev",O_RDWR);
        for(i=0;i<100;i++)
        {
        adc_data = read(fp,NULL,0);
        printf("%d\n",adc_data);
        sleep(1);
        }
        close(fp);
        return 0;
}五、運行效果


《解決方案》

學習鳥  謝謝分享
《解決方案》

多路接入如何處理?通道選擇如何處理?不同通道性能要求不同如何配置?




[火星人 ] mini6410 實現 linux adc驅動詳解--muge0913版 .已經有538次圍觀

http://coctec.com/docs/service/show-post-517.html