设为首页收藏本站

米尔科技论坛

 找回密码
 注册账号

QQ登录

只需一步,快速开始

查看: 5086|回复: 0

mx28 ADC驱动与测试

[复制链接]

34

主题

43

帖子

363

积分

中级会员

Rank: 3Rank: 3

积分
363
conway 发表于 2015-5-26 17:48:46 | 显示全部楼层 |阅读模式
本帖最后由 conway 于 2015-5-26 18:20 编辑

默认情况下ADC驱动没有将接口导出到用户空间,它只是应用于电阻触屏,若要使用别的ADC通道还得另外实现驱动,下面是一个简单的ADC驱动及测试程序:
lradc.c:
#include<linux/module.h>                                                /* module                       */
#include<linux/fs.h>                                                    /* file operation               */
#include<asm/uaccess.h>                                                 /* get_user()                   */
#include<linux/miscdevice.h>                                            /* miscdevice                   */
#include<asm/io.h>                                                      /* ioctl                        */
#include <mach/regs-lradc.h>						/* #define                      */


static void __iomem *adc_base = NULL;


static int adc_open (struct inode *inode, struct file *fp) 
{

	try_module_get(THIS_MODULE);
	writel(0xC0000000, adc_base + HW_LRADC_CTRL0_CLR);              /* 开启CLK,关闭复位模式        */
	writel(0x18430000, adc_base + HW_LRADC_CTRL1_CLR);              /* 关闭0-1-6通道及按键中断      */ 
	writel(0x30000000, adc_base + HW_LRADC_CTRL3_SET);              /* 忽略上电前三次采集数据       */     
	writel(0x76543210, adc_base + HW_LRADC_CTRL4);                  /* 设置对应的数据存放位置       */
	
	printk("adc open!\n");
	return 0;
}
static int adc_release (struct inode *inode, struct file *fp)
{
	module_put(THIS_MODULE);
    
	printk("adc closed!\n");
	return 0;
}
/*********************************************************************************************************
**   cmd: 
**	10:CH0     	11:CH1    	16:CH6  	 17:Vbat(内部除4)	  
**      20:CH0(开启除2) 21:CH1(开启除2) 26::CH6(开启除2) 
**
**   被注释部分为3.0以上内核函数定义形式
*********************************************************************************************************/

//static int adc_ioctl(struct file *fp, struct file *flip, unsigned int cmd, unsigned long arg)
static int adc_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
{
    	int iRes;
	int iTmp;
	
	if(cmd <10 || cmd >27){
		return -1;
	}

	iTmp = cmd % 10;
   		
	if(cmd == 20){
		writel(0x01000000, adc_base + HW_LRADC_CTRL2_SET);
	}
	if(cmd == 10){	
		writel(0x01000000, adc_base + HW_LRADC_CTRL2_CLR);
	}
        if(cmd == 21){
                writel(0x02000000, adc_base + HW_LRADC_CTRL2_SET);
        }
	if(cmd == 11){	
		writel(0x02000000, adc_base + HW_LRADC_CTRL2_CLR);
	}
        if(cmd == 26){	
                writel(0x40000000, adc_base + HW_LRADC_CTRL2_SET);
        }
	if(cmd == 16){	
		writel(0x40000000, adc_base + HW_LRADC_CTRL2_CLR);
	}
	
	writel(0x00000001 << iTmp, adc_base + HW_LRADC_CTRL0_SET);
        
    	while(!( readl(adc_base + HW_LRADC_STATUS) & ((1 << 16) << iTmp) )); 
    		
	iRes = readl(adc_base + HW_LRADC_CHn(iTmp));

	iRes = iRes & 0x0003FFFF;	
    
   	copy_to_user((void *)arg, (void *)(&iRes), sizeof(int));
    
    	return 0;
}
/*********************************************************************************************************
Device Struct
*********************************************************************************************************/
struct file_operations adc_fops = 
{
	.owner		= THIS_MODULE,
	.open		= adc_open,
	.release	= adc_release,
    	.ioctl      	= adc_ioctl,
};
static struct miscdevice adc_miscdev = 
{
	.minor	        = MISC_DYNAMIC_MINOR,
   	.name	        = "simple-adc",
    	.fops	        = &adc_fops,
};
/*********************************************************************************************************
Module Functions
*********************************************************************************************************/
static int __init adcModule_init (void)
{
    	int iRet=0;
    	printk("\nadc module init!\n");
	
	adc_base = ioremap(0x80050000, 0x180*4);    
	
    	iRet = misc_register(&adc_miscdev);
	if (iRet) {
		printk("register failed!\n");
	} 
	return iRet;
}
static void __exit adcModule_exit (void)                                /* warning:return void          */
{
	printk("\nadc module exit!\n");
	misc_deregister(&adc_miscdev);
}
/*********************************************************************************************************
Driver Definitions
*********************************************************************************************************/
module_init(adcModule_init);
module_exit(adcModule_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("abcdczj@163.com");
MODULE_DESCRIPTION("imx28x LRADC");
/*********************************************************************************************************
End File
*********************************************************************************************************/


lradc_test.c:
#include<stdio.h>	/* using printf()        */
#include<stdlib.h>      /* using sleep()         */
#include<fcntl.h>       /* using file operation  */
#include<sys/ioctl.h>   /* using ioctl()         */

int main(int argc, char *argv[])
{
	int fd;
	int iRes;
	int time = 100;
	double val;

	fd = open("/dev/simple-adc", 0);
	if(fd < 0){
		printf("open error by APP- %d\n",fd);
		close(fd);
		return 0;
	}

	while(time--){
		sleep(1);		

		ioctl(fd, 20, &iRes);			/* 开启除2     CH0    */
		val = (iRes * 3.7) / 4096.0;
		printf("CH0:%.2f\t", val);

		ioctl(fd, 11, &iRes);                   /* 不开除2     CH1    */
		val = (iRes * 1.85) / 4096.0;
       		printf("CH1:%.2f\t", val);

        	ioctl(fd, 26, &iRes);                   /* 开启除2     CH6    */
		val = (iRes * 3.7) / 4096.0;
        	printf("CH6:%.2f\t", val);

        	ioctl(fd, 17, &iRes);                   /* 电池电压默认除4    */
		val = (iRes * 7.4) / 4096.0;
        	printf("Vbat:%.2f\t", val);

		printf("\n");
	}
	close(fd);
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

Archiver|手机版|小黑屋|米尔科技论坛   

GMT+8, 2019-10-21 14:18 , Processed in 0.412177 second(s), 25 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表