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<而没有parens。 不同之处在于,您会受到运营商优先级的影响。 例如,使用DDRB &= ~BUTTON你没有你期望的。 你的右边表达展开到11111100 (因为~1<<111111110 << 1 )而你想要11111101 (因为~(1<<1)~ 00000010 )。 如果你将PB0用于别的东西,你会发现不想要的行为。

此外,在复制示例代码时,请确保您了解它的含义。 sleep.h的样本依赖于使用seicli互补。 在你的代码中,你只坚持在循环中重新启动中断,这在这里毫无意义。

编辑:由于您声称唤醒工作在“空闲”模式,然后您的下一个问题是您希望系统通过在MCUCR (ISC00,ISC01)(0,1)在下降沿唤醒。 请参见数据表第9.2章“注意,识别INT0上的下降沿或上升沿中断需要存在I / O时钟”,而第7.1章中的表表明Clk_I / 0在掉电模式下不存在 。 您唯一的选择是通过在MCUCR (ISC00,ISC01)(0,0)来使INT0外部中断在低电平触发。