如何在2秒后使用计时器关闭数字输出

时间:2018-12-01 14:32:25

标签: timer interrupt avr atmega

我有一个Atmega328p,想通过按一下按钮打开数字输出,然后在2秒钟后自动关闭它。

我知道如何为按钮使用硬件中断,但是如何设置计时器中断以自动关闭数字输出呢?


更新:

我能够弄清楚。这是我的解决方案(仅显示相关功能):

static inline void initTimer1(void) {

    TCCR1B |= (1 << WGM12);  // CTC Mode, immediate
    TCCR1B |= (1 << CS10) | (1 << CS12);  // Clock speed: 16 MHz / 1024, ~= 15.6 ticks per ms

}

void set_valve_on_time(uint16_t on_time) {

    OCR1A = on_time;  // set output compare register for valve on time

}

void open_valve(uint8_t state) {

    if (state > 0) {
        PORTD |= (1 << PIND6);  //turn on PD6, open valve
        PORTD &= ~(1 << PIND7);  //turn off PD7, turn off close valve in case it was on
        if (state == 2) {
            TCNT1 = 0;
            TIFR1 |= (1 << OCF1A);  // clear output compare match flag
            TIMSK1 |= (1 << OCIE1A);  // enable output compare interrupt
        }
    }
    else {
        PORTD &= ~(1 << PIND6);  //turn off PD6, stop opening valve
    }   

}

ISR(TIMER1_COMPA_vect) {

    TIMSK1 &= ~(1 << OCIE1A);  // disable output compare interrupt
    open_valve(0);  //turn off close valve output

}

通过按下按钮(未显示)调用open_valve函数。我最难的时刻是弄清楚我需要TIFR1 |= (1 << OCF1A)才能正常工作。我仍然不太清楚为什么,因为我认为ISR应该自动执行此操作。

1 个答案:

答案 0 :(得分:0)

您必须大致遵循以下步骤:

  • 在按钮处理例程中,使用以下属性设置计时器:
    • 在CTC模式下最好使用16位计时器(如果您有可用的免费计时器)
    • 设置预分频器,以使计时器otherflow比您的比较值慢一点:
      在2秒和10MHz的CPU频率下,我将在1/1024预分频器上运行它,因此,在(10.000.000 / 1024/65536)上会发生溢出->每6.7s发生1次溢出(265溢出的次数会超过一次每2秒)
    • 将ctc最高值(请参见所选模式的说明-具体寄存器有所不同)设置为2s之后达到的值:10.000.000 / 1024 * 2s-> 19531
  • 实施ISR(请参阅在选定的CTC模式中哪一个是正确的),并激活掩码寄存器中的Interupt
    • 在ISR中设置您的输出,并停止计时器
  • 奖金:设置计时器,使其使用输出比较引脚来停用输出
    然后完全不需要ISR,只需将比较输出模式设置为“匹配时清除”即可。

如果您没有免费的16位计时器,我建议在CTC模式下使用1个计时器来生成(10)毫秒的时基,并在此ms事件处理中实现时间计数逻辑。