📄 robot_adc.c
字号:
/** system depend file*/#include <linux/init.h>#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/delay.h>#include <linux/proc_fs.h>#include <linux/fcntl.h> /* O_ACCMODE */#include <linux/aio.h>#include <linux/interrupt.h>#include <linux/device.h>#include <asm/hardware.h>#include <asm/hardware/clock.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/leds.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <asm/semaphore.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/arch/map.h>#include <asm/arch/regs-adc.h>#include <asm/arch/regs-timer.h>#define DEVFS_FL_DEFAULT 0x000#define ADC_DEVNAME "robot_adc"static int nADCMajor = 0;extern devfs_mk_dir(const char *fmt,...);int ADC_major = 0;int ADC_devs = 1; /* number of bare ADC devices */struct unit { //struct semaphore lock; u32 *ADCCON; u32 *ADCDAT0; }; static struct unit ADC_unit={ .ADCCON = (u32 *)S3C2410_ADCCON, .ADCDAT0 = (u32 *)S3C2410_ADCDAT0, };extern struct platform_device s3c_device_i2c; void delay(int usecs){ volatile int loops; for(loops = usecs * 12; loops > 0; loops--) /* nothing */; }static void address_map(void) { #define ADC_ADDR (0x58000000) void __iomem *regs; struct clk *clk; clk = clk_get(NULL, "adc"); if (IS_ERR(clk)) return; clk_use(clk); clk_enable(clk); regs=ioremap(ADC_ADDR, 0x08000000); ADC_unit.ADCCON = (u32*)(regs+0x00000000); ADC_unit.ADCDAT0 = (u32*)(regs+0x0000000C); }int ADC_open (struct inode *inode, struct file *file) { printk("open ADC\n"); file->private_data=&ADC_unit; return 0; /* success */ } static int ADC_release_f (struct inode *inode, struct file *file) { //printk("release\n"); return 0; } static int prevCh=-1;int value;static ssize_t ADC_read (struct file *file, const char *buf, size_t count, loff_t *offset)// count= Number of reading channel { int ret,ch; struct unit *unit=(struct unit *)file->private_data; ch=count & 0x7; *unit->ADCCON = *unit->ADCCON & 0xffc7 | (ch<<3); //setup channel if(prevCh!=ch) { delay(100);//delay to set up the channel prevCh=ch; } //printk("ADCCON=0x%X\n",*unit->ADCCON); delay(1000); *unit->ADCCON = *unit->ADCCON | 0x1;////start ADC while(*unit->ADCCON & 0x1) printk(KERN_ALERT,"a\n"); //check if Enable_start is low while(!(*unit->ADCCON & 0x8000)); //check if EC(End of Conversion) flag is high value= (*unit->ADCDAT0) & 0x3ff ; count=2; //printk("read:adc_data=0x%X\n",value); ret=copy_to_user(buf, &value, count) ? -EFAULT:count; return ret; } static struct file_operations ADC_ops = { .owner = THIS_MODULE, .read = ADC_read, .open = ADC_open, .release = ADC_release_f,};static int ADC_init(void) { u32 temp; int res; #ifdef CONFIG_DEVFS_FS res= register_chrdev(0,ADC_DEVNAME, &ADC_ops); if(res<0) { printk("robot_ADC.o:unable to get major for ADC device.\n"); return res; } //create the devfs: /driver/ADC/ devfs_mk_dir(ADC_DEVNAME); devfs_mk_cdev(MKDEV(res,0),S_IFCHR | S_IRUSR |S_IWUSR, ADC_DEVNAME"/%d",0); #else res = register_chrdev(nADCMajor, ADC_DEVNAME, &ADC_ops); #endif address_map(); //get the major number if(nADCMajor==0) { nADCMajor = res; printk("ADC major number = %d.\n",nADCMajor); } printk("ADCCON=0x%X\n",*ADC_unit.ADCCON); *ADC_unit.ADCCON=(1<<14)|(49<<6);//A/D converter freq. = 50 MHz/(49+1) = 1 MHz printk("ADCCON=0x%X after setting\n",*ADC_unit.ADCCON); *ADC_unit.ADCCON = (*ADC_unit.ADCCON) | 0x1;//A/D converter freq. = 50 MHz/(49+1) = 1 MHz delay(100); printk("ADCCON=0x%X after setting start\n",*ADC_unit.ADCCON); return 0;}static void ADC_exit(void) { int ret; ret=unregister_chrdev(nADCMajor, ADC_DEVNAME); if (ret<0) printk("error in module unregistering\n"); printk("Out,Out.\n"); }module_init(ADC_init);module_exit(ADC_exit);MODULE_AUTHOR("JORRY");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -