📄 adc_drv.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 + -