У меня странная ситуация с ATMega2560.
Я хочу сэкономить электроэнергию, перейдя в режим PowerDown. В этом режиме есть только несколько событий, которые могут разбудить его.
На USART1 у меня есть внешний контроллер, который отправляет сообщения на AVR. Но когда используется USART1, я не могу использовать INT2 и INT3 для внешнего прерывания (= ЦП не просыпается).
Так что у меня возникла идея отключить USART1 прямо перед переходом в режим PowerDown и включить 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();
В ISR INT2 меняю все обратно на 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 на прерывание, которое может разбудить ЦП, а затем немедленно изменить его обратно на USART и обработать его как можно скорее.
PS: Мне действительно нужно использовать для этой цели тот же пин, другого доступного варианта нет. Так что указание на использование других контактов не будет принято в качестве ответа.