1.查寻式的
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/device.h>
#include <asm/irq.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <asm/arch/map.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch-s3c2410/regs-adc.h>
#include <asm/arch-s3c2410/regs-clock.h>
#include "adc.h"
#define DEVICE_NAME "adc"
static int adc_major = 0;
static ssize_t adc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
int data="0";
unsigned long tmp;
//printk("1.........\n");
//start ADC
tmp = readl(S3C2410_ADCCON) | 0x01; //start AD convert
writel( tmp, S3C2410_ADCCON);
// printk("2.........\n");
do{
tmp = readl(S3C2410_ADCCON);
}while(((unsigned int)tmp) & 0x01); //check if Enable_start is low
//printk("3.........\n");
//state
do{
tmp = readl(S3C2410_ADCCON);
}while(!(((unsigned int)tmp)&0x8000));
//read data
// printk("4.........\n");
data = readl(S3C2410_ADCDAT0) & 0x3ff;
// printk("5.........\n");
//printk("data=%d\n", data);
if(copy_to_user(buf, &data, sizeof(data)))
return -EFAULT;
return (sizeof(int));
}
static ssize_t adc_write(struct file * file, const char * buf, size_t count, loff_t * off)
{
unsigned long tmp;
struct ADC_DEV adcdev;
copy_from_user(&adcdev, (struct ADC_DEV *)buf, count);
writel((readl(S3C2410_CLKCON) | S3C2410_CLKCON_ADC),S3C2410_CLKCON); //S3C2410_ADCTSC//使能ADC_CLK
tmp = readl(S3C2410_ADCTSC);
tmp &= (~S3C2410_ADCTSC_AUTO_PST) | S3C2410_ADCTSC_XY_PST(S3C2410_NOP_MODE);
writel(tmp , S3C2410_ADCTSC);
//S3C2410_ADCCON----set chanel and prescaler
tmp = readl(S3C2410_ADCCON);
tmp = S3C2410_ADCCON_PRSCEN | PRSCVL(adcdev.prescale) | ADC_INPUT(adcdev.channel);
writel( tmp, S3C2410_ADCCON);
return sizeof(struct ADC_DEV);
}
static int adc_open(struct inode * inode, struct file * filp)
{
printk("ad convert opened!\n");
return 0;
}
static int adc_release(struct inode * inode, struct file * filp)
{
printk("ad convert closed!\n");
return 0;
}
static void adc_setup_cdev(struct cdev *dev, int minor,
struct file_operations *fops)
{
int err, devno = MKDEV(adc_major, minor);
cdev_init(dev, fops);
dev->owner = THIS_MODULE;
dev->ops = fops;
err = cdev_add (dev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk (KERN_NOTICE "Error %d adding adc %d", err, minor);
}
static struct cdev AdcDevs;
static struct file_operations adc_remap_ops = {
.owner = THIS_MODULE,
.open = adc_open,
.read = adc_read,
.write = adc_write,
.release = adc_release,
};
int __init adc_init(void)
{
/* normal ADC */
int result;
dev_t dev = MKDEV(adc_major, 0);
/* Figure out our device number. */
if (adc_major)
result = register_chrdev_region(dev, 1, "adc");
else {
result = alloc_chrdev_region(&dev, 0, 1, "adc");
adc_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "adc: unable to get major %d\n", adc_major);
return result;
}
if (adc_major == 0)
adc_major = result;
adc_setup_cdev(&AdcDevs, 0, &adc_remap_ops);
printk("adc device installed, with major %d\n", adc_major);
return 0;
}
static void adc_cleanup(void)
{
cdev_del(&AdcDevs);
unregister_chrdev_region(MKDEV(adc_major, 0), 1);
printk("adc device uninstalled\n");
}
module_init(adc_init);
module_exit(adc_cleanup);
MODULE_AUTHOR("Machuanlong");
MODULE_LICENSE("Dual BSD/GPL");
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
adc.h
#ifndef __ADC_H__
#define __ADC_H__
struct ADC_DEV
{
int channel;
int prescale;
};
#define S3C2410_ADCTSC_AUTO_PST (1<<2)
#define S3C2410_NOP_MODE 3
#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
#define ADC_INPUT(x) (x<<3) //选取通道
#define PRSCVL(x) (x<<6) //设分频值
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Makefile:
///////////////////////////////////////////////////////////////////////////////////
ifeq ($(KERNELRELEASE),)
#KERNELDIR ?= /your/target/source/directory/
#KERNELDIR ?= /source/kernel/linux-2.6.8.1-farsight
#KERNELDIR ?= /disk3/linux-2.6.13-mcl+lcd+yaffs2+nand+cs8900
KERNELDIR ?= /disk2/linux-2.6.14
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
.PHONY: modules modules_install clean
else
obj-m := s3c2410-adc.o
endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
测试程序:
/**********************************************
* *AD convert driver test function
* *date : created at 2008-01-03 by baijb
**********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#define PATH "/dev/adc" //device file
static struct ADC_DEV
{
int channel;
int prescale;
}adc_infor;
int main(void)
{
int fd;
int result, data;
int val;
float d;
//int times = 0;
fd = open(PATH, O_RDWR);
if (fd < 0) {
printf("Failed to open ad_driver\n");
exit(1);
}
printf("Please select which chanel to read....\n");
printf("0 : chanel--0\n");
printf("1 : chanel--1\n");
scanf("%d", &val);
if((val !=0) && (val !=1))
val = 0; //by default the chanel is 0
adc_infor.channel = val; //chanel 0 or 1
adc_infor.prescale = 255;
do {
result = write(fd, (void *)&adc_infor, sizeof(adc_infor)) == sizeof(struct ADC_DEV);
if (!result) {
printf("wrong when writing!\n");
goto failed;
}
result = read(fd, &data, sizeof(data)) == sizeof(data);
if (!result) {
printf("Wrong size!\n");
goto failed;
}
//printf("chanel %d --ad result=%d\n", val, data);
printf("fuck1....................");
d=((float)data*3.3)/1024.0;
printf("%8.4f\t",d);
printf("\n");
sleep(1);
}while(1);
failed:
close(fd);
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
挂载方法
insmod s3c2410-adc.ko
mknod /dev/adc c 253 0
./adc_test
用户24289 2008-12-23 11:43