脉冲宽度测量

时间:2015-09-06 09:54:38

标签: avr avr-gcc atmega atmel atmega16

我想测量脉冲持续时间,但我需要测量4个信号,因此我不能使用定时器捕获中断,因为只有1个引脚ICP1提供该选项(或可以?)。所以我尝试实现类似arduino pulseIn的东西,区别在于我使用的是计时器(arduino有一些其他的实现,但非常相似)。

实际问题是pulseIn没有返回任何东西,只是继续在无限循环中工作。

使用ATmega16。 现在仅在PB2上进行测试。

unsigned long pulseIn()
{
    unsigned long duration = 0;
    DDRB = 0x00;

    /* Initiate timer and wait for the end of previous pulse*/
    initTime1();
    while(getPortBPin(2) == 1);

    /* Wait for current pulse begin */
    while(getPortBPin(2) != 1);

    /* Time before previous pulse ended */
    TCNT1 = 0;
    overflowCounter = 0;

    /* Wait for current pulse end */
    while(getPortBPin(2) == 1);

    /* Closk freq is 2 MHz = 1/2 us per tick */
    duration = (TCNT1+overflowCounter*65536)/2;
    overflowCounter = 0;
    stopTimer1();

    return duration;
}

void initTime1()
{
    /* Noise filtering */
    TCCR1B = (1 << ICNC1);

    /* Set prescaling factor to 8 */
    TCCR1B |= (1 << CS11);

    /* Enable overflow interruption */
    TIMSK = (1 << TOIE1);

    /* Clear counter */
    TCNT1  = 0;
}

void stopTimer1()
{
    TCCR1B = 0;
    TIMSK = 0;
    TCNT1 = 0;
}


uint8_t getPortBPin(uint8_t pin)
{
    if(pin < 0 || pin > 8)
    {
        return 0;
    }    

    return (uint8_t)((PINB >> pin) & 0x01);
}

更新

这是我的抗议计划。信号来自发电机。频率为1kHz,宽度为50%。 mplmplitude是5伏特。    Proteus scheme

更新

抱歉,这是一个愚蠢的错误。它工作正常。我调试的东西没有按预期工作。

1 个答案:

答案 0 :(得分:1)

我无法找到代码中的问题所在。但这里有一些我可以遵循的调试步骤:

1)引脚总是读什么?逻辑10,可能脉冲电压不够高,因此AVR无法感知它。

2)duration = (TCNT1+overflowCounter*65536 - timestamp)/2;中的乘法占用了大量CPU时间,可能需要比脉冲更多的时间,因此在AVR进入最后while循环之前脉冲变低。当然,这取决于脉冲是连续的还是只有一个脉冲。此外,我不知道你为什么使用timestamp,因为你已经清除了overflowcounter。我想这行应该删除。

<强>更新

为了测量四个信号脉冲,我建议使用PORTB更改中断,当中断发生时,你可以屏蔽端口以查看哪个信号已经改变并计算它的持续时间。