⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adc_drv.c

📁 嵌入式linux ADC驱动及测试程序
💻 C
字号:
/*****************************************************************************
;Institue of Automation, Chinese Academy of Sciences
;www.hyesco.com
;Description: 	ADC driver on Linux for XKMHK
;Date:					2006-5-20		
;Author:		
;E_mail:		
*****************************************************************************/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h> 				//including irq number
#include <asm/arch/AT91RM9200_SYS.h>

//ADC基地址,与硬件电路相关,地址为:0x8000,0000,由NCS7选择。 
#define EBI_BASE_ADDRESS		0x80000000L
#define EBI_OFFSET_ADDRESS	0x00
#define ADDR_sys_offset			EBI_BASE_ADDRESS + EBI_OFFSET_ADDRESS
#define ADDR_Size						0x20

//全局变量,常量;
static int major=249;
static char s_name[]="adc0";
unsigned int *IO_Addr;			//ADC地址指针;

//函数定义;
static int s_open(struct inode * s_node,struct file * s_file);
static int s_release(struct inode * s_node,struct file * s_file);
static int s_write(struct file*s_file, const char*w_buf,int len,loff_t* loff);
static int ADDR_mem();

struct file_operations Tmint_fops_ADDR=
{
		write  :	(void(*)) s_write,
		open   :	(void(*)) s_open,
		release:	(void(*)) s_release,
 };

//地址空间申请与检测函数;
static int ADDR_mem()
{
		
		//申请内存区域,以检测该地址空间是否被使用;
		if (!request_mem_region(ADDR_sys_offset,ADDR_Size,"IO_ADDR"))
			printk("Error request mem I/O address! \r\n"); 
    		
		//进行内存区域的映射,把物理地址映射为逻辑地址;  
		IO_Addr = ioremap(ADDR_sys_offset,ADDR_Size); 
		return 0;	
};

//延时函数;
void Delay(unsigned int x)
{
		unsigned int i,j;
		for(i=0;i<=x;i++)
			for(j=0;j<100;j++)
				;
}

//初始化模块函数;
static int __init s_init_module(void)
{
		int retv;
		//注册模块;
		retv=register_chrdev(major,s_name,&Tmint_fops_ADDR);
		if(retv<0)
			{
			printk("<1>Register Fail!\n");
			return retv;
			}
		ADDR_mem();
		printk("init IO_ADDR module is ok!\n");
		return 0;
}

//清除模块函数;
static void __exit s_cleanup_module(void)
{
 		int retv;
 	
 		//注销模块;
		retv=unregister_chrdev(major,s_name);
 	
 		//取消内存区域映射;
		iounmap(IO_Addr);
	
		//释放申请的内存区域;
		release_mem_region(ADDR_sys_offset,ADDR_Size);
		if(retv<0)
			{
    		printk("<1>IO_ADDR UnRegister Fail!\n");
   			return ;
			}
		printk("<1>IO_ADDR:Good Bye!\n");
}

//open函数
static int s_open(struct inode * s_node,struct file * s_file)
{
		MOD_INC_USE_COUNT;
	
		//定义EBI控制寄存器的读写参数,参考AT91RM9200用户手册P190;
		/* AT91_SYS->EBI_SMC2_CSR[7]= AT91C_SMC2_NWS| AT91C_SMC2_WSEN
			| AT91C_SMC2_TDF | AT91C_SMC2_BAT | AT91C_SMC2_DBW_16
			| AT91C_SMC2_RWHOLD|AT91C_SMC2_ACSS_3_CYCLES;
		*/
		AT91_SYS->EBI_SMC2_CSR[7]= 0x11003183;
		return 0;
}

//write函数 
static int s_write(struct file*s_file, const char *w_buf,int len,loff_t* loff)
{
		
		unsigned int Channel;
		unsigned int res,i;
		
		//从用户空间拷贝数据到内核空间;		
		if(copy_from_user(&Channel,w_buf,sizeof(unsigned int)))	
				return -EFAULT;
		
		//设定PC11、PC12口为输出
    
    //PIO Enable Register
   	AT91_SYS->PIOC_PER = (unsigned int)(1<<11)|(unsigned int)(1<<12); 
   	//PIO Output Enable Register
    AT91_SYS->PIOC_OER = (unsigned int)(1<<11)|(unsigned int)(1<<12); 	
    //PIO Output Write Register
    AT91_SYS->PIOC_OWER = (unsigned int)(1<<11)|(unsigned int)(1<<12);	       
       
    //通道选择;
    switch(Channel)
    		{
    		case 0:
    			 AT91_SYS->PIOC_ODSR = (unsigned int)(0<<12)|(unsigned int)(0<<11);
    			 break;
    			 
    		case 1:
    			 AT91_SYS->PIOC_ODSR = (unsigned int)(0<<12)|(unsigned int)(1<<11);
    			 break;
    			 
    		case 2:
    			 AT91_SYS->PIOC_ODSR = (unsigned int)(1<<12)|(unsigned int)(0<<11);
    			 break;
    		
    		case 3:
    			 AT91_SYS->PIOC_ODSR = (unsigned int)(1<<12)|(unsigned int)(1<<11);
    			 break;
    		}
    
    Delay(100);
		  	
  	//启动AD转换,并等待转换结束,同时求8次AD转换结果的均值;
  	res = 0;
  	for(i=0;i<8;i++)
  			{
  			*IO_Addr = 0x0;
   			Delay(500);
   			res = res + ((*IO_Addr) & 0xfff);
   			}
   	
   	//返回AD转换的值;
   	return (res >> 3);      		
}

//release函数
static int s_release(struct inode * s_node,struct file * s_file)
{
		MOD_DEC_USE_COUNT;
		return 0;
}

module_init(s_init_module);
module_exit(s_cleanup_module);
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -