avr睡眠模式并唤醒
我正试图让我的AtTiny 13进入睡眠状态并通过中断将其唤醒。 它确实会睡觉,但它永远不会醒来。 整个代码:
#include #include #include #include #define RED (1<<PB4) #define RED_HIGH PORTB |=RED #define RED_LOW PORTB &= ~RED #define RED_TOG PORTB ^= RED #define BUTTON 1<<PB1 volatile static bool is_sleeping; ISR(INT0_vect) { RED_TOG; is_sleeping = true; } int main(void){ GIMSK |= 1<<INT0; MCUCR |= 0<<ISC00 | 1<<ISC01; sei(); DDRB |= RED; DDRB &= ~BUTTON; PORTB |= BUTTON; RED_HIGH; set_sleep_mode(SLEEP_MODE_PWR_DOWN); while(1){ if(is_sleeping){ sleep_enable(); sei(); sleep_cpu(); sleep_disable(); } } }
根据sleep.h数据,它应该工作。 有任何想法吗?
更新:从IDLE模式唤醒没有问题;
假设没有硬件接线问题,您的代码工作如下:启动后,LED打开,而while循环处于空闲状态,因为is_sleeping
最初设置为零。 第一个INT0中断切换LED(将其关闭)并设置is_sleeping
标志,以便while循环将在下一轮进入保护代码。 该代码使MCU在sleep_mcu()
行上sleep_mcu()
。 一旦INT0中断等待MCU,它将从最后一个位置继续,即它返回睡眠状态,因为仍然设置了is_sleeping
! (并且在您的代码中永远不会变回false)。 这意味着在MCU唤醒后,它几乎立即进入hibernate状态,直到下一个INT0中断为止。
因此,为了回答你的问题它永远不会醒来我会说:它确实醒来但是真的很短暂。 如果您测量电流(例如使用示波器和分流电阻器),您会在醒来时观察尖峰并立即进入睡眠状态。
无论你的主要问题是注重代码质量。 嵌入式编程远非宽容,你可能会因为琐碎的错误而坚持数小时。 例如,总是对宏观定义采取防御措施。 您将BUTTON
定义为1<
DDRB &= ~BUTTON
你没有你期望的。 你的右边表达展开到11111100
(因为~1<<1
是11111110 << 1
)而你想要11111101
(因为~(1<<1)
是~ 00000010
)。 如果你将PB0用于别的东西,你会发现不想要的行为。
此外,在复制示例代码时,请确保您了解它的含义。 sleep.h
的样本依赖于使用sei
和cli
互补。 在你的代码中,你只坚持在循环中重新启动中断,这在这里毫无意义。
编辑:由于您声称唤醒工作在“空闲”模式,然后您的下一个问题是您希望系统通过在MCUCR
(ISC00,ISC01)
为(0,1)
在下降沿唤醒。 请参见数据表第9.2章“注意,识别INT0上的下降沿或上升沿中断需要存在I / O时钟”,而第7.1章中的表表明Clk_I / 0在掉电模式下不存在 。 您唯一的选择是通过在MCUCR
(ISC00,ISC01)
为(0,0)
来使INT0外部中断在低电平触发。