智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 3933|回复: 10
打印 上一主题 下一主题

XS128输入捕捉(InputCapture),测脉宽时诡异的问题

[复制链接]

4

主题

22

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
威望
146
贡献
67
兑换币
80
注册时间
2013-3-15
在线时间
22 小时
毕业学校
USTC
跳转到指定楼层
1#
发表于 2013-8-10 10:56:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
是用输入捕捉功能测一个脉冲的宽度。其实就是超声波测距的那个HC-SR04,这个模块返回来的东西是一个持续若干毫秒的方波脉冲。我要用输入捕捉测量这个宽度。
注意用的是输入捕捉,不是像看到的很多例子的那个输入捕捉,那个应该称为外部中断,因为根本没有用真正意义上的输入捕捉。。
输入捕捉就是,当发生事件匹配时,由硬件把当前计数器的值(TCNT)保存到一个寄存器中(TCx),不是使能计数器设置累计变量什么的。


测脉宽就是这样,这里是用的是T0口:

1、设置为上升沿触发,使能中断;
2、上升沿到来后,(通过if判断知道到来的是上升沿),在中断服务程序中改为下降沿触发;
3、下降沿到来后,(通过if判断知道到来的是下降沿),在同一个中断服务程序中,把TC0的值存起来。wtemp=TC0;

这是wtemp就是脉宽。
框架程序如下:

        us0Trig = 1;//这是触发信号,一个10us的脉冲
        TCTL4_EDG0A=1;
        TCTL4_EDG0B=0;//设置成rising edge触发
        Delay_us(10);
        us0Trig = 0;//触发信号发送完毕 trig send ok
        TIE_C0I = 1;//使能中断

        Delay_ms(100);//在这100ms里,完成测脉宽的工作。(中断函数执行两次,第一次上升沿,第二次下降沿)


中断程序如下:
void interrupt VectorNumber_Vtimch0 us0measure(void){
  //第一个超声波的中断函数
  TFLG1_C0F = 1;//clear flag清标志
  if(TCTL4_EDG0A == 1){//如果刚才来到的是上升沿
    //上升沿来到
    TCTL4_EDG0A = 0;
    TCTL4_EDG0B = 1;//falling就改成下降沿触发,等下一个下降沿的到来
    TCNT = 0;//clear timer这是下面的第二个问题
    //return;
  }else{
    //下降沿来到
    //disable intt
    wtemp = TC0;//保存TC0,这个就是Capture到的脉宽。
    TIE_C0I = 0;
    //sprintf(szBuffer,"MeasTC0:%d",wCntCaptured[bCntMeasured-1]);其实是测量几次取最小值,这里略去
  }
  //LCD_write_english_string(0,3,szBuffer);
  return;
}


wtemp就是了。
出现了诡异的问题。本来用的好好的,可以在5110上显示距离。但是连上一大堆别的东西后就不行了。
然后把外围的东西都拔掉,还是有问题。
是这样的:如果用BDM供电,按下F5后,单击“Run”,非常好,可以准确测距。
如果用7805供电,出来的结果是一坨烂玩意。但是,所有的中断都执行了。
不会是供电的问题,因为:如果我用BDM供电,但是按系统板上的“复位”按钮,出来的又是一堆垃圾。
看起来,像是TCNT是乱飞的,或者,是没有在合适的地方清零。
而用7805,本质上是按复位按钮。所以姑且认为,唯一的区别是“单击调试工具上的复位(运行)”和“按下系统板上的复位”。
这他么怎么就不一样呢!!!求解答。

还有,我想知道匹配发生的时候,TCNT是什么状态?清零?还是接着跑(free running)?
数据手册上的意思好像是接着跑,但是如果接着跑,我上面的程序是永远不可能得到正确结果的,但是我曾经得到过。而且,没有发现给TCNT清零的方法。上面写的是:Write: Has no meaning or effect in the normal mode;
那这个计数器到底是怎么跑的呢。
还有,这个模块貌似只有一个timer,那如果有好几个InputCapture,如果是清零的话岂不要乱套。但是。。。
这到底是怎么回事呢?有没有同志研究过这个玩意儿?


31

主题

619

帖子

0

精华

跨届大侠

大神经常病

Rank: 10Rank: 10Rank: 10

积分
8900

论坛元老奖章在线王奖章活跃会员奖章优秀会员奖章

威望
4214
贡献
2736
兑换币
2252
注册时间
2012-2-15
在线时间
975 小时
2#
发表于 2013-8-10 13:43:26 | 只看该作者
这问题好高深啊。。。是不是代码下错地方了?

回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
威望
146
贡献
67
兑换币
80
注册时间
2013-3-15
在线时间
22 小时
毕业学校
USTC
3#
 楼主| 发表于 2013-8-10 13:58:18 | 只看该作者
搞好了。下面我要解释一下。
回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
威望
146
贡献
67
兑换币
80
注册时间
2013-3-15
在线时间
22 小时
毕业学校
USTC
4#
 楼主| 发表于 2013-8-10 14:24:25 | 只看该作者
其实我上面的叙述已经很接近真相了。不过我又绕了个圈才发现。
就是这三句话:
第一句:::唯一的区别是“单击调试工具上的复位(运行)”和“按下系统板上的复位”。
第二句:::数据手册里,Write: Has no meaning or effect in the normal mode; only writable in special modes (test_mode = 1)(靠我上面说问题的时候,犹豫了一下没有考后面的半句)
第三句:::单击调试工具上的复位,是special mode,按下系统板上的复位,是normal mode。
已经看懂的不用往下看了。

主要就是那个TCNT=0,如果是前一种情况,就确实清零了。所以得到的是正确的结果。
如果是后一种情况,这一句根本没有把计数器清零(无法清零,总是free running)。所以得到的是错误的结果。
如果把TCNT=0这句话注释掉。那么,就都不能用了。因为这时候,TCNT是完完全全的free running。
从0开始往后数,数到0xffff,回到0.如果发生Input Capture,就把TCNT的当前值存到对应的TCx中。这才是最科学的,因为整个IOC模块只有一个计数器。必须保证free running才能保证互不影响。
至于那个test_mode,可以去看数据手册里的Background Debug Module,什么时候是什么mode可以执行什么操作执行的结果是什么,是个值得探讨的问题。

所以,要想实现计数脉冲宽度,就要用两次InputCapture的值作差。开一个signed long 变量。如果相减是负数,就再加一个0xffff(因为我知道无论如何也不可能溢出两次的)。有特殊需要的同志可以使用溢出中断,如果溢出就把一个计数变量加一。当然开signed long和直接读溢出标志应该都是可以的(如果溢出标志是1,就说明溢出过。即使没有使能中断,这个标志还是会被置的。兴许还要手动清零,不过就不能知道溢出次数了,假如会溢出多次)。

就这样。我更百分之九十九点九的相信,以我现在的水平,如果出了问题,那一定是我的问题。

顺便说下我搜的论坛上用这个模块的方式,虽然是可以的,不过是完全的浪费,不过因为我们的车已经够用所以很少有人注意到。
主要是用来测速。只是使用了一个边沿中断,剩下的事,比如,打开一个pit,在pit中断里把计数变量加一什么的,都是用软件做的。这真是完全没有必要。InputCapture本来就是为计数宽度用的,我们却舍近求远开什么pit。要知道,虽然中断是个很好的东西,但是在不合适的时候被频繁打断确实是很糟糕的事情。尤其是我们用的质量很好的几百线的编码器。
如果真的要用pit的方式,应该用端口P、H或J,这三个端口的所有针脚都有边沿触发功能,就像大多数人使用InputCapture一样。具体的设置也很简单。(虽然我目前还没用过。)

就这样了。欢迎交流。
回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
威望
146
贡献
67
兑换币
80
注册时间
2013-3-15
在线时间
22 小时
毕业学校
USTC
5#
 楼主| 发表于 2013-8-12 12:46:43 | 只看该作者
Frozenflame 发表于 2013-8-10 13:58
搞好了。下面我要解释一下。

虽然脑袋晕晕的也不至于把代码下错地方。。
回复 支持 反对

使用道具 举报

24

主题

114

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
3252
威望
990
贡献
1908
兑换币
304
注册时间
2011-8-17
在线时间
177 小时
6#
发表于 2013-9-2 23:10:40 | 只看该作者
本帖最后由 自明了然 于 2013-9-2 23:34 编辑

楼主我也在用输入捕捉测脉宽,网上确实好多程序都不规范都是结合外部中断用的,下面是我的程序,可在2m内测距,但是不稳定
void interrupt 8 timech0_capture(void)    //输入捕捉通道0的中断向量为8
{
   TFLG1_C0F=1;   //标志位清零

     T0interruptcount++;
     OutData[0] = TCNT;
     if(T0interruptcount==1)
        {
        
          firstnum = TC0;  OutData[1] = firstnum;
          //TimerOverflow = 0;  
         }       //上升沿捕捉
     if(T0interruptcount==2)
        {
         
          secondnum = TC0;
            OutData[2] = secondnum;

         timecount = secondnum-firstnum;
         if(timecount<0)   timecount+=65535;
         
         OutData[3] = timecount;
         

          distance = (unsigned int)timecount;
           distance = (unsigned int)(timecount/58);
          T0interruptcount = 0;

          }        //下降沿捕捉
                     
}

以上是波形图,结果直接TCNT和TC0竟然都有负值,实在让我郁闷!!!!!求助啊!!!









本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

24

主题

114

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
3252
威望
990
贡献
1908
兑换币
304
注册时间
2011-8-17
在线时间
177 小时
7#
发表于 2013-9-2 23:20:05 | 只看该作者
本帖最后由 自明了然 于 2013-9-2 23:36 编辑

黄线是第一次的计数器值(也就是上升沿触发时的值),蓝线是第二次(下降沿触发时的值),紫线是差值(也就是脉宽高电平时间)
void Init_ECT0(void)
{

     TSCR2=0X06;           //溢出中断关闭且64分频   计一个数为1us
     TIOS_IOS0=0;          //定通道0为输入捕捉
     TCTL4=0X03;             //上升沿捕捉  0x02为下降沿捕捉 0x03为任意沿捕捉
     TIE_C0I=1;               //通道0中断使能
     TSCR1=0X80;      //开启总定时器中断
     TFLG1_C0F=1;   //标志位清零
     
}
回复 支持 反对

使用道具 举报

14

主题

84

帖子

0

精华

高级会员

Rank: 4

积分
798
威望
495
贡献
127
兑换币
294
注册时间
2013-9-18
在线时间
88 小时
毕业学校
哈尔滨工业大学
8#
发表于 2014-4-29 15:14:51 | 只看该作者
Frozenflame 发表于 2013-8-10 14:24
其实我上面的叙述已经很接近真相了。不过我又绕了个圈才发现。
就是这三句话:
第一句:::唯一的区别是 ...

楼主你好我也遇到相同的问题了,但是我找你说的改了还是不好使,插上下载线好使,

中断中是这样的
{
   time[1]=time[0];
   time[0]=TCNT;
   if(time[0]-time[1]<0)
    time[2]=time[0]-time[1]+0xffff;
   else
    time[2]=time[0]-time[1];




}

为啥这样得到的time[2]  还是不正确的呢
回复 支持 反对

使用道具 举报

10

主题

99

帖子

0

精华

高级会员

Rank: 4

积分
653
威望
409
贡献
118
兑换币
143
注册时间
2011-10-31
在线时间
63 小时
9#
发表于 2014-5-2 02:53:28 | 只看该作者
我最近也在S12上弄这个,楼主分析的也是我想的,TCNT正常模式下是不能清零定的,而且禁止定时器后,还是自由运行,是一个自由计数器。不过还可以通过脉冲累加的门限方式直接测量脉宽,即时间
回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
威望
146
贡献
67
兑换币
80
注册时间
2013-3-15
在线时间
22 小时
毕业学校
USTC
10#
 楼主| 发表于 2014-8-27 17:18:36 | 只看该作者
自明了然 发表于 2013-9-2 23:10
楼主我也在用输入捕捉测脉宽,网上确实好多程序都不规范都是结合外部中断用的,下面是我的程序,可在2m内测 ...

是不是因为溢出了多次所以有问题?
还有,非常重要的,你的变量的数据类型可能有严重问题,记录计数器值的变量应该使用unsigned,记录差值的变量应该使用signed,在合适的时候应该使用强制类型转换.
所以你可能是把大于 2^15 的无符号数当成有符号的了,所以看到的是负值.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-29 01:33 , Processed in 0.071160 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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