AVR 唤醒外部中断然后立即读取 USART
AVR wakeup for external interrupt then immediately reading 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 再次正常工作。
开头错误位太多(掉电唤醒后)
这有多黑?
有什么合理的方法可以让改变更快?
主要想法是将 'RX' 端口设置为中断,可以唤醒 CPU 然后立即将其改回 USART 并尽快处理。
PS:我真的必须为此使用相同的引脚,没有其他可用的选项。因此,指导使用其他一些别针将不会被接受为答案。
Power-down模式禁用振荡器,因此唤醒后必须等待stable振荡器。
请查看第 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 页的 table 10-4
)。
您可以使用待机模式。如果您使用外部振荡器,CPU 会进入待机模式,这与 Power-down 模式相同,但振荡器不会停止。此外,您可以设置 Power Reduction Register
以获得额外的省电选项。
另一种选择是使用扩展待机模式,它与 Power-save 模式相同。此模式禁用振荡器,但振荡器会在六个时钟周期内唤醒。
我遇到了一个 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 再次正常工作。 开头错误位太多(掉电唤醒后)
这有多黑? 有什么合理的方法可以让改变更快?
主要想法是将 'RX' 端口设置为中断,可以唤醒 CPU 然后立即将其改回 USART 并尽快处理。
PS:我真的必须为此使用相同的引脚,没有其他可用的选项。因此,指导使用其他一些别针将不会被接受为答案。
Power-down模式禁用振荡器,因此唤醒后必须等待stable振荡器。
请查看第 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 页的 table 10-4
)。
您可以使用待机模式。如果您使用外部振荡器,CPU 会进入待机模式,这与 Power-down 模式相同,但振荡器不会停止。此外,您可以设置 Power Reduction Register
以获得额外的省电选项。
另一种选择是使用扩展待机模式,它与 Power-save 模式相同。此模式禁用振荡器,但振荡器会在六个时钟周期内唤醒。