首页 > 解决方案 > AVR wakeup for external interrupt then immediately reading USART

问题描述

I'm in a strange situation with an ATMega2560.

I want to save power by going into PowerDown mode. In this mode there are only a few events only which can wake it up.

On USART1 I have an external controller which sends messages to the AVR. But when USART1 is used I can not use the INT2 and INT3 for external interrupt (=the CPU will not wake up).

So I had an idea to disable the USART1 just right before going into PowerDown mode, and have the INT2 enabled as external interrupt.

Pseudo code for this:

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();

In the ISR of INT2, I change everything back to USART1.

Pseudo:

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

However it seems to take long time until the USART1 is working correctly again. There are too many faulty bits in the beginning (after waking up from PowerDown).

How hackish is this? Is there any reasonable way to make the change faster?

The main idea was to set the 'RX' port to an interrupt which can wake the CPU up then immediately change it back to USART and process it asap.

PS: I really have to use the same pin for this purpose, there is no other available option. So guiding toward using some other pins won't be accepted as an answer.

标签: sleepinterruptavrusart

解决方案


The Power-down mode disables the oscillator, so you have to wait for a stable oscillator after wakeup. Please take a look at the datasheet on page 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.
You have to wait up to 258 clock cykles assuming you use a high speed ceramic oscillator (see table 10-4 on page 42).

You can use the Standby Mode. If you use an external oscillator the CPU enter the Standby Mode, which is identical to Power-down Mode, but the Oscillator isn´t stopped. Furthermore you can set the Power Reduction Register for additional power save options. Another option is to use the Extended Standby Mode, which is identical to the Power-save Mode. This mode disables the oscillator, but the oscillator wakes up in six clock cycles.


推荐阅读