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

📄 2410-adc-2.c

📁 嵌入式开发板s3c2410的模数转换模块的linux操作系统驱动程序
💻 C
字号:
/*
*    HLG442-S3C2410-ADC_DRV 
* /26/03/2008    AUTHOR "machuanlong"
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/hardware.h>
#include <asm/semaphore.h>
#include <asm/uaccess.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/mm.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <asm/io.h>


#include <linux/errno.h>

#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <asm/irq.h>
#include <asm/arch/regs-adc.h>
#include <asm/arch/map.h>
#include <asm/hardware/clock.h>
#include "s3c2410-adc.h"

#include <asm/arch/regs-irq.h>
#include <asm/arch-s3c2410/regs-clock.h>
 
#define DEVICE_NAME "adc"
static int adc_major = 0;
typedef struct {
 struct semaphore lock;
 wait_queue_head_t wait;
 int channel;
 int prescale;
}ADC_DEV;
static ADC_DEV adcdev;
static irqreturn_t adcdone_int_handler(int irq,void *dev_id,struct pt_regs *regs)
{
 wake_up(&adcdev.wait);
 return IRQ_HANDLED ;
}
static ssize_t s3c2410_adc_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
{
 return 0;
}
static ssize_t s3c2410_adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
 int ret = 0;
  
 if (down_interruptible(&adcdev.lock))
  return -ERESTARTSYS;
 writel((readl(S3C2410_CLKCON) | S3C2410_CLKCON_ADC),S3C2410_CLKCON);
 writel((1<<14) | PRSCVL(adcdev.prescale) | ADC_INPUT(adcdev.channel) | 0x01 | 0x01, S3C2410_ADCCON);
 interruptible_sleep_on(&adcdev.wait);
 ret = readl(S3C2410_ADCDAT0);
 ret &= 0x3ff;
 copy_to_user(buffer, (char *)&ret, sizeof(ret));
 up(&adcdev.lock);

 return sizeof(ret);
}
static int s3c2410_adc_open(struct inode *inode, struct file *filp)
{ 
  int ret;
  ret = request_irq(IRQ_ADC, adcdone_int_handler, SA_INTERRUPT, DEVICE_NAME, NULL);
 if (ret) {
  return ret;
 }
 init_MUTEX(&adcdev.lock);
 init_waitqueue_head(&(adcdev.wait));
 adcdev.channel=0;
 adcdev.prescale=255;
 return 0;
}
static int s3c2410_adc_release(struct inode *inode, struct file *filp)
{
 free_irq(IRQ_ADC, NULL);
 printk( "adc 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 = s3c2410_adc_open,
 .read = s3c2410_adc_read, 
 .write = s3c2410_adc_write,
 .release = s3c2410_adc_release,
};

int __init adc_init(void)
{
 /* normal ADC */
 writel(0,S3C2410_ADCTSC); //XP_PST(NOP_MODE);
 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");
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
Makefile(驱动的)
///////////////////////////////////////////////////////////////////////////////////
ifeq ($(KERNELRELEASE),)
#KERNELDIR ?= /source/kernel/linux-2.6.8.1-farsight
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
 
///////////////////////////////////////////////////////////////////////////////////
s3c2410-adc.h
///////////////////////////////////////////////////////////////////////////////////
#ifndef _S3C2410_ADC_H_
#define _S3C2410_ADC_H_
#define ADC_WRITE(ch, prescale) ((ch)<<16|(prescale))
#define ADC_WRITE_GETCH(data) (((data)>>16)&0x7)
#define ADC_WRITE_GETPRE(data) ((data)&0xff)
#define ADC_INPUT(x)  (x<<3)
#define PRSCVL(x)  (x<<6)
#endif /* _S3C2410_ADC_H_ */
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
测试程序:
main.c
///////////////////////////////////////////////////////////////////////////////////
/************************************************\
**HLG442 ADC-TEST
 /26/3/2008
Author machuanlong 
*      *
\***********************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <fcntl.h>
#include "s3c2410-adc.h"
#define ADC_DEV  "/dev/adc"
static int adc_fd=-1;
static int GetADresult(int channel)
{
 int data;
 int PRESCALE=0xFF;
 int data=ADC_WRITE(channel, PRESCALE);
 write(adc_fd, &data, sizeof(data));
 read(adc_fd, &data, sizeof(data));
 return data;
}
static int stop=0;
int main(void)
{
 int i;
 float d;
 if((adc_fd=open(ADC_DEV, O_RDWR))<0){
  printf("Error opening %s adc device\n", ADC_DEV);
  return -1;
 }
                                                                               
 for(i=0;i<=7;i++){
   d=((float)GetADresult(i)*3.3)/1024.0;
   printf("a%d=%8.4f\t",i,d);
   printf("\n");
   sleep(1);
   printf("\r");
  
 }
 close(adc_fd);
 return 0;
}

⌨️ 快捷键说明

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