Chinaunix首页 | 论坛 | 博客
  • 博客访问: 402742
  • 博文数量: 62
  • 博客积分: 1483
  • 博客等级: 上尉
  • 技术积分: 779
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-24 12:25
文章分类

全部博文(62)

文章存档

2012年(2)

2011年(6)

2010年(6)

2009年(48)

我的朋友

分类: LINUX

2009-10-20 15:10:44

adc驱动写好了,但是不知道我的应用程序每秒能读几次adc转换的数据。
我把adc的时钟调到了最高,2.5Mhz,2.5Mhz/5 也就是500ksps,每秒可以采样500k次,但这描述的是adc的工作速度,
并不是系统实际的采样速度,系统实际的采样速度会受中断的影响,进程调度到别的进程的时候,也要影响。所以有必要测量一下
应用程序的实际采样速率。

测速的结果显示,每秒次,我的应用程序可以获得2400次采样/每秒 左右。
2486                                                                           
2485                                                                           
2486                                                                           
2485                                                                           
2485                                                                           
2485                                                                           
2486                                                                           
2485                                                                           
2486                                                                           
2484                                                                           
2486                                                                           
2485                                                                           
2486                                                                           
2485                                                                           
2485                                                                           
2485                                                                           
2486                                                                           
2485                                                                           
2486                                                                           
2484                                                                           
2486                                                                           
2485                                                                           
2486

这样一来,如果车速200km/s,测速管子的宽度是1cm,那么,车子在管子上的时间为1cm/200km/s = 0.00018s
而我的adc每次采样时间 1/2480 = 0.000403s > 0.00018s,所以这样的采样速度是不行的。代是考虑管子不会立刻回到
原状,所以是可以考虑的。

测速程序
#include
#include
#include
#include
#include

#define CMD_ADC_START_AND_GET     1
#define CMD_SEL_MUX   2

int counter = 0;

static void sig_alarm(void)
{
    printf("%d\n",counter);
    counter = 0;
    alarm(1);
}

int main(int argc, char **argv)
{
    int val;
    int fd;
    if (argc != 1) {
        fprintf(stderr, "Usage: ./a.out\n");
        exit(1);
    }
    fd = open("/dev/myadc", 0);
    if (fd < 0) {
        perror("open device adc");
        exit(1);
    }

    if(signal(SIGALRM,sig_alarm) == SIG_ERR){
        perror("signal(SIGALRM,sig_alarm)\n");
    }

    alarm(1);

    while(1){
        ioctl(fd, CMD_SEL_MUX, 0); //选择通道0,默认的也是0
        val = ioctl(fd,CMD_ADC_START_AND_GET);
        counter++;
    }

    close(fd);
    return 0;
}

使用gettimeofday测量时间,如下:
time used 473us                                                                
time used 435us                                                                
time used 413us                                                                
time used 415us                                                                
time used 445us                                                                
time used 424us                                                                
time used 415us                                                                
time used 415us                                                                
time used 413us                                                                
time used 414us                                                                
time used 480us                                                                
time used 435us                                                                
time used 414us                                                                
time used 445us                                                                
time used 424us                                                                
time used 413us                                                                
time used 415us                                                                
time used 414us                                                                
time used 414us                                                                
time used 414us                                                                
time used 413us                                                                
753

主要代码:
while(1){
        gettimeofday(&start, NULL);
        ioctl(fd, CMD_SEL_MUX, 0); //选择通道0,默认的也是0
        val = ioctl(fd,CMD_ADC_START_AND_GET);
        counter++;
        gettimeofday( &end, NULL );
        timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
        printf("time used %dus\n",timeuse);
    }

结构timeval的定义为:
strut timeval {
    long tv_sec; /* 秒数 */
    long tv_usec; /* 微秒数 */
};

gettimeofday测量到的时间差跟alarm()函数计算的结果近似,可以认为正确。
time used xxxus 近似于 0.000403s = 403us 。

通过上述的系统速度的测试,写了个ad采集的应用

#include
#include
#include
#include
#include
#include
#include
#include

#define CMD_ADC_START_AND_GET     1
#define CMD_SEL_MUX   2

#define START 0
#define CLEAN 0
#define DIRTY 1

int chanel = 0; //ad通道选择,默认通道是0
int status = CLEAN;

int get_ad_data(int fd,int chanel);
void save_time(int chanel);
int save_record(void);
void switch_chanel(void);
void write_time(void);

struct record { //文件中,每个ad记录结构
    struct timeval start;
    struct timeval end;
} record;

struct time_record {
    int tag_s;
    time_t t;
    int tag_e;
}time_record = {0x1999,0,0x1999};

#define HOUR_TIMEOUT 0
#define MUX2_TIMEOUT 1
#define HOUR 3600 //调整这个时间为3600?????????
int saved_alarm = 0;
int alarm_flag = HOUR_TIMEOUT; //这个标志,表示定时器到时是发生在 1:对ad通道2的检测超时 2:一小时到时(默认)

static void sig_alarm(void)
{
    switch(alarm_flag){
        case MUX2_TIMEOUT:
            status = CLEAN;
            chanel = 0;
            alarm_flag = HOUR_TIMEOUT;
            alarm(saved_alarm);
            break;
        default:
            write_time();
            alarm(HOUR);            
    }
}

int main(int argc, char **argv)
{
    int val,adc_data;
    int fd;
    struct timeval start,end;
    unsigned long timeuse;

    if (argc != 1) {
        fprintf(stderr, "Usage: .adc\n");
        exit(1);
    }

    fd = open("/dev/myadc", 0);
    if (fd < 0) {
        perror("open device adc");
        exit(1);
    }

    if(signal(SIGALRM,sig_alarm) == SIG_ERR){
        perror("signal(SIGALRM,sig_alarm)\n");
    }

    alarm(HOUR); //每个小时要在数据文件中增加一条时间记录

#define MIN_WITH    0x10    
#define MIN_PRESS     0x3ff

while(1){
 
        adc_data = get_ad_data(fd,chanel);
             
        if(adc_data >= MIN_PRESS){
            save_time(chanel);

            if(status){ //表示这个记录已经脏了,可以保存到nand
                val = save_record();
                alarm(saved_alarm); //已经记录了就不用等着通道2超时了。
                if(val != sizeof(record)){;} //暂时没有出错处理
            }
            switch_chanel();
        }

        usleep(500000);
     
    }/*while end*/

    return 0;
}


int get_ad_data(int fd,int ch)
{
    int val;
    ioctl(fd, CMD_SEL_MUX, ch); //选择通道
    val = ioctl(fd,CMD_ADC_START_AND_GET);
    return val;

}


/*保存时间到flags指定的记录的start或者end里*/
void save_time(int chanel)
{
    if(chanel == 0)
        gettimeofday(&record.start, NULL);
    else
        gettimeofday(&record.end,NULL);
}

/*保存当前的记录到数据库文件*/
int save_record(void)
{
    int fd,ret;
    fd = open("/data", O_RDWR | O_APPEND | O_CREAT,S_IRUSR | S_IWUSR); //追加到这个文件的结尾处
    if (fd < 0) {
        perror("fail open /data\n");
        exit(1);
    }
    ret = write(fd,&record,sizeof(record));
    if(ret != sizeof(record)){
        perror("write failed\n");
    }
    close(fd);
    return ret;
}


void switch_chanel(void)
{
    chanel = (chanel == 0?1:0);

    if(chanel == 1){ //是通道1,表示下次要检测通道1了
        status = DIRTY;
        alarm_flag = MUX2_TIMEOUT;
        saved_alarm = alarm(1);
    }else{
        status = CLEAN;
    }       
}

void write_time(void)
{
    int fd,ret;
    time_record.t = time((time_t *)NULL);

    fd = open("/data", O_RDWR | O_APPEND | O_CREAT,S_IRUSR | S_IWUSR); //追加到这个文件的结尾处
    if (fd < 0) {
        perror("fail open /data\n");
        exit(1);
    }
    ret = write(fd,&time_record,sizeof(time_record));
    if(ret != sizeof(time_record)){
        perror("write failed\n");
    }
    close(fd);
}

阅读(2626) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~