Board logo

标题: 请教脉冲累计器的“分辨率” [打印本页]

作者: asker_dfr    时间: 2007-7-2 11:22

在论坛上也看了许多tx的关于脉冲捕捉和脉冲累加器的帖子,明白一些,也还存在很多不懂的地方。我同时也对级联后的16位脉冲累计通道A进行了配置(似乎比B复杂一些),得出的效果也对于100Hz以下的脉冲输入不敏感,我纳闷了,用输入捕捉(IC)方式,可以很精确地采集并计算出脉冲的周期,不至于脉冲累积器的分辨率就只这么低吧。想来问题要不出在对脉冲累积器的初始化,要不硬件问题,请各位大侠指点一哈^_^
作者: asker_dfr    时间: 2007-7-2 11:23     标题: 请教脉冲累计器的“分辨率”

在使用S12系列单片机(DP256)进行脉冲累计的测试,发现按照我的如下初始化配置:
void pbca_init(void)
{
    PBCTL_PBEN = 1;
    TCTL4_EDG0A = 1;
    TCTL4_EDG0B = 0;//Capture on rising edges only
}

使用级联后的16位通道B进行脉冲累计,脉冲由PT0输入,定期读取PACN10(Pulse Accumulators Count 10 Register; 0x00000064 ***/)的值来反映一定时间上的脉冲数,然后可计算出脉冲频率。
请问:1)这种方式用来计算脉冲频率有问题吗?
2)我读取PACN10,发现其最大的分辨率只在100Hz,也就是说100Hz以下频率的脉冲输入(我使用的是函数发生器输入方波信号),该脉冲累计器没用变动,当高于100Hz时,PACN10开始累计。请问,这正常吗?我希望能够如实第捕捉从1Hz到10KHz的脉冲频率

[此贴子已经被作者于2007-7-2 11:23:32编辑过]


作者: strongchen    时间: 2007-7-2 11:30

你说的定期读取PACN10的值,是如何定期的呢?周期是多长?
作者: asker_dfr    时间: 2007-7-2 13:25

比如我在主程序中10ms读取一次PACN10的值,然后将当前值与上一次读取的值相减,这样的差值就是就可以计算出脉冲频率。这样的计算有问题吗?10ms时间我是通过模数递减计数器(MDC)产生1ms定时中断,累计10次得出的

版主的回复好快啊,谢谢

[此贴子已经被作者于2007-7-2 13:25:26编辑过]


作者: strongchen    时间: 2007-7-2 14:03

100Hz的周期正好是10mS。100Hz以下频率的信号也有问题吗?把你的project整个打包贴出来看看吧。
作者: asker_dfr    时间: 2007-7-2 16:03

不好意思,我下午想到一些东西,可能对于解决这个有所启发,正在理清头绪
作者: asker_dfr    时间: 2007-7-2 16:10

我下午随意在本子上写了一些什么是频率,10ms采集的对比
频率就是单位时间的脉冲数量,设脉冲数量为0~Nmax,单位时间就是1s
那么频率 f = (0~Nmax)/ (1 s)
1)目前我是10ms计算读取一次脉冲累加器(PACN10)的值,
此时频率计算 f1 = ( (0~Nmax)÷100 )/ (10 ms)
从( (0~Nmax)÷100 )这个式子来看,实际采集来的脉冲数被人为地压缩了100倍。
2)如果我是1s计算读取一次脉冲累加器(PACN10)的值,
此时频率计算 f2 = ( (0~Nmax) )/ (1s)
这样似乎就没用“分辨率”降低的忧虑了,但是这样,对于脉冲计算的延时,是相当滞后的。比如车速采集,不知道这样考虑是否正确
作者: strongchen    时间: 2007-7-2 16:17

如果你在运算中确实采用了÷100的运算,那么会有很多数值会被丢掉。实际上在应用程序中,这样的运算不推荐使用,也没有必要。你不必非要得到以Hz为单位的频率值。
作者: asker_dfr    时间: 2007-7-2 17:12

是的,确实很多数值被丢掉了。今天谢谢strongchen的回答和帮助。我还有一些问题可能还要实践一下,遇到了问题再请教大家。
作者: asker_dfr    时间: 2007-7-2 17:22

其实在运算中并没用对PACN10÷100,只是以每10ms读取一次累加寄存器的方式,100Hz以内的脉冲是不能被侦测到差值的,上面f1 = ( (0~Nmax)÷100 )/ (10 ms)或者f2 = ( (0~Nmax) )/ (1s)的计算完全是由单位换算看到出现的绝对误差。呵呵,我的表述不知道是否清楚。不过我觉得这是个问题。
作者: strongchen    时间: 2007-7-3 10:03

建议你先做一个最简单的脉冲计数程序试试,不要任何运算。如果还有问题,可以将这个project贴出来看看。
作者: asker_dfr    时间: 2007-7-3 14:56

下午,做了一个最简单的脉冲计数程序。我所遇到的问题,现在想来,既非初始化的问题,也不是硬件的毛病。是“定时”读取PCN10或者PCN32中存在的误差。我把整个project贴出来,可能会说得更清楚

word plus_data[10];
void mdc_init(void) //MDC初始化,配置为1ms定时基准
{
    MCCTL = 0xcd;
    MCCNT = 2000;
}

#pragma CODE_SEG NON_BANKED //MDC中断服务程序
#pragma TRAP_PROC
void MDC_ISR(void)
{
    MCCNT=2000;
    MCFLG=0x80;

    if ( mdc_cout > 60000 )
    {
        mdc_cout = 0;
    }
    mdc_cout++;

    if ( !(mdc_cout%100) ) //100ms定时标识
    {
        plus_run_flag = 1;
    } 
}
#pragma CODE_SEG DEFAULT


void pbca_init(void) //脉冲累加器B的开启与边沿捕捉的配置
{
    PBCTL_PBEN = 1;
    TCTL4_EDG0A = 1;
    TCTL4_EDG0B = 0;
}

void plus_cont(void) //一定时间(100ms)内脉冲数量
{
    static word oldValue;

    plus_data[0] = abs(PACN10 - oldValue);
    oldValue = PACN10;
}

void main(void)
{
    DisableInterrupts;
    mdc_init();
    pbca_init();

    EnableInterrupts;

    while(1)
    {

        if(plus_run_flag) //100ms定时标志位
        {
            plus_run_flag = 0;
            plus_cont();
        }
    }
}

    目前100ms读取一次PACN10的值并与前一次记录下来的值作比较,得到该100ms内的脉冲数N,即N/100ms = N*10/1s = N*10 Hz,只是作减法,但是低于10Hz的脉冲,却由于我是100ms的读取,能捕捉到,但在我的差值plus_data[0]上是没用大的持续变化的,因此计算出来脉冲频率“分辨率”只能是10Hz;昨天我用10ms的周期定时读取PACN10,差值plus_data[0]更是只在100Hz开外变动,即只能识别诸如1.1~1.2Khz,而没法读到1.100~1.299Khz,
这样分析一下,不知道是不是抓住了根本。

[此贴子已经被作者于2007-7-3 14:56:48编辑过]


作者: asker_dfr    时间: 2007-7-3 15:51

还要一个问题想请教,我可否在PTO上既使用输入捕捉(IC)功能,又能开启脉冲累积器进行计数,也就是想用“IC算周期”和“脉冲累积器算频率”共同计算同一个输入信号的频率,而不使用两个通道分开进行采集。
(我试着在程序中将IC的初始化和pbca_init(void)初始化均打开,实际只是IC初始化起作用,即只输入捕捉采集到数据,PACN10无变化)
作者: strongchen    时间: 2007-7-3 16:10

把整个project打包贴出来吧。
作者: asker_dfr    时间: 2007-7-3 16:24

我打包发上来啦http://bbs.chinaecnet.com/uploadImages/plus_test.rar
作者: asker_dfr    时间: 2007-7-3 16:38

现在打包的是将IC的初始化ic_init()和pbca_init(void)初始化均打开,最后只有IOC0_wData采集到了周期值,plus_data[0]的值却不正常(在跳动),我希望是能够“‘IC算周期’和‘脉冲累积器算频率’共同计算同一个输入信号的频率”http://bbs.chinaecnet.com/uploadImages/plus_test2.rar
作者: asker_dfr    时间: 2007-7-3 16:41

plus_test2.rar 中,如果单个初始化,如只进行脉冲捕捉ic_init()初始化,或者之将B通道的脉冲累积器使能pbca_init(void),则结果正常。是不是该PTO对于这两个功能不能复用?
作者: strongchen    时间: 2007-7-3 17:42

我看了你前面的程序。你的问题出在这一句:
plus_data[0] = abs(PACN10 - oldValue);
你只用一个单元,即plus_data[0]来记录PACN10的差值。后一个值总会把前一个值覆盖。当查询频率快于信号频率时,你想想看会发生什么情况?plus_data[0]必然会在很多时间都为0,你自然是感觉“不敏感”了。如果你只读PACN10的值,就会发现,实际上它的值是一直在递增的,直到溢出后翻转。
作者: asker_dfr    时间: 2007-7-4 08:57

首先谢谢strongchen的解答,^_^
是的,我后来也发现问题之所在,“当查询频率快于信号频率时”,PACN10=oldValue,结果是统计不出当前脉冲的,不过我总是要类似的方法来计算频率吧,如果要求有比较好的实时性,采集并且滤波之后不致于滞后太多。如果把输入频率调至1Hz并实时监控PACN10的值,确实能够看到该累积器是从0至0xFFFF在递增的。

另外,PAC和IC共享相同的引脚,用它来对同一引脚进行记录,为何我让其一同工作的时候(前者用于记录脉冲数量,后者记录脉冲周期)在plus_test2.rar 中,得到的脉冲数量却不正常,但是偶尔能够采集到正常,问题又出在哪里呢?

[此贴子已经被作者于2007-7-4 8:57:03编辑过]


作者: asker_dfr    时间: 2007-7-4 17:36

plus_test2.rar的main.c中发现,读取TC0H的值对脉冲累积器的值PCN10有影响,怎么解决呢?
作者: asker_dfr    时间: 2007-7-5 10:35

我设置PT0脚输入捕捉和脉冲累积器B使能,当我读取TC0H的值对脉冲累积器的值PCN10有影响(把PCN10清零了),不知这种做法是否妥当,有没用办法不让PCN10被清零。我看说明文档中,只是ICSYS中的LATQ位设为1(锁存方式)时候,才会在捕捉到内容并转移至保存寄存器,才会将8为的脉冲累积器清零。然而,我设置的是队列方式,而且用的是级联后的累计其B。有点不明白了
作者: strongchen    时间: 2007-7-5 10:49

我觉得你的方法有问题。如果你最终的目的是得到脉冲的频率,而非只是要计脉冲的个数,建议你就采用输入捕捉的方式,通过脉冲周期来计算脉冲频率。而且应采用中断的方式。这样响应速度也快,频率计算也精确。
作者: asker_dfr    时间: 2007-7-5 11:01

版主的回复好快啊,谢谢

首先想比较充分利用PT0的资源,因为毕竟它有这个功能,而且针对一个脉冲信号,不同频率下(低频段,高频段)我根据需要精度和实时性的要求,可以采用“脉冲周期来计算脉冲频率”或者用记脉冲的个数。
另外,最初我是用中断方式来进行输入捕捉(IC),但发现输入脉冲在1K以上之后,非常占用MCU的资源,我想如果MCU还需要进行较多的上层其他控制计算的话,这样的中断方式似乎很不可取,除非我专门进行脉冲采集。呵呵

刚才,我试了只用PT0进行脉冲累计,PT3进行输入捕捉,对同一信号进行采集,结果是相互毫无影响,能正常工作。

[此贴子已经被作者于2007-7-5 11:01:52编辑过]


作者: asker_dfr    时间: 2007-7-5 11:09

其实最开始我也挺怀疑这种方法的,但是在一本书上看到“由于PAC0~3与IC0~3共享相同的引脚,而且共享入口的逻辑,因此在两者方式下,PAI与IC都可以同事工作,对同一引脚进行记录,前者记录脉冲或者边沿的数量,后者记录具体的时刻”(该MCU文档中我还没用找到有没有这样的说明),所以呢,想尝试一下。
有这么多高手在论坛上,无论这种方式的对错,我想都会有解决的。
或许只是说由于“PAC0~3与IC0~3”,而非“PACA和IC0”?
作者: asker_dfr    时间: 2007-7-5 11:11

最后一句改正:
或许只是说由于“PAC0~3与IC0~3共享相同的引脚”,而非“PACB和IC0”?

[此贴子已经被作者于2007-7-5 11:11:54编辑过]


作者: asker_dfr    时间: 2007-7-5 14:28

目前采取的办法就是用脉冲捕捉的时候不读取脉冲累积器的值,如果在30~2Khz范围,用脉冲捕捉得到周期再算频率的方法还是很准确的。
谢谢stongchen的跟帖和解答。还要,我在有个帖子中看到了stongchen写的有关PE的操作,很实用,真是热心啊
作者: strongchen    时间: 2007-7-5 16:55

我一直在看你的project,我觉得有这几个方面的问题:
1. ICSYS的BUFEN=1而LATQ=0。根据数据手册,此时每当发生输入捕捉事件时,TC10和TC10H的值会刷新;但是此时PACN10和PACN10H的值如何变化却没有说明;实际上,PACN10和PACN10H的值应该在LATQ=1的情况下,与MCCNT的动作同步;所以输入捕捉和脉冲计数不能同时采用缓冲锁存的方式计数;
2. 你对输入捕捉和脉冲计数的读数都是在主循环中根据MDC的定时进行的。输入捕捉和脉冲计数都没有采用中断。这样,你的读数与输入信号是不同步的。这在高频而且频率稳定的情况下可能没有问题,但是如果输入信号频率较低,或者输入信号的频率变化较快的情况下,读数就会出现错误。
作者: asker_dfr    时间: 2007-7-6 08:28

早上一来,又仔细看了strongchen昨天的留言,谢谢你的关注,让我对于ECT内部的一些工作细节又有了深入的了解。我再看看文档,在脉冲捕捉中,对于周期的计算,还碰到一些问题,我先想一想,不明白再向各位请教

作者: strongchen    时间: 2007-7-6 18:27

我现在知道PACN10被清零的原因了。因为BUFEN=1而LATQ=0,脉冲计数处于QUEUE模式。按照数据手册的说明,此时当读脉冲计数锁存寄存器时,会将脉冲计数器的值传到锁存器中,并将脉冲计数器清零。你的程序虽然没有读脉冲计数锁存器,但在调试时,每当运行停止、遇到中断或周期性刷新显示时,BDM都会去读所有寄存器的值,从而导致脉冲计数器被清零。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0