1

我想测量脉冲持续时间,但我需要测量 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);
}

更新

那是我的proteus方案。信号来自发生器。频率为 1kHz,宽度为 50%。幅度为 5 伏。 变形虫方案

更新

对不起,那是一个愚蠢的错误。它工作正常。调试我没有按预期工作的东西。

4

1 回答 1

1

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

1)引脚总是读什么?逻辑1或者0,也许脉冲电压不够高,所以 AVR 无法感应到它。

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

更新

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

于 2015-09-06T10:41:08.353 回答