主题 : 如何提高AD采样频率? 复制链接 | 浏览器收藏 | 打印
级别: 侠客
UID: 2177
精华: 0
发帖: 70
金钱: 620 两
威望: 463 点
综合积分: 140 分
注册时间: 2008-10-30
最后登录: 2015-01-12
楼主  发表于: 2009-06-02 16:31

 如何提高AD采样频率?

之前我发贴问过,s3c2440自带的AD采样频率到底能够达到多少?因为我自己编写的驱动,测试出来采样频率只有1K左右。后来在裸机上测试,在ADS开发环境下测试AD采样频率其实可以在100K以上的,后来看了一下资料,说是驱动里面的copy to user()函数需要在内核空间与用户空间之间来回拷贝,花费了大量时间,要提高采样频率,一个可行的方法是采用mmap。然后我再AD驱动里面增加mmap接口,代码如下:
static int s3c2440adc_mmap(struct file *filp, struct vm_area_struct *vma)
{
    if (remap_pfn_range(vma, vma->vm_start, ADC_CTL_BASE, vma->vm_end - vma->vm_start, vma->vm_page_prot))
        return -EAGAIN;
    printk("the physis address is %dl\n", vma->vm_pgoff);
    return 0;
}
其中ADC_CTL_BASE为0x58000000,为ADCCON的物理地址;
然后在用户程序里面调用mmap,代码如下:
if( (fd = open("/dev/s3c2440_adc", O_RDWR, 0666)) < 0 )
    {
        perror("open:");
        exit(1);
    }
map_base = mmap(NULL,0x14,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
for (i=0;i<LOOP;i++)
        {
            ADCCON = (volatile int*)(map_base + S3C2410_ADCCON);
            ADCDATA = (volatile int*)(map_base + S3C2410_ADCDAT0);
            *ADCCON = START_ADC(0,255);
            do
            {
                result = *ADCCON;    
            }
            while((unsigned int)result & 0x01);

            do
            {
                result = *ADCCON;    
            }
            while(!(((unsigned int)result) & 0x8000));
            
                                                                data = (*ADCDATA) & 0x3ff;
            printf("AIN=%dmv\n",data*3300/1024);

        }
程序在while(!(((unsigned int)result) & 0x8000));处死循环,无法继续,原因应该是地址映射有误,用户程序根本没有读写到AD寄存器;mmap函数的写法出现了问题,不知道是哪里出现了问题?

后来,我又改用映射/dev/mem文件,用户程序可以读取AD寄存器,代码如下:
if((fd=open("/dev/mem",O_RDWR|O_SYNC))<0)
    {
        perror("open:");
        exit(1);
    }

map_base = mmap(NULL,0x14,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x58000000);
        for (i=0;i<LOOP;i++)
        {
            ADCCON = (volatile int*)(map_base + S3C2410_ADCCON);
            ADCDATA = (volatile int*)(map_base + S3C2410_ADCDAT0);
            *ADCCON = START_ADC(0,255);
            do
            {
                result = *ADCCON;    
            }
            while((unsigned int)result & 0x01);

            do
            {
                result = *ADCCON;    
            }
            while(!(((unsigned int)result) & 0x8000));
            data = (*ADCDATA) & 0x3ff;
            printf("AIN=%dmv\n",data*3300/1024);
        }

此时,能够正确读到AD的寄存器了,并打印出AD值,但有两个问题,一是采样速度依然没有上去,速度还不足1K,把物理地址映射到用户空间,采样频率应该有所提高才对,为什么一直上不去呢?二是部分数据有问题,大概4到5个数据之后就会有一个错误数据,估计是触摸屏驱动的干扰;
明明芯片本身可以达到100K以上的采样频率,在ADS环境下可以实现,怎么样才能在linux环境下实现呢?
-
级别: 侠客
UID: 2177
精华: 0
发帖: 70
金钱: 620 两
威望: 463 点
综合积分: 140 分
注册时间: 2008-10-30
最后登录: 2015-01-12
1楼  发表于: 2009-07-15 20:30
问题解决了,原来还是触摸屏驱动的干扰,将触摸屏驱动去除,mmap速度提高了,数值也正确,采样速度可达到100K
-
级别: 新手上路
UID: 31873
精华: 0
发帖: 6
金钱: 30 两
威望: 6 点
综合积分: 12 分
注册时间: 2010-11-06
最后登录: 2017-09-13
2楼  发表于: 2010-11-16 13:51
不去触摸频不行吗
级别: 新手上路
UID: 29200
精华: 0
发帖: 7
金钱: 35 两
威望: 7 点
综合积分: 14 分
注册时间: 2010-09-24
最后登录: 2012-02-21
3楼  发表于: 2011-04-13 09:46
怎么知道采样速率?