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

Sleep AVR唤醒外部中断,然后立即读取USART,sleep,interrupt,avr,usart,Sleep,Interrupt,Avr,Usart,我在一个奇怪的情况下和一个朋友在一起 我想进入断电模式以节省电能。在这种模式下,只有少数事件可以唤醒它 在USART1上,我有一个向AVR发送消息的外部控制器。 但是当使用USART1时,我不能将INT2和INT3用于外部中断=CPU不会唤醒 因此,我有一个想法,在进入断电模式之前禁用USART1,并将INT2作为外部中断启用 此操作的伪代码: UCSR1B &= ~(1<<RXEN1); //Disable RXEN1: let AVR releasing it DDRD

我在一个奇怪的情况下和一个朋友在一起

我想进入断电模式以节省电能。在这种模式下,只有少数事件可以唤醒它

在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再次正常工作似乎需要很长时间。 从断电状态醒来后,开始时有太多的错误位

这有多骇人? 有什么合理的方法可以让改变更快吗

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


PS:我真的必须使用相同的pin码,没有其他可用选项。因此,不接受使用其他引脚的指导作为答案。

断电模式禁用振荡器,因此您必须在唤醒后等待稳定的振荡器。 请参阅第51页的数据表: 当从断电模式唤醒时,从唤醒状态发生到唤醒生效都会有延迟。这允许时钟重新启动并在停止后变得稳定。wake upperiod由定义复位超时周期的相同CKSEL保险丝定义,如第40页“时钟源”中所述。 假设您使用的是高速陶瓷振荡器,您必须等待258个时钟周期,见第42页的表10-4

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

尽管问题更多的是设置中断错误,但此答案还有一个附加值。