timer - 如何使用定时器在 2 秒后关闭数字输出
问题描述
我有一个 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 应该自动执行此操作。
解决方案
您必须大致遵循以下步骤:
- 在您的按钮处理例程中设置具有以下属性的计时器:
- 在 CTC 模式下最好使用 16 位定时器(如果你有可用的空闲定时器)
- 设置预分频器,使定时器的其他流比您的比较值慢一点:
对于 2 秒和 10MHz CPU 频率,我将在 1/1024 预分频器上运行它,因此在 (10.000.000/1024/65536) -> 上会发生溢出每约 6.7 秒 1 次溢出(265 次溢出比每 2 秒更频繁) - 将 ctc 最高值(请参阅所选模式的说明 - 特定寄存器会有所不同)设置为 2s 后达到的值:10.000.000/1024 * 2s --> 19531
- 实施 ISR(查看在所选 CTC 模式下哪个是正确的)并激活屏蔽寄存器中的中断
- 在 ISR 中设置你的输出,并停止计时器
- 奖励:设置它使用输出比较引脚来停用输出的定时器
然后根本不需要 ISR,只需将比较输出模式设置为“匹配时清除”
如果您没有可用的 16 位定时器,我建议在 CTC 模式下使用 1 个定时器来生成(10)毫秒时基,并在此 ms 事件处理中实现时间计数逻辑。