繁体   English   中英

AVR睡眠模式并唤醒

[英]avr sleep mode and wake up

我试图让我的AtTiny 13进入睡眠状态,并通过中断将其唤醒。 它确实会入睡,但它永远不会醒来。 整个代码:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <avr/sleep.h>

#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指示灯打开,而is_sleeping最初设置为零,则while循环处于空闲is_sleeping 第一个INT0中断触发LED(将其关闭)并设置is_sleeping标志,以便while循环将在下一个回合中进入受保护的代码。 该代码使MCU在sleep_mcu()行上进入睡眠状态。 一旦INT0中断等待MCU,它将从最后一个位置继续执行,即因为is_sleeping仍被设置,所以is_sleeping返回睡眠状态! (并且在您的代码中永远都不会变回false)。 这意味着MCU唤醒后,它几乎立即进入睡眠状态,直到下一个INT0中断都将关闭。

因此,要回答您的问题, 它永远不会醒来,我会说:它确实醒了,但时间很短。 如果测量电流(例如,使用示波器和分流电阻器),则在唤醒并立即进入睡眠状态时会观察到尖峰。

不管您遇到什么主要问题,都要注意代码质量。 嵌入式编程远非宽容,您可能会因琐碎的错误而停留数小时。 例如,始终对宏定义保持防御。 您将BUTTON定义为1<<PB1不带括号。 区别在于,稍后您会受到运算符优先级的打击。 例如,使用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外部中断在低电平触发。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM