我的采集程序哪里出问题了?帮帮忙看看 点击:2336 | 回复:54



习习

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-17 17:49:00
楼主
我用的K-811数据采集卡,但是加入8253控制采集频率后,就不能采集到数据,只是一个固定的数:(.大家帮我看看哪里出问题了?多谢了
#include "stdio"
#include "dos.h"
#include "conio.h"

main()
{
    int ch;
    int dl,dh,j,base;
    clrscr();
    base=0x300; /*基卡地址*/
    dl=inportb(base+1); /*空读低8位,清除转换标志及中断标志*/
    printf("input channle number:");
    scanf("%d",&ch);
    outportb(base,ch); /*送通道号*/
    outportb(base+0xf,0xb1); /*设定8253定时器控制字,选择计数器3,方式0*/
    outportb(base+0xe,0x0f/0x99); /*送计数初值 9999*/
    outportb(base+0xe,0x27/0x99);

    for(j=0;j<1000;j++) /*控制采样次数*/
       { 

        do{
           ; 
           }while(inportb(base)<=128); /*查询AD转换状态*/
        outportb(base+0xe,0x0f/0x99); /*再次启动8253计数*/
        outportb(base+0xe,0x27/0x99);
        dh=inportb(base+0); /*读数据*/
        dl=inportb(base+1);
        outportb(base+4,dl); /*数据送入D/A通道,进行DA转换*/
        outportb(base+5,dh);
        inportb(base+4); /*启动D/A转换*/
        
        }
}



习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 16:56:00
21楼
好像是 时钟脉冲的 高电平 占1/3

  --    --    --    --
--  ----  ----  ----  ----
大概是这样子的脉冲

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-26 16:59:00
22楼
猜測這不是問題.
 

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 17:02:00
23楼
关于晴川大虾的:是不是你的循环周期比较长,与采集频率不相符?您的意思是说是每次循环所需的时间跟采集周期不相符合?超过了采集周期?

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 17:05:00
24楼
我们目前只是用信号发生器 产生的 50Hz 的信号,应该不是信号没有变化阿,输入信号是持续不断的应该是

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-26 17:11:00
25楼
要不, 把新的 code 丟上來看看!

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 17:11:00
26楼
我用了下面的程序查询方式,在ADC转换结束时才读取数据
do{
   ; 
  }while(inportb(base)<=128); /*查询AD转换状态*/

 dh=inportb(base+0); /*转换结束时读取高四位数据*/
 dl=inportb(base+1); /*读取低8位数据*/

是不是说循环的周期远远小于ADC的启动信号周期?以至于同一个数显示了20次?才到下一个采样点?

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 17:14:00
27楼
我这个机子不能做实验:( 做实验机子在机房里,数据都是我印象中记录的 

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-26 17:17:00
28楼
do { ; } while( (inportb(base) & 0x80) == 0); // Wait ADC busy
do { ; } while( (inportb(base) & 0x80) == 0x80); // Wait ADC ready

 dh=inportb(base+0); /*转换结束时读取高四位数据*/
 dl=inportb(base+1); /*读取低8位数据*/

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 17:18:00
29楼
等ADC再次進入 busy 的狀態, 並等它再次回到 ready 的狀態時, 才能取一筆數據. 对于从busy 到ready 这一点怎么查询呢? 我只能检测到ADC的8位状态位的最高位是不是1,从而判断转换是否结束。

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 17:23:00
30楼
阿这样子阿 我怎么没有想到呢 哈哈多谢我在去实验室看看了 多谢阿 

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 19:46:00
31楼
应该是 
 先do { ; } while( (inportb(base) & 0x80) == 0x80); //*Wait while ADC ready*/
 后do { ; } while( (inportb(base) & 0x80) == 0); /*Wait while ADC busy*/
吧?

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 21:51:00
32楼
我去实验室试过了,好像还是不行! 甚至有时候采集的数就是一个数
4.99000 ,已经超过了我们的输入信号幅值(-2~+2v).
不过如果在循环的最下面加入适当的延时的话,使循环的周期刚好等于采集的间隔时间,采出来的数据还挺逼真的!

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-26 22:00:00
33楼
这是我现在的程序您帮我看看吧
main()
{
  int ch;
  int dl,dh,j,i,base;
  clrscr();
  base=0x300; /*基卡地址*/
  dl=inportb(base+1); /*空读低8位,清除转换标志及中断标志*/
  printf("input channle number:");
  scanf("%d",&ch);
  outportb(base,ch); /*送通道号*/
  outportb(base+0xf,0xb7); /*启动8253定时器,设定初始控制字,选择计数器2,方式3*/
  outportb(base+0xe,0x00); /*送计数初值 2M/(50*10)=4000*/
  outportb(base+0xe,0x40);
    
  for(j=0;j<10000;j++) /*控制采样次数*/
   { 
    do{ ;} while( (inportb(base) & 0x80) == 0x80); /*Wait while ADC ready*/
    do{ ; } while((inportb(base) & 0x80) ==0) ; /*wait while ADC busy*/

    dh=inportb(base+0); /*转换结束时读取高四位数据*/
    dl=inportb(base+1); /*读取低8位数据*/

    outportb(base+4,dl); /*数据送入D/A通道,进行DA转换*/
    outportb(base+5,dh);
    inportb(base+4); /*启动D/A转换*/
    }
}

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-27 09:42:00
34楼
8253 的初值有誤, 4000 = 0x0FA0, 不是 0x4000

要先等其 Busy (開始轉換), 再等其 Ready (轉換結束)才是!

而且 Busy 到 Ready 的時間通常很短, 順序弄錯時, 可能會遇上 ADC 正在 write data, 您的程序也正在 read data. 此時 read data 可能會有問題(數據有誤). 所以, 當 ADC 在 busy 時, 這不會是您讀取 data 的好時機 (Read/Write 的 timing 可能沖突).

其它程序的 logical 看來 OK.

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-27 15:12:00
35楼
哈哈,成功了 ~!!!非常感谢GaryLin前辈这么久的对我的帮助!! 感动ing!!
 不过我用的是8253方式2,方式2(分频器) 是计数结束输出一个负的clock周期, 用方式3(方波发生器)采的有效数值倒是不重复了,但是中间有四五十个4.997559 然后是下一个有效数值,在四五十个4.997559!
同时我把adc的状态从检查busy~ready---开始读数据
                   读完数据----检查ready~busy
                   然后循环一下采集
for(j=0;j<1000;j++)

  do{;} while((inportb(base) & 0x80) ==0);
  dh=inportb(base+0); 
  dl=inportb(base+1);  
  do{;} while((inportb(base)&0x80)==0x80); 
 }  
这样子就可以采集了 :)
  至于用方式3为什么不可以正确采集还得向GaryLin前辈请教阿 。

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-28 10:58:00
36楼
看了下 Mode 2 與 Mode 3 之差異, 應該只在於 pulse 的 high/low width 不同而已. 這對 trigger 之效用應該一樣的, 不致於 Mode 2 可用而 Mode 3 不能用. 這有點怪. 

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-28 12:05:00
37楼
恩是的, Mode2输出的时一个clock周期的负脉冲 ,mode3是输出计数初值的一半个clock 宽度的负脉冲。
 我用mode3时 采集到的数据有很多4.997559,
ADC的信号输入范围是-5v~+5v,是不是采的 这个+5v呀?

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-28 13:20:00
38楼
8253 的 bit-0, 我習慣把它設為 0 = binary mode. 不知是否有差!

另外, 之前的程序我有點弄混了! 這樣比較明確...

for(j=0;j<1000;j++)

   while(1) { 
      if ( (inportb(base) & 0x80) == 0 ) break; // Until ADC busy
   }
   while(1) {
      if ( (inportb(base) & 0x80) == 0x80 ) break; // Until ADC ready
   }

 dh=inportb(base+0); /*转换结束时读取高四位数据*/
 dl=inportb(base+1); /*读取低8位数据*/
}

GaryLin

  • 精华:0帖
  • 求助:0帖
  • 帖子:4帖 | 1186回
  • 年度积分:0
  • 历史总积分:1263
  • 注册:2003年4月15日
发表于:2006-04-28 13:27:00
39楼
請查一下該板卡的手冊, 其讀取 Base +0, 與 Base +1 後, 其內的 data 會不會被清空?

若會的話, 其中 ADC status 的檢查就會影響到後面的數據. 此時您得在讀 status 時, 就把其 high byte 一併記錄下來. 

习习

  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 38回
  • 年度积分:0
  • 历史总积分:103
  • 注册:2005年10月13日
发表于:2006-04-28 16:20:00
40楼
采集卡是科日新的K-811多功能卡,里面提到转换结束后,读取低8位数据的另一附加作用是清除AD转换标志及中断标志,所以在每一个AD转换程序段开始时,应通过空读低8位数据初始化ad转换标志及中断申请标志。

热门招聘
相关主题

官方公众号

智造工程师