QT+2440-AD-mmap

QT+2440-AD-mmap  

2009-08-18 22:30:42|  分类: 嵌入式学习 |  标签: |举报 |字号 订阅

         这几天一直在做2440的AD采样,实际上这个很早以前就做了一部分了,不多之前采集的数据比较少,都在驱动里解决了,但是现在要采集大量的数据,由于在驱动程序中无法用数组保存大量数据(好像我做的时候,数组最大不能大于1000,不知道是不是我做错了,要是我做错了,希望可以有人提醒我),因此希望边在驱动里一边采集数据一边传回到应用程序中去,而考虑到要保证采样速率,因此不能使用copy_to_user(),最后决定使用mmap().

        说起使用mmap,还是以前做AD采样的时候一个网友告诉我的,并且很无私的把他的程序给了我,在这里感谢网名“任意球”的朋友,我的程序基本上来自他的代码。

       说起2440的AD采样,手册上写的最高是500K,但是我最高只做到160K,并且这个时候还非常的不稳定,大概在100K左右的时候AD采样才比较稳定,难道又是因为不是裸机的原因?

       mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。munmap执行相反的操作,删除特定地址区域的对象映射。

基于文件的映射,在mmap和munmap执行过程的任何时刻,被映射文件的st_atime可能被更新。如果st_atime字段在前述的情况下没有得到更新,首次对映射区的第一个页索引时会更新该字段的值。用PROT_WRITE 和 MAP_SHARED标志建立起来的文件映射,其st_ctime 和 st_mtime

在对映射区写入之后,但在msync()通过MS_SYNC 和 MS_ASYNC两个标志调用之前会被更新。

用法:

#include <sys/mman.h>

void *mmap(void *start, size_t length, int prot, int flags,int fd, off_t offset);

int munmap(void *start, size_t length);

各参数的含义可以参考http://baike.baidu.com/view/1499209.htm

因为我是要在AD中使用mmap,所有首先要写AD驱动,这里的AD驱动和不用mmap的写法是一样的,但是要在驱动里定义下面的mmap函数(和一般的open,read是一样的):

static int s3c2440adc_mmap(struct file *filp, struct vm_area_struct *vma)
      {
                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
                 vma->vm_pgoff = ADC_CTL_BASE >> PAGE_SHIFT;
                 if (remap_pfn_range(vma, vma->vm_start,vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot))
                 return -EAGAIN;
                 printk("s3c2440 VMA open, virt %lx, phy %lx\n", vma->vm_start, vma->vm_pgoff<<PAGE_SHIFT); 
                  return 0;
}

接下来就是在自己的QT程序里加上mmap代码:


        #define S3C2410_ADCCON   0x00
       #define S3C2410_ADCDAT0    0x0C

#define S3C2410_ADCCON_PRSCEN  (1<<14)
      #define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6)
       #define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3)
      #define S3C2410_ADCCON_ENABLE_START (1<<0)

#define START_ADC(ch, prescale) S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(prescale) \
                                | S3C2410_ADCCON_SELMUX(ch) | S3C2410_ADCCON_ENABLE_START

unsigned long int i;
       void *map_base;
       volatile  unsigned int *ADCCON;
       volatile  unsigned int *ADCDATA;
       volatile  unsigned int result;
       unsigned int data[LOOP];

AD_fd = open("/dev/adc",O_RDWR);

map_base = mmap(0,0x20,PROT_READ|PROT_WRITE,MAP_SHARED,AD_fd,0);//映射AD设备文件
       ADCCON = ((volatile  unsigned int *)map_base+S3C2410_ADCCON); //映射AD控制寄存器
      ADCDATA = ((volatile  unsigned int *)map_base + 3);//映射数据寄存器

注意这里的“+3”,若是不在QT编译,而是直接使用C语言写的话,这里应该是“+S3C2410_ADCDAT0”,也就是“+12”。至于原因就不说了

FILE *stream;//数据存贮文件
      stream = fopen("data_file", "a+");
 

 for (i=0;i<LOOP;i++)
      {
        *ADCCON = 0x4501;

这里本应该是*ADCCON = START_ADC(0,20);写成,并且在C语言这样写编译运行都没有问题,但是在QT里,这部操作后寄存器里的值不对,是什么原因暂时没有去追寻,我干脆把该写的值直接赋给寄存器好了QT+2440-AD-mmap - ★段昌平★ - ★段昌平★

   do
        {
             result = (*ADCCON);

  } 
        while(result & 0x01);


        do//判断AD转换是否完成
       {
            result = *ADCCON; 
       }
         while(!(result & 0x8000));

  data[i] = (*ADCDATA) & 0x3ff;//获取数据
         fprintf(stream,"%d\n",data[i]);//把数据写入文件。
 }
 
 好了,添加完这些语句,就可以在不影响采样速率的情况下进行AD采样中的实时传输了。
    

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值