ATTiny 13 выходит из спящего режима

Я пытаюсь перевести свой ATTiny в спящий режим, а затем разбудить его. Я использую этот код, чтобы перевести его в спящий режим:

void go_to_sleep(){
is_sleeping = true;
RED_HIGH;
YELLOW_HIGH;
GREEN_HIGH;
sleep_enable();
sei();
sleep_cpu();
sleep_disable();

}

Затем я использую внешнее прерывание, но ничего не происходит.

ISR(INT0_vect)
{
    if(is_sleeping){
        awake();
    }
    if(BUTTON_LOW){ // przycisk wciśnięty?
        _delay_ms(80);
        if(BUTTON_LOW){ // nadal wciśnięty?
            do_thing();
        }
    }
}
void awake(){
    is_sleeping = false;
    RED_LOW;
    YELLOW_HIGH;
    GREEN_HIGH;
}

Приветствуются любые идеи.

Я добавляю main, чтобы показать, что прерывание работает нормально, я тестировал его без спящего режима:

int main(void)
{
MCUCR |= 1<<SE; // zezwolenie na sleep mode
GIMSK |= 1<<INT0; // int0 enable
MCUCR |= 0<<ISC00 | 1<<ISC01; //przerwanie zboczem opadającym
sei(); // zezwolenie na przerwania

//OUTPUTS
DDRB |= RED | YELLOW  | GREEN;
//INPUTS
DDRB &= ~BUTTON;
// Podciągnięcie przycisku do VCC
PORTB |= BUTTON;

set_sleep_mode(SLEEP_MODE_PWR_DOWN); // ustaw tryb sleep modu, ta linijka nie uruchamia go

//Stan początkowy
RED_LOW;
YELLOW_HIGH;
GREEN_HIGH;

timer0(TIMER_PRESCALER_1024,255);

while(1);
}

person Piotr Konopacki    schedule 13.11.2017    source источник
comment
sei() разве это не код для отключения прерываний? в каком случае внешние прерывания будут замаскированы?   -  person Jean-François Fabre    schedule 13.11.2017
comment
@Jean-FrançoisFabre нет, на AVR прерывания разрешены, когда флаг прерывания установлен (в отличие, например, от 6502, у которого логика противоположна флагу прерывания). См., например. мой рабочий код...   -  person    schedule 13.11.2017
comment
в общем, ваш ISR, вероятно, делает слишком много. В любом случае задержка внутри ISR вызывает проблемы. ISR должны быть максимально короткими и быстрыми, старайтесь только устанавливать (изменчивые) флаги и выполнять работу в основном коде.   -  person    schedule 13.11.2017
comment
@FelixPalmen это инструкция 6502 SEI, которая натолкнула меня на эту идею :)   -  person Jean-François Fabre    schedule 13.11.2017
comment
@ Jean-FrançoisFabre Это известный дефект ядер Atmel. Они заимствовали большую часть своего ассемблера у Motorola, но перепутали смысл инструкций sei и cli. Таким образом, на Atmel sei означает разрешение прерываний, а на ядрах Motorola это означает блокировку всех прерываний. Они инвертировали значение бита I в CCR.   -  person Lundin    schedule 13.11.2017
comment
Что касается того, почему прерывание не работает, вы должны настроить некоторые параметры для этого конкретного аппаратного периферийного устройства (таймер?) и указать ему, что он должен разбудить ЦП. Я не знаю этот конкретный MCU, но обычно так оно и бывает.   -  person Lundin    schedule 13.11.2017


Ответы (2)


Вы должны включить прерывание INT0 в общем регистре маски прерывания.... введите здесь описание изображения

Добавьте строку...

GIMSK |= _BV( PCIE );

... перед тем, как вы заснете, и активация вывода INT0 (по умолчанию с низким уровнем) должна вывести MCU из спящего режима.

Обратите внимание, что с вашим кодом, как показано, я не уверен, что вы сможете сказать, что процессор проснулся. Попробуйте вывести на контакт высокий уровень непосредственно перед сном, а затем, когда вы проснетесь, сделать его низким, чтобы вы знали, что это произошло.

person bigjosh    schedule 13.11.2017
comment
Я использую sei() в основной функции. Разве этого недостаточно? - person Piotr Konopacki; 14.11.2017
comment
sei() делает возможным прерывание, но вы также должны отдельно включить каждый источник прерывания. В вашем случае внешний источник прерывания включается битом INT0 в регистре GIMSK. Другие прерывания разрешены в других местах. - person bigjosh; 14.11.2017

Я полагаю, что вы опубликовали свою проблему с пробуждением от отключения питания режим. Убедитесь, что мой ответ на другой вопрос работает для вас здесь, т. Е. Что вы не можете проснуться после отключения питания с помощью обнаружения заднего фронта на INT0 из-за отсутствия часов ввода-вывода при отключении питания.

person andy    schedule 28.11.2017