linux adc命令测试,实验 A/D驱动程序编写与测试

实验 A/D驱动程序编写与测试

【实验内容】

编写一个字符设备驱动程序,驱动FS_S5PC100开发板上的可调电阻,采集AD转换过来的电压值

可调电阻位于开发板第二个串口(COM2)的正下方

【实验目的】

了解AD的工作原理,掌握驱动里操作AD控制器的方法,巩固字符设备驱动程序编写方法

【实验平台】

主机:Ubuntu 10.10

目标板:FS_S5PC100

目标内核版本:2.6.29

交叉编译器版本:arm-unknown-linux-gnueabi-gcc-4.2.2

【实验步骤】

在主机ubuntu环境下:

1、将文件夹s5pc100_adc复制到linux环境中,如:/home/linux/test

$ cp s5pc100_adc /home/linux/test –a

2、$ cd /home/linux/test/s5pc100_adc

3、$ make //编译设备驱动,生成adc.ko模块

4、$ arm-linux-gcc adc_test.c -o adc_test //编译应用程序

5、$ sudo cp adc.ko adc_test /source/rootfs

在开发板的串口终端控制台下:

6、通过insmod命令将模块加入内核

# insmod adc.ko //由于驱动采用的是动态获取主设备号的方式,所以根据打印信息建立设备结点

major number of adc is 252

7、 创建设备结点

# mknod /dev/adc c 252 0

9、运行应用程序

# ./adc_test

调整可调电阻上的旋钮,发现输出值也在发生变化

val = 630

val = 623

val = 60b

val = 5fb

val = 913

val = 925

val = 916

val = 911

10、修改应用程序,将直接从驱动获得的数字量转换为实际的电压值(可调电阻可以承受的电压范围为: 0 —— 3.3V)

附:

1、 驱动程序代码:

#include

#include

#include

#include

#include

#include // copy_to_user, copy_from_user

#include

#include

#include

#include

MODULE_AUTHOR("farsight");

MODULE_LICENSE("Dual BSD/GPL");

#define ADC_BASE_ADDR 0xF3000000

#define MAP_SIZE 36

static int adc_major = 0;

static volatile void *adc_base;

#if 0

static irqreturn_t ad_interrupt(int irq, void *dummy)

{

//input_report_key(ad_dev, BTN_0, inb(BUTTON_PORT) & 1);

//input_sync(ad_dev);

return IRQ_HANDLED;

}

#endif

static int adc_open(struct inode *inode, struct file *filp)

{

//map physical address to virtual address

adc_base = ioremap(ADC_BASE_ADDR, MAP_SIZE);

//ADC output resolution seletion : 12-bit A/D conversion

writel(readl(adc_base+S3C_ADCCON) | S3C_ADCCON_RESSEL_12BIT, adc_base+S3C_ADCCON);

//enable A/D converter prescale and set prescaler as 0xFF

writel(readl(adc_base+S3C_ADCCON) | S3C2410_ADCCON_PRSCEN, adc_base+S3C_ADCCON);

//set prescaler as 0xFF

writel((readl(adc_base+S3C_ADCCON) & ~S3C2410_ADCCON_PRSCVLMASK) | S3C2410_ADCCON_PRSCVL(0xff), adc_base+S3C_ADCCON);

//select normal operation mode

writel(readl(adc_base+S3C_ADCCON) & ~S3C2410_ADCCON_STDBM, adc_base+S3C_ADCCON);

//select channel as AIN0

writel(readl(adc_base+S3C_ADCMUX) & ~S3C_ADCMUX_MASK, adc_base+S3C_ADCMUX);

#if 0

if (request_irq(IRQ_ADC, ad_interrupt, 0, "adc", NULL)) {

printk(KERN_ERR "%s: Can't allocate irq %d\n", __FUNCTION__, IRQ_ADC);

return -EBUSY;

}

#endif

//enable A/D conversion

//writel(readl(adc_base+S3C_ADCCON) | S3C2410_ADCCON_ENABLE_START, adc_base+S3C_ADCCON);

writel(readl(adc_base+S3C_ADCCON) | S3C_ADCCON_READ_START, adc_base+S3C_ADCCON);

return 0;

}

static int adc_close( struct inode *inode, struct file *filp )

{

//free_irq(IRQ_ADC, ad_interrupt);

return 0;

}

static ssize_t adc_read( struct file *filp, char __user *buffer, size_t count, loff_t *offset )

{

int val;

//read A/D conversion data from ADCDAT0

val = readl(adc_base+S3C_ADCDAT0) & 0xfff;

printk(KERN_INFO "val = %x\n", val);

if( copy_to_user(buffer, &val, sizeof(val)) != 0 ) {

printk( KERN_ERR "copy to user failed\n" );

return -1;

}

return sizeof(val);

}

static struct file_operations adc_fops = {

.owner = THIS_MODULE,

.open = adc_open,

.release = adc_close,

.read = adc_read,

};

static int __init adc_init( void )

{

int res;

res = register_chrdev( adc_major, "adc", &adc_fops );

if ( res < 0 ) {

printk( KERN_ERR "%s failed.\n", __FUNCTION__ );

return res;

}

else {

if ( adc_major )

printk ( KERN_INFO "major number of adc is %d\n", adc_major );

else {

adc_major = res;

printk ( KERN_INFO "major number of adc is %d\n", adc_major );

}

}

return 0;

}

static void __exit adc_cleanup( void )

{

unregister_chrdev( adc_major, "adc" );

}

module_init(adc_init);

module_exit(adc_cleanup);

2、 测试程序代码

#include

#include

int

main( int argc, char *argv[] )

{

int fd = open( "/dev/adc", O_RDWR );

if( fd < 0 ) {

perror( "open /dev/adc error" );

return -1;

}

int nread = 0;

int adc_val = 0;

while( 1 ) {

nread = read( fd, (void *)&adc_val, sizeof(adc_val) );

if( nread < 0 ) {

perror( "read adc" );

return -1;

}

sleep( 1 );

}

close( fd );

return 0;

}

3、 AD转换接口原理图:

22695194_1.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值