реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Прерывание не вызывается повторно
Anub
сообщение Jul 10 2008, 14:20
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 47
Регистрация: 26-05-08
Пользователь №: 37 825



ATMEGA16

Такая вот проблема. Изначально МК находится в спящем режиме, при 0 на int1 вызывается прерывание которые выводит мк из спящего режима, После чего повторно вызвать прерывание не удается. Регистры которые я задавал-
MCUCR - 01100000
GICR - 10000000
При этом int1 становится обычным выводом, т. к. специально написанная тестовая функция показала что так оно и есть. Похоже что я где то чего то не прописал?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2008, 14:49
Сообщение #2


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Anub @ Jul 10 2008, 17:20) *
Похоже что я где то чего то не прописал?

Вы не сказали на чем пишете. Да и код привести было бы не плохо, чтобы не гадать
Go to the top of the page
 
+Quote Post
Anub
сообщение Jul 10 2008, 14:58
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 47
Регистрация: 26-05-08
Пользователь №: 37 825



Цитата(defunct @ Jul 10 2008, 18:49) *
Вы не сказали на чем пишете. Да и код привести было бы не плохо, чтобы не гадать

Пишу на Си, с кодом сложновато, но попробую
Код
//Регистры прерываний записанные в main
GICR=0x80;  
MCUCR=0x60;  
GIFR=0x00;      

// Обработка прерывания
interrupt [EXT_INT1] void ext_int1_isr(void)
{
GICR=0x80;
SREG=0x02;
PORTA=0xFF;
    for (i=0; i<=4; i++)
        {
            SYSCODE[i]=0;
        }
    for (i=0; i<=8; i++)
        {
            CORRECT[i]=0;
        }
    PR=0;
    while(PIND==0xF3){};
    scan();
}
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2008, 15:59
Сообщение #4


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



MCUCR = 0x80; <-- Посмотрите в ДШ флажки ISCxx (врятли вам нужен Level Sensitive int).
GIFR = 0x00; <-- это не обязательно (тем более сброс флагов делается записью "1", а "0" - не имеет никакого эффекта).

SREG=0x02; <--- Уберите это!!

while(PIND==0xF3){}; <-- здесь возможно подвисание.

в остальном все Ок


давайте попробуем Int настроить как Edge Triggered (а не Level Sensitive), и в обработчике просто перевернуть значение порта A.
Код
#define ISC11 3

MCUCR = 0x60 | (1 << ISC11); // int1 on falling edge  (----\int___)
GICR = 0x80;

interrupt [EXT_INT1] void ext_int1_isr(void)
{
    static char x = 0;
    x = ~x;
    PORTA = x;
}
Go to the top of the page
 
+Quote Post
Александр Куличо...
сообщение Jul 10 2008, 18:21
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017



Цитата
Изначально МК находится в спящем режиме

Цитата
давайте попробуем Int настроить как Edge Triggered (а не Level Sensitive)

Edge Triggered по Int0/Int1 разбудит МК только из Idle mode.
Если под спящим режимом подразумевается ADC Noice Reduction, Power Down, PowerSave или Standby Mode, то нужно либо Level Sensitive по Int0/Int1, либо Edge Triggered по Int2.
Кроме того, для того, чтобы после вывода из power done mode в МК выставился флаг прерывания Int1, низкий уровень на пине должен удерживаться до самого старта контроллера (т.е. 2 цикла watchdog'a + время, определяемое fuse-битами SUT). При меньшем времени контроллер "проснется", но прерывание по Int1 не будет выполнено
Цитата
Note that if a level triggered interrupt is used for wake-up from Power-down mode, the changed
level must be held for some time to wake up the MCU. This makes the MCU less sensitive to
noise. The changed level is sampled twice by the Watchdog Oscillator clock. The period of the
Watchdog Oscillator is 1 μs (nominal) at 5.0V and 25°C. The frequency of the Watchdog Oscillator
is voltage dependent as shown in ”Electrical Characteristics” on page 291. The MCU will
wake up if the input has the required level during this sampling or if it is held until the end of the
start-up time. The start-up time is defined by the SUT Fuses as described in ”System Clock and
Clock Options” on page 24. If the level is sampled twice by the Watchdog Oscillator clock but
disappears before the end of the start-up time, the MCU will still wake up, but no interrupt will be
generated
. The required level must be held long enough for the MCU to complete the wake up to
trigger the level interrupt.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2008, 22:10
Сообщение #6


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата
Edge Triggered по Int0/Int1 разбудит МК только из Idle mode.

Извиняюсь, только сейчас заметил, что у автора ветки Power-Down.
Набросал заготовку (WinAVR) для выхода из PowerDown и входа обратно через idle (если 0 будет держаться долго) и проверил на STK500:
Проверял с внутренним осциллятором 8Mhz и 1Mhz, а также с внешним клоком. С тактированием от кварца не проверял.

Код
#include <avr/io.h>
#include <avr/interrupt.h>


// вводит MK в PowerDown режим
void EnterPowerDown(void)
{
    MCUCR = (1 << SE) | (1 << SM1); // int1 level sensitive + power-down
    GICR = (1 << INT1);
    asm("sleep");
}


// вводит МК в idle режим, пока INT1 в нуле.
void WaitOnInt1ToGetHigh(void)
{
    if (PIND & (1 << PD3)) // INT1 high?
    {    // the level already high, no need to go idle
        return;
    }

    MCUCR = (1 << SE) | (1 << ISC11) | (1 << ISC10); // int1 on rising edge + idle
    GICR = (1 << INT1);
    asm("sleep");
}


void main(void)
{

    sei();

    DDRB = 0xFF;

    for(;;)
    {
        EnterPowerDown();

        // since we got here the device has woke up from power down
        // do all necessary tasks here

        PORTB += 1; // на порту B висят светодиоды;>
    
        // since there is no more tasks to do, lets prepare to power down
        WaitOnInt1ToGetHigh(); // <-- move MCU to idle mode until INT1 level rises
        
        // TODO: добавить небольшую задержку перед входом в power down для пресечения дребезга.
    }

}

// обработчик прерывания
SIGNAL (INT1_vect)
{
    MCUCR = (1 << ISC11) | (1 << ISC10); // int on rising edge, disable sleep mode
    GICR &= (1 << INT1); // mask int1 while we got a tasks to do in background
}
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 14:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01408 секунд с 7
ELECTRONIX ©2004-2016