通过AVR唤醒外部中断,然后立即读取USART

时间:2019-07-07 20:20:19

标签: sleep interrupt avr usart

我遇到一个ATMega2560的奇怪情况。

我想通过进入PowerDown模式来节省电量。在这种模式下,只有少数事件可以唤醒它。

在USART1上,我有一个外部控制器,该控制器将消息发送到AVR。 但是当使用USART1时,我不能使用INT2和INT3进行外部中断(= CPU不会唤醒)。

所以我有一个主意,就是在进入掉电模式之前立即禁用USART1,并启用INT2作为外部中断。

伪代码:

UCSR1B &= ~(1<<RXEN1); //Disable RXEN1: let AVR releasing it
DDRD &= ~(1<<PD2); //Make sure PortD2 is an input - we need it for waking up
EIMSK &= ~(1<<INT2); //Disable INT2 - this needs to be done before changing ISC20 and ISC221
EICRA |= (1<<ISC20)|(1<<ISC21); //Rising edge on PortD2 will generate an interrupt and wake up the AVR from PowerDown
EIMSK |= (1<<INT2); //Now enable INT2

//Sleep routine
cli();
sleep_enable();
sei();
sleep_cpu();
sleep_disable();

在INT2的ISR中,我将所有内容都更改回USART1。

伪:

ISR(INT2_vect) {
  EIMSK &= ~(1<<INT2); //Disable INT2 to be able to use it as USART1 again
  UCSR1B=(1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);
}

但是,似乎要花很长时间才能使USART1再次正常工作。 (从PowerDown唤醒后)开始时有太多错误位。

这是多么骇人听闻? 有什么合理的方法可以使更改更快?

主要思想是将“ RX”端口设置为可以唤醒CPU的中断,然后立即将其改回USART并尽快对其进行处理。

PS:为此,我确实必须使用相同的引脚,没有其他可用的选项。因此,不能将使用其他别针的指导作为答案。

1 个答案:

答案 0 :(得分:1)

掉电模式禁用振荡器,因此唤醒后必须等待稳定的振荡器。 请查看第51页的数据表:
When waking up from Power-down mode, there is a delay from the wake-up condition occurs until the wake-upbecomes effective. This allows the clock to restart and become stable after having been stopped. The wake-upperiod is defined by the same CKSEL Fuses that define the Reset Time-out period, as described in “ClockSources” on page 40.
假设您使用高速陶瓷振荡器,则您必须等待258个时钟周期(请参阅第42页的表10-4)。

您可以使用待机模式。如果使用外部振荡器,则CPU进入待机模式,该模式与掉电模式相同,但振荡器不会停止。此外,您可以将Power Reduction Register设置为其他节电选项。 另一种选择是使用扩展待机模式,该模式与省电模式相同。此模式禁用振荡器,但振荡器会在六个时钟周期内唤醒。