2410自带ad

2410自带了8个ad通道,10bit,500ksps。在网上查了资料,很少有人用它做ad转换的,原因是精度不高。不过对于一些要求不是很高的地方,还是值得一用。
在/kernel/drivers/char中已经有了ad不完整的驱动,基本框架搭好了,只要加上文件系统那部分就可以直接使用了。使用时一定要在Vref上加上电压,否则ad就不工作了。现在就把驱动和应用程序贴出来,供大家参考学习。
应用程序的作用是要测量的通道号告诉驱动,驱动得到通道号经过ad转换后将数字量传给应用程序。
驱动程序:
/*
* s3c2410-adc.c
*
* S3C2410 ADC
*  exclusive with s3c2410-ts.c
*/
#include linux/config.h>
#include linux/module.h>
#include linux/kernel.h>
#include linux/init.h>
#include linux/sched.h>
#include linux/irq.h>
#include linux/delay.h>
#include asm/hardware.h>
#include asm/semaphore.h>
#include asm/uaccess.h>
#include asm/io.h>

#define DEVICE_NAME"s3c2410-adc"
#define ADCRAW_MINOR1
#define ADC_WRITE(ch, prescale)((ch)<<16|(prescale))
#define ADC_WRITE_GETCH(data)(((data)>>16)&0x7)   //得到通道号
#define ADC_WRITE_GETPRE(data)((data)&0xff)      //得到转换的比例因子

static int adcMajor = 0;

typedef struct {
struct semaphore lock;
wait_queue_head_t wait;
int channel;
int prescale;
}ADC_DEV;

static ADC_DEV adcdev;

#define START_ADC_AIN(ch, prescale) \
do{ \
ADCCON = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT((ch)) ; \
ADCCON |= ADC_START; \
}while(0)

static void adcdone_int_handler(int irq, void *dev_id, struct pt_regs *reg)
{
wake_up(&adcdev.wait);
}

static ssize_t s3c2410_adc_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
{
int data;

if(count!=sizeof(data)){
printk("the size of  input data must be %d\n", sizeof(data));
return 0;
}
copy_from_user(&data, buffer, count);
adcdev.channel=ADC_WRITE_GETCH(data);
adcdev.prescale=ADC_WRITE_GETPRE(data);
DPRINTK("set adc channel=%d, prescale=0x%x\n", adcdev.channel, adcdev.prescale);
return count;
}

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;
START_ADC_AIN(adcdev.channel, adcdev.prescale);
interruptible_sleep_on(&adcdev.wait);
printk("in read channel=%d\n",adcdev.channel);
ret = ADCDAT0;
printk("ADCDAT0=%x\n",ADCDAT0);
while((ADCCON & 0x80)!=1)
udelay(100);
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)
{
init_MUTEX(&adcdev.lock);
init_waitqueue_head(&(adcdev.wait));

adcdev.channel=0;
adcdev.prescale=0xff;

MOD_INC_USE_COUNT;
printk("adc opened!\n");
return 0;
}

static int s3c2410_adc_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
printk( "adc closed\n");
return 0;
}


static struct file_operations s3c2410_fops = {
owner:THIS_MODULE,
open:s3c2410_adc_open,
read:s3c2410_adc_read,
write:s3c2410_adc_write,
release:s3c2410_adc_release,
};

#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_adc_dir, devfs_adcraw;
#endif

int __init s3c2410_adc_init(void)
{
int ret;

/* normal ADC */
ADCTSC = 0;
ret = request_irq(IRQ_ADC_DONE, adcdone_int_handler, SA_INTERRUPT, DEVICE_NAME, NULL);
if (ret) {
return ret;
}

ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't get major number\n");
return ret;
}
adcMajor=ret;

#ifdef CONFIG_DEVFS_FS
devfs_adc_dir = devfs_mk_dir(NULL, "adc", NULL);
devfs_adcraw = devfs_register(devfs_adc_dir, "0raw", DEVFS_FL_DEFAULT,
adcMajor, ADCRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR, &s3c2410_fops, NULL);
#endif
printk (DEVICE_NAME"\tinitialized\n");
printk ("initialized\n");

printk("inilized ADCDAT0=%x\n",ADCDAT0);
printk("inilized ADCCON=%x\n",ADCCON);
return 0;
}

module_init(s3c2410_adc_init);

#ifdef MODULE
void __exit s3c2410_adc_exit(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_adcraw);
devfs_unregister(devfs_adc_dir);
#endif
unregister_chrdev(adcMajor, DEVICE_NAME);

free_irq(IRQ_ADC_DONE, NULL);
}

module_exit(s3c2410_adc_exit);
MODULE_LICENSE("GPL");
#endif

应用程序:
#include stdio.h>
#include unistd.h>
#include sys/types.h>
#include sys/ipc.h>
#include sys/ioctl.h>
#include fcntl.h>

#define ADC_DEV"/dev/adc/0raw"
#define ADC_WRITE(ch, prescale)((ch)<<16|(prescale))
#define ADC_WRITE_GETCH(data)(((data)>>16)&0x7)   //得到通道号
#define ADC_WRITE_GETPRE(data)((data)&0xff)      //得到转换的比例因子

static int get(int channel)
{
int PRESCALE=0XFF;
int data=ADC_WRITE(channel, PRESCALE);
write(adc_fd, &data, sizeof(data));
read(adc_fd, &data, sizeof(data));
return data;
}

main()
{
int i;
int fd;
float d;
void * retval;
   
if((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)get(i)*3.3)/1024.0;
printf("a[%d]=%8.4f\n",i,d);
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值