搜索
bottom↓
回复: 19

还是AVR 输入捕捉测脉宽的问题,误差太大??

[复制链接]

出0入0汤圆

发表于 2012-6-6 11:52:46 | 显示全部楼层 |阅读模式
昨天提得那个数据乱的问题已经解决了,是硬件上的问题,PB0管位有点虚焊,所以造成数据很乱,
也很感谢eblc1388的解答,不过elbc1388可能没看我的程序,我的程序就是和你所说的那样啊。
今天做了几组数据的测试,发现误差很大啊,这是正常吗???
晶振是8M,不分频,定时器也不分频

把我测的数据贴上来:

700us:        5760----5775      *   0.125           720us------722us

1490us:     12345--- 12400    *  0.125           1543us----1550us

2280us:     18945---19000     *  0.125           2368us---2375us

输入的信号源决对稳定,测出的数据怎么感觉比用定时器测得误差还大呢??

再把相关程序也贴出,让大家帮我看看问题出在哪

初始化程序为
void  time1_init(void)
{
       TCCR1A=0x00;       //普通计数
       TCCR1B=0xc1;       //捕捉使能,上升沿触发,不分频
       TIMSK1=0X20;      //开中断
}

捕捉中断程序
void   INcatch_ser(void)
{
      uint    a,b;

      if(PINB&0X01)    //读脚位电平
     {
          a=ICR1L;
          b=ICR1H;
          num1=(b<<8)|a;   
          TCCR1B  &= 0XBF;    //改触发方式,下降沿
       TIFR|=(1<<ICF1);    //改变触发方式后立即清中断标志
          m=1;   //上升沿捕捉完成标志
     }
     else
     {
          a=ICR1L;
          b=ICR1H;
          num2=(b<<8)|a;
          TCCR1B  |= 0X40;    //改触发方式,上升沿
       TIFR|=(1<<ICF1);   //改变触发方式后立即清中断标志
          n=1;  //下降沿捕捉完成标志
     }
     if((m==1)&&(n==1))   //表示一个完整的高电平脉宽检测完
     {
            if(num1<num2)  num3= num2-num1;    //判断定时器是否溢出
            else    num3=0xffff-num1+num2;
            n=0;m=0;
     }
}

出0入0汤圆

 楼主| 发表于 2012-6-6 18:26:11 | 显示全部楼层
怎么么人啊,不可能都没用过啊?

自己先顶顶

出0入0汤圆

发表于 2012-6-6 19:48:56 | 显示全部楼层
没看你前个帖子,不知道用的什么芯片,执行一条指令要多长时间
考虑下中断响应时间,是否还有别的中断

出0入0汤圆

发表于 2012-6-13 10:07:54 | 显示全部楼层
你的捕捉程序我看了   我用的是飞思卡尔DZ32   呵呵 我正好要用到   我用一下试试

出0入0汤圆

 楼主| 发表于 2012-6-15 14:45:01 | 显示全部楼层
zhaochuanyuAVR 发表于 2012-6-13 10:07
你的捕捉程序我看了   我用的是飞思卡尔DZ32   呵呵 我正好要用到   我用一下试试 ...

也不能原搬照抄啊,先看懂我写的思路才是最重要的!

出0入0汤圆

 楼主| 发表于 2012-6-15 14:47:42 | 显示全部楼层
zhaochuanyuAVR 发表于 2012-6-13 10:07
你的捕捉程序我看了   我用的是飞思卡尔DZ32   呵呵 我正好要用到   我用一下试试 ...

发现测不准的原因,别忘了跟我说声丫!

出0入0汤圆

发表于 2012-6-15 15:15:48 | 显示全部楼层
支持一下!

出0入0汤圆

发表于 2012-6-15 16:59:11 | 显示全部楼层
>> 测出的数据怎么感觉比用定时器测得误差还大呢??
不应如此。

初始化程序为
void  time1_init(void)
{
void  time1_init(void)
{
       TCCR1A=0x00;       //普通计数
       m=0;
       n=0;
        
       // TCCR1B: 不使能输入捕捉噪声抑制,上升沿触发,不分频
       TCCR1B = (0<<ICNC1)|(1<<ICES1)|(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10)

       // 先等待上升沿,然後等待下降沿
       while !(PINB & 0x01);
       while (PINB & 0x01);      
      
       TIFR|=(1<<ICF1);    //清 ICF 中断标志
      
       TIMSK1=0X20;        //开捕捉中断
}

捕捉中断程序
void   INcatch_ser(void)
{
      uint    a;

    a = ICR1;   

      if(PINB&0X01)    //读脚位电平
     {
          num1=a;   
   
        // TCCR1B  &= 0XBF;    //改触发方式,下降沿
         
         // TCCR1B: 不使能输入捕捉噪声抑制,下降沿触发,不分频
        TCCR1B = (0<<ICNC1)|(0<<ICES1)|(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10)

         TIFR|=(1<<ICF1);    //改变触发方式后立即清中断标志
          m=1;   //上升沿捕捉完成标志
     }
     else
     {
          num2=a;
          // TCCR1B  |= 0X40;    //改触发方式,上升沿
  
          // TCCR1B: 不使能输入捕捉噪声抑制,上升沿触发,不分频
         TCCR1B = (0<<ICNC1)|(1<<ICES1)|(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10)

         TIFR|=(1<<ICF1);   //改变触发方式后立即清中断标志
          n=1;  //下降沿捕捉完成标志
     }
     if((m==1)&&(n==1))   //表示一个完整的高电平脉宽检测完
     {
            if(num1<num2)  num3= num2-num1;    //判断定时器是否溢出
            else    num3=0xffff- num1 + num2 + 1;
            n=0;m=0;
     }
}

出0入0汤圆

 楼主| 发表于 2012-6-15 19:44:31 | 显示全部楼层
eblc1388 发表于 2012-6-15 16:59
>> 测出的数据怎么感觉比用定时器测得误差还大呢??
不应如此。

谢谢你的回复,我按照你的修改了一下程序,测了一组数据感觉还是不准
1490us         12290---12360之间,乘以0.125的话是  1536---1545
1490us信号源是决对稳定准确的,这个我用示波测过,这次我是单独提取这段程序做测试,所以也不会什么其它程序上的干拢。
我用两个板试得都一样,是乎硬件上也没有问题啊。
还会是什么问题呢??

出0入0汤圆

发表于 2012-6-15 20:26:34 | 显示全部楼层
>> 1490us信号源是决对稳定准确的
九成九是信号源不稳定。

你有没有 HC4040,如有的话,把HC4040的的时钟输入(10脚)接到 M48 的 XTAL2, 11脚接地,第1脚12倍分频输出(8MHz/4096=1.953KHz, 大约512uS)接到 M48的 ICP1,看看输入捕捉数据是准不准。

出0入0汤圆

发表于 2012-6-15 20:34:47 | 显示全部楼层
your code is way too complicated.

all you need to do is to set up the timer, but keep it stopped.

wait for the leading edge of the pulse, then turn on the timer.
wait for the trailing edge of the pulse, then turn off the timer.
at that point, return the count.

on 8Mhz crystal, I got 8003 while counting a 1000us pulse, vs. a 8000 theoretical count.

出0入0汤圆

 楼主| 发表于 2012-6-15 21:40:47 | 显示全部楼层
millwood0 发表于 2012-6-15 20:34
your code is way too complicated.

all you need to do is to set up the timer, but keep it stopped.

很感谢你的见意,我大概明白你的意思,不过我的英语水语不好,不能用英文回复你,抱歉!

我这程序是复杂了点,不过目前为止我也想不出更简单明了的。
不地这句我就不太明白了“to set up the timer, but keep it stopped”,  开启捕捉而不是关闭??  难道我的没有开启吗??

你测1000us的脉冲能够做到那么精确是怎么做到的啊,能分享一下你的代码吗?或者帮我修改一下。文字说明容易理解错。thank you  very  much!!

出0入0汤圆

 楼主| 发表于 2012-6-15 21:55:19 | 显示全部楼层
eblc1388 发表于 2012-6-15 20:26
>> 1490us信号源是决对稳定准确的
九成九是信号源不稳定。

没有那玩意,也许确实是信号源的问题,很感谢你!

出0入0汤圆

发表于 2012-6-15 22:06:17 | 显示全部楼层
caihong001 发表于 2012-6-15 21:55
没有那玩意,也许确实是信号源的问题,很感谢你!

你也可以轻易的使另外一枚 M48+CTC 来取得非常稳定的讯号。

出0入0汤圆

发表于 2012-6-15 22:19:02 | 显示全部楼层
我使用10MHz,Mega48输入捕获1秒周期的讯号,得到的数值是10,000,000,误差只是正负1,足见输入捕获可以非常精确。

使用Mega48输入捕获, 用 GPS 1PPS 来校准恒温晶振

出0入0汤圆

 楼主| 发表于 2012-6-15 22:31:15 | 显示全部楼层
eblc1388 发表于 2012-6-15 22:19
我使用10MHz,Mega48输入捕获1秒周期的讯号,得到的数值是10,000,000,误差只是正负1,足见输入捕获可以非 ...

哦,程序就如上面那样吗?还有我用得是内部晶振,会不会跟这个也有关呢?

出0入0汤圆

发表于 2012-6-15 22:41:43 | 显示全部楼层
还有我用得是内部晶振


Bingo!

You used internal RC (not 内部晶振 as 内部晶振 doesn't exist).

here is my version of your code:


  1. //捕捉中断程序
  2. unsigned short INcatch_ser(unsigned char ch) {
  3.     //unsigned char a,b;

  4.     DDRB &=~ch;                        //ch as input

  5.     //reset the timer
  6.     TCCR1B = 0x00;                //stop the timer
  7.     TCCR1A=0x00;       //普通计数
  8.     //TCCR1B=0xc1;       //捕捉使能,上升沿触发,不分频
  9.     TCCR1C = 0x00;                //no foc
  10.     TCNT1 = 0x00;                //reset the counter
  11.     //TIMSK1=0X20;      //开中断

  12.     while (!(PINB & ch)) continue;                //wait for pinb.0 to go high
  13.     TCCR1B = 0xc1;                //start the timer
  14.     while ( (PINB & ch)) continue;                //wait for pinb.0 to go low
  15.     TCCR1B = 0x00;                //stop the timer
  16.     return TCNT1;
  17. /*
  18.     if(PINB&0X01) {  //读脚位电平
  19.         a=ICR1L;
  20.         b=ICR1H;
  21.         num1=(b<<8)|a;
  22.         TCCR1B  &= 0XBF;    //改触发方式,下降沿
  23.         TIFR|=(1<<ICF1);    //改变触发方式后立即清中断标志
  24.         m=1;   //上升沿捕捉完成标志
  25.     } else {
  26.         a=ICR1L;
  27.         b=ICR1H;
  28.         num2=(b<<8)|a;
  29.         TCCR1B  |= 0X40;    //改触发方式,上升沿
  30.         TIFR|=(1<<ICF1);   //改变触发方式后立即清中断标志
  31.         n=1;  //下降沿捕捉完成标志
  32.     }
  33.     if((m==1)&&(n==1)) { //表示一个完整的高电平脉宽检测完
  34.         if(num1<num2)  num3= num2-num1;    //判断定时器是否溢出
  35.         else    num3=0xffff-num1+num2;
  36.         n=0;
  37.         m=0;
  38.     }
  39. */
  40. }
复制代码

出0入0汤圆

发表于 2012-6-15 23:01:42 | 显示全部楼层
caihong001 发表于 2012-6-15 22:31
哦,程序就如上面那样吗?还有我用得是内部晶振,会不会跟这个也有关呢? ...

一定就是这带出的问题,用外接晶振吧。

出0入0汤圆

 楼主| 发表于 2012-6-18 09:43:25 | 显示全部楼层
在这里特别感谢eblc1388和millwood0的全力解答!问题出在内部RC上,一般情况下我用的是5V电压,但随着电压慢慢的下降,误差范围也会进一步扩大,总之感觉用内部RC做精确的脉宽测量比较难。但也不是说一定不能,或许有哪位高人有更好的办法。

出0入0汤圆

发表于 2021-8-19 17:01:59 | 显示全部楼层
能看到这么精彩的讨论,真是幸福
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号 )

GMT+8, 2022-7-3 14:08

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表