Chinaunix首页 | 论坛 | 博客
  • 博客访问: 44863
  • 博文数量: 14
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 180
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-10 16:54
文章分类
文章存档

2011年(1)

2008年(13)

我的朋友
最近访客

分类: LINUX

2008-04-10 19:09:17

1.查寻式的
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#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
 
阅读(2640) | 评论(14) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-04-13 16:12:43

博主,你好!我编译你的驱动程序,提示S3C2410_CLKCON_ADC和S3C2410_ADCCON_PRSCEN 没有定义!然后,我把S3C2410_CLKCON_ADC改成了S3C2410_CLKCON,把S3C2410_ADCCON_PRSCEN改成了PRSCALE_EN ,再编译就没错了!为什么S3C2410_CLKCON_ADC和S3C2410_ADCCON_PRSCEN 会没有定义??? 最后,我运行的测试程序,提示wrong when writing! 也就是write 函数出错了?这又是为什么了? 博主如果有空,请尽快给予解答! 在此先谢过了!!!

chinaunix网友2011-01-19 21:41:23

你好 你的程序是 通道口都设置在触屏上的吗?能修改成其他的通道吗?

gamestarck2009-11-24 21:31:32

是内核版本不匹配的原因吗??

gamestarck2009-11-24 21:29:39

我的邮箱chenkai287989266@163.com QQ287989266 盼博主赐教咧

gamestarck2009-11-24 21:27:48

我用的是2.6.12的核,S3C2440的,应该也可以用,出现错误如下,博主能给指点下吗?谢谢了 [root@(none) adc]# ./adc_test ad convert opened! Please select chanel(0,1): 0 Please select prescale: 255 Unable to handle kernel NULL pointer dereference at virtual address 00000004 pgd = c260c000 [00000004] *pgd=325c8031, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#2] Modules linked in: adc s3c2410mci clk CPU: 0 PC is at adc_write+0x68/0xa0 [adc] LR is at adc_write+0x3c/0xa0 [adc] pc : []