adc驱动问题,高手救命
时间:2007-08-08
来源:互联网
我使用优龙的YL2440的开发板,
我自己写了一个驱动程序:
文件名:adc.c
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm-arm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-adc.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h>
#include <asm/arch/irqs.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>
#include "adc.h"
//预分频倍数
#define PRESCALER 19
#define ADCCON (0x58000000)
#define ADCTSC (0x58000004)
#define ADCDLY (0x58000008)
#define ADCDAT0 (0x580000c)
#define ADCDAT1 (0x58000010)
#define ADCUPDN (0x58000014)
MODULE_LICENSE("Dual BSD/GPL");
//static int channel = -1;
static unsigned long *adccon, *adctsc, *adcdly, *adcdat0, *adcdat1, *adcupdn;
static unsigned int adc_usage[MAX_ADC];
static ssize_t adc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
static int adc_open(struct inode *inode, struct file *filp);
static int adc_release(struct inode *inode, struct file *filp);
int adc_init(void);
void adc_cleanup(void);
module_init(adc_init);
module_exit(adc_cleanup);
static struct file_operations adc_fops = /* driver info */
{
.owner = THIS_MODULE,
.open = adc_open,
.release = adc_release,
.read = adc_read,
};
static ssize_t adc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
unsigned long flags;
u32 temp0, temp;
unsigned short temp2;
int i = 0, j = 0;
if (count > 8)
{
return -EFBIG;
}
if (!access_ok(VERIFY_WRITE, (void *)buf, count))
{
return -EFAULT;
}
//temp1 = (int)filp->private_data;
local_irq_save(flags);
//outl(AdcrSave | (1u <_u32 ?temp) | (1u << 24), ADCCON);
//使能设置预分频,采用AIN0
writel((0x1<<14)|(PRESCALER<<6)|(0<<3), adccon);
//等待通道切换
for(j = 0; j < 20000; j++)
i++;
temp0 = readl(adccon);
//开始AD转换
writel(temp0|0x01, adccon);
//等待AD转换完成
while((readl(adccon) & 0x01) != 0);
//等待AD数据写入ADCDAT0
while((readl(adccon) & (0x1 _u60 ? 15)) == 0);
printk("adccon = %d, adctsc = %d, adcdly = %d, adcdat0 = %d, adcdat1= %d, adcupdn = %d\n", readl(adccon), readl(adctsc), readl(adcdly), readl(adcdat0), readl(adcdat1), readl(adcupdn));
temp = readl(adcdat0);
temp2 = temp&0x3fff;
copy_to_user(buf, &temp2, 2);
printk("temp2 = %d\n", temp2);
local_irq_restore(flags);
return 1;
}
static int adc_open(struct inode *inode, struct file *filp)
{
int num;
num = MINOR(inode->i_rdev);
if (num >= MAX_ADC)
{
return -ENODEV;
}
adc_usage[num]++;
//MOD_INC_USE_COUNT;
try_module_get(THIS_MODULE);
return 0; /* success */
}
static int adc_release(struct inode *inode, struct file *filp)
{
int num;
num = MINOR(inode->i_rdev);
if (num >= MAX_ADC)
{
return -ENODEV;
}
module_put(THIS_MODULE);
adc_usage[num]--;
return(0);
}
int adc_init(void)
{
int result;
result = register_chrdev(ADC_MAJOR_NR, DEVICE_NAME, &adc_fops);
if (result < 0)
{
printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n", ADC_MAJOR_NR );
return(result);
}
/*****************
if (ADC_MAJOR_NR == 0)
{
ADC_MAJOR_NR = result;
}
******************/
adccon = ioremap(ADCCON,0x00000004);
adctsc = ioremap(ADCTSC,0x00000004);
adcdly = ioremap(ADCDLY,0x00000004);
adcdat0 = ioremap(ADCDAT0,0x00000004);
adcdat1 = ioremap(ADCDAT1,0x00000004);
adcupdn = ioremap(ADCUPDN,0x00000004);
writel(0x58, adctsc);
writel(0, adcupdn);
printk("adcdat0 = %d\n", readl(adcdat0));
printk(KERN_INFO DEVICE_NAME ": init OK\n");
return(0);
}
void adc_cleanup(void)
{
iounmap(adccon);
iounmap(adctsc);
iounmap(adcdly);
iounmap(adcdat0);
iounmap(adcdat1);
iounmap(adcupdn);
unregister_chrdev(ADC_MAJOR_NR, DEVICE_NAME);
}
Makefile文件内容:
obj-m += adc.o
执行命令:
make -C /usr/src/linux-2.6.12/ SUBDIRS=/root/driver/adc/ modules
进行编译。(说明:“/usr/src/linux-2.6.12/”为内核源文件的目录,“/root/driver/adc/“ 为存放驱动程序的目录)
测试程序:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
int fp;
unsigned short data = 0;
fp = open("/dev/adc", O_RDONLY);
if(fp == -1)
{
perror("open");
return errno;
}
while(1)
{
read(fp, &data, 2);
printf("adc = %d\n", data);
sleep(1);
}
return -1;
}
测试程序的Makefile:
EXEC =adctest
OBJS =adctest.o
SRC =adc_test.cpp
CC =arm-linux-gcc
BASEPATH =/usr/src/
LIBPATH =$(BASEPATH)/lib
INCLUDEPATH =$(BASEPATH)/linux-2.6.12/include
LDFLAGS =-Os -g -Dlinux -D__linux__ -Dunix -D__uClinux__ -DEMBED
LDLIBS_OBJS =-c
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS)
%.o:%.c
$(CC) $(LDFLAGS) -c $< -o $@
clean:
-rm -f $(EXEC) *.o
但是运行的结果树出为:
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
…
我觉得所有的设置都是对的,为什么就是AD转换的结果始终为0。
高手救命!!!!!!!!!!
我自己写了一个驱动程序:
文件名:adc.c
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm-arm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-adc.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h>
#include <asm/arch/irqs.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>
#include "adc.h"
//预分频倍数
#define PRESCALER 19
#define ADCCON (0x58000000)
#define ADCTSC (0x58000004)
#define ADCDLY (0x58000008)
#define ADCDAT0 (0x580000c)
#define ADCDAT1 (0x58000010)
#define ADCUPDN (0x58000014)
MODULE_LICENSE("Dual BSD/GPL");
//static int channel = -1;
static unsigned long *adccon, *adctsc, *adcdly, *adcdat0, *adcdat1, *adcupdn;
static unsigned int adc_usage[MAX_ADC];
static ssize_t adc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
static int adc_open(struct inode *inode, struct file *filp);
static int adc_release(struct inode *inode, struct file *filp);
int adc_init(void);
void adc_cleanup(void);
module_init(adc_init);
module_exit(adc_cleanup);
static struct file_operations adc_fops = /* driver info */
{
.owner = THIS_MODULE,
.open = adc_open,
.release = adc_release,
.read = adc_read,
};
static ssize_t adc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
unsigned long flags;
u32 temp0, temp;
unsigned short temp2;
int i = 0, j = 0;
if (count > 8)
{
return -EFBIG;
}
if (!access_ok(VERIFY_WRITE, (void *)buf, count))
{
return -EFAULT;
}
//temp1 = (int)filp->private_data;
local_irq_save(flags);
//outl(AdcrSave | (1u <_u32 ?temp) | (1u << 24), ADCCON);
//使能设置预分频,采用AIN0
writel((0x1<<14)|(PRESCALER<<6)|(0<<3), adccon);
//等待通道切换
for(j = 0; j < 20000; j++)
i++;
temp0 = readl(adccon);
//开始AD转换
writel(temp0|0x01, adccon);
//等待AD转换完成
while((readl(adccon) & 0x01) != 0);
//等待AD数据写入ADCDAT0
while((readl(adccon) & (0x1 _u60 ? 15)) == 0);
printk("adccon = %d, adctsc = %d, adcdly = %d, adcdat0 = %d, adcdat1= %d, adcupdn = %d\n", readl(adccon), readl(adctsc), readl(adcdly), readl(adcdat0), readl(adcdat1), readl(adcupdn));
temp = readl(adcdat0);
temp2 = temp&0x3fff;
copy_to_user(buf, &temp2, 2);
printk("temp2 = %d\n", temp2);
local_irq_restore(flags);
return 1;
}
static int adc_open(struct inode *inode, struct file *filp)
{
int num;
num = MINOR(inode->i_rdev);
if (num >= MAX_ADC)
{
return -ENODEV;
}
adc_usage[num]++;
//MOD_INC_USE_COUNT;
try_module_get(THIS_MODULE);
return 0; /* success */
}
static int adc_release(struct inode *inode, struct file *filp)
{
int num;
num = MINOR(inode->i_rdev);
if (num >= MAX_ADC)
{
return -ENODEV;
}
module_put(THIS_MODULE);
adc_usage[num]--;
return(0);
}
int adc_init(void)
{
int result;
result = register_chrdev(ADC_MAJOR_NR, DEVICE_NAME, &adc_fops);
if (result < 0)
{
printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n", ADC_MAJOR_NR );
return(result);
}
/*****************
if (ADC_MAJOR_NR == 0)
{
ADC_MAJOR_NR = result;
}
******************/
adccon = ioremap(ADCCON,0x00000004);
adctsc = ioremap(ADCTSC,0x00000004);
adcdly = ioremap(ADCDLY,0x00000004);
adcdat0 = ioremap(ADCDAT0,0x00000004);
adcdat1 = ioremap(ADCDAT1,0x00000004);
adcupdn = ioremap(ADCUPDN,0x00000004);
writel(0x58, adctsc);
writel(0, adcupdn);
printk("adcdat0 = %d\n", readl(adcdat0));
printk(KERN_INFO DEVICE_NAME ": init OK\n");
return(0);
}
void adc_cleanup(void)
{
iounmap(adccon);
iounmap(adctsc);
iounmap(adcdly);
iounmap(adcdat0);
iounmap(adcdat1);
iounmap(adcupdn);
unregister_chrdev(ADC_MAJOR_NR, DEVICE_NAME);
}
Makefile文件内容:
obj-m += adc.o
执行命令:
make -C /usr/src/linux-2.6.12/ SUBDIRS=/root/driver/adc/ modules
进行编译。(说明:“/usr/src/linux-2.6.12/”为内核源文件的目录,“/root/driver/adc/“ 为存放驱动程序的目录)
测试程序:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
int fp;
unsigned short data = 0;
fp = open("/dev/adc", O_RDONLY);
if(fp == -1)
{
perror("open");
return errno;
}
while(1)
{
read(fp, &data, 2);
printf("adc = %d\n", data);
sleep(1);
}
return -1;
}
测试程序的Makefile:
EXEC =adctest
OBJS =adctest.o
SRC =adc_test.cpp
CC =arm-linux-gcc
BASEPATH =/usr/src/
LIBPATH =$(BASEPATH)/lib
INCLUDEPATH =$(BASEPATH)/linux-2.6.12/include
LDFLAGS =-Os -g -Dlinux -D__linux__ -Dunix -D__uClinux__ -DEMBED
LDLIBS_OBJS =-c
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS)
%.o:%.c
$(CC) $(LDFLAGS) -c $< -o $@
clean:
-rm -f $(EXEC) *.o
但是运行的结果树出为:
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
adccon = 50368, adctsc = 88, adcdly = 255, adcdat0 = 0, adcdat1= 32768, adcupdn
= 0
temp2 = 0
adc = 0
…
我觉得所有的设置都是对的,为什么就是AD转换的结果始终为0。
高手救命!!!!!!!!!!
作者: wujidong 发布时间: 2007-08-08
如果AD的输入量就是0呢?
作者: 风雪狂客 发布时间: 2007-08-08
输入肯定不为零,在ADS下可以得到正确的AD转换的值!
作者: wujidong 发布时间: 2007-08-13
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28