FL2440 ADC 数据采样

一、开发环境

软件开发环境:linux-3.0

硬件开发环境:fl2440开发板

日期:2013.12.22


二、这个ADC驱动程序虽然很简单,但是我在写的时候费了很多时间,因为一开始我用中断来读数据,然而AD的中断号跟LCD的中断号共用了,用了共享中断,还是没能解决,由于能力有限,就没有用中断。下面是我写的ADC驱动的代码:

/*********************************************************************************
 *      Copyright:  (C) 2013 Yang zheng<yangzheng@gmail.com>  
 *                  All rights reserved.
 *
 *       Filename:  fl2440_adc.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(12/17/2013~)
 *         Author:  yangzheng <yangzheng@mail.com>
 *      ChangeLog:  1, Release initial version on "12/17/2013 07:14:19 PM"
 *                 
 ********************************************************************************/


#include <plat/regs-adc.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/clk.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/wait.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>




#define DEVICE_NAME             "s3c-adc"
#define CON_BASE                0x58000000
#define DATA_BASE               0x5800000c
#define CON_LEN                 4
#define DATA_LEN                4
#define s3c_adc_write(val, reg) __raw_writel((val), (reg))
#define s3c_adc_read(reg)       __raw_readl((reg))
#define DEV_MAJOR               0
#define DESABLE                 0


static void __iomem *adc_con; /* Defines a after virtual map is used to store the memory address*/
static void __iomem *adc_dat0; /* Defines a after virtual map is used to store the memory address*/
static struct clk *adc_clk; /* Save the clock in the queue for the ADC clock from the platform*/
static DEFINE_MUTEX(ADC_CLK); /* Statements and initialize a semaphore ADC_LOCK, on ADC resources for exclusive access*/


int         dev_major = DEV_MAJOR;
int         dev_minor = 0;
int         dev_count = 1;
int         debug = DESABLE;


static struct cdev *adc_cdev;


/* The opening of the ADC device driver interface function */
static int adc_open(struct inode *inode, struct file *file)
{
    int minor = iminor(inode); 


    file->private_data = (void *)minor;


    printk(KERN_DEBUG "dev/fl2440_adc %d opened.\n", minor);


    return 0;
}


/* The reading of the ADC device driver interface function*/
static ssize_t adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{


    unsigned long adc_data;
    unsigned int  tmp;


    adc_con = ioremap(CON_BASE, CON_LEN); /* The memory mapping */
    adc_dat0 = ioremap(DATA_BASE, DATA_LEN); /* The memory mapping */


    tmp = s3c_adc_read(adc_con);
    tmp = (0x1 << 14) | (0x5 << 6) | (0x0 << 3); /* 0100 00001 100 0000 */    
    s3c_adc_write(tmp, adc_con); 
    
    tmp = s3c_adc_read(adc_con);
    tmp = tmp | (0x1 << 0);
    s3c_adc_write(tmp, adc_con);  /* Start the AD conversion*/


    while (s3c_adc_read(adc_con) &0x1);  /* Waiting to start a reset*/ 
    while (!(s3c_adc_read(adc_con) & 0x8000)); /* Waiting for the AD conversion to complete*/ 


    mutex_lock(&ADC_CLK);
    adc_data = s3c_adc_read(adc_dat0);


    copy_to_user (buffer, (char *)&adc_data, sizeof(adc_data));
    
    mutex_unlock(&ADC_CLK);


    return sizeof(adc_data);


}


/* The closing of the ADC device driver interface function */
static int adc_release(struct inode *inode, struct file *filp)
{
    return 0;
}


/* Character device related operations */
static struct file_operations adc_fops = {
    .owner = THIS_MODULE,
    .open = adc_open,
    .read = adc_read,
    .release = adc_release,
};


/* Misc equipment structure */
//static struct miscdevice adc_miscdev = {
 //   .minor = MISC_DYNAMIC_MINOR, /* In the device number, defined in miscdevice. H, 255*/
  //  .name = DEVICE_NAME, /* Device name */
   // .fops = &adc_fops, /* The ADC device file operations */
//};
static int __init adc_init(void)
{
    int             ret;
    dev_t           devno;


    if (0 != dev_major)
    {
        devno = MKDEV(dev_major, 0);
        ret = register_chrdev_region(devno, dev_count, DEVICE_NAME);
    }
    else
    {
        ret = alloc_chrdev_region(&devno, dev_minor, dev_count, DEVICE_NAME);
        dev_major = MAJOR(devno);
    }
    if (ret < 0)
    {
        printk(KERN_ERR "S3C %s driver can't use major %d\n", DEVICE_NAME, dev_major);
        return -ENODEV;
    }
    
    printk(KERN_DEBUG "S3C %s driver major %d\n", DEVICE_NAME, dev_major);
    
    /* The clock in the queue for the ADC clock from the platform*/
    adc_clk = clk_get(NULL, "fl2440_adc");
    if (!(adc_clk = clk_get(NULL, "fl2440_adc")))
    {
        printk(KERN_ERR "failed to find adc clock source.\n");
        goto err_irq;
        return ENOENT;
    }


    /* The clock can get to make before you can use*/
    clk_enable(adc_clk);


    /* The ADC registered as misc equipment */
    /*  ret = misc_register(&adc_miscdev);
    if (ret)
    {
        printk(KERN_ERR "cannot register on minor=%d (%d)", MISC_DYNAMIC_MINOR, ret);
        goto err_noclk;
    }*/
    if(NULL == (adc_cdev=cdev_alloc()) )
    {
        printk(KERN_ERR "S3C %s driver can't alloc for the cdev.\n", DEVICE_NAME);
        unregister_chrdev_region(devno, dev_count);
        return -ENOMEM; 


    }   
        
    adc_cdev->owner = THIS_MODULE;
    cdev_init(adc_cdev, &adc_fops);
             
    ret = cdev_add(adc_cdev, devno, dev_count);
    if (0 != ret)
    {   
        printk(KERN_INFO "S3C %s driver can't reigster cdev: result=%d\n", DEVICE_NAME, ret);
        goto ERROR;
    }   
                             
    printk(DEVICE_NAME "initialized.\n");


    return 0;
    
ERROR:
    printk(KERN_ERR "S3C %s driver installed failure.\n", DEVICE_NAME);
    cdev_del(adc_cdev);
    unregister_chrdev_region(devno, dev_count);
    return ret;
err_irq:
    free_irq(IRQ_ADC, (void *)1);
    return ret;
}


void __exit adc_exit(void)
{
    dev_t devno = MKDEV(dev_major, dev_minor);
    cdev_del(adc_cdev);
    unregister_chrdev_region(devno, dev_count);
    iounmap(adc_con); 
    iounmap(adc_dat0);
    
    if (adc_clk)
    {
        clk_disable(adc_clk);
        clk_put(adc_clk);
        adc_clk = NULL;
    }


    printk(KERN_ERR "S3C %s driver removed!\n", DEVICE_NAME);


    return ;


}


module_init(adc_init);
module_exit(adc_exit);


module_param(debug, int, S_IRUGO);
module_param(dev_major, int, S_IRUGO);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("YangZheng");
MODULE_DESCRIPTION("FL2440 ADC Driver");


三、测试程序

/*********************************************************************************
 *      Copyright:  (C) 2013 Yang zheng<yangzheng@gmail.com>  
 *                  All rights reserved.
 *
 *       Filename:  adc_test.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(12/18/2013~)
 *         Author:  yangzheng <yangzheng@mail.com>
 *      ChangeLog:  1, Release initial version on "12/18/2013 08:28:44 PM"
 *                 
 ********************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int         fd;
   


    fd = open("/dev/s3c-adc", 0);
    if (fd < 0 )
    {
        printf("Open ADC device failed.\n");
        exit(1);
    } 


    for( ;  ;  )
    {
        int         ret;
        int         data;


        ret = read(fd, &data, sizeof(data));
        if (sizeof(data) != ret)
        {
            if (errno != EAGAIN)
            {
                printf("Read ADC device failed.\n");
            }
            continue;
        }       
        else
        {
            printf("ADC value is :%d\n", data);
        }
        sleep(1);
    }


    close(fd);
    return 0;
} /* ----- End of main() ----- */




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值