Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: прерывание INT1 затык
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
customizer
Здравствуйте!Помогите разобраться.
Микроконтроллер ATmega88v
Схема: к выводу PD3 подтянут плюс питания через резистор 10к, подключена кнопка на землю.
К выводу PB0 подключен светодиод.
Тактируется от внутреннего генератора.
Код проверяю на железке.
Вот кодок.
Код
#include<ioavr.h>
#include<intrinsics.h>

volatile unsigned char x = 0;
int main(void)
{
  DDRD = (1 <<DDD0)|(1 <<DDD1)|(1 <<DDD2)|(0 <<DDD3)|(1 <<DDD4)|(1 <<DDD5)|(1 <<DDD6)|(1 <<DDD7);
  DDRB = 255;
  PORTD = (0 << PD0)|(0 << PD1)|(0 << PD2)|(1 << PD3)|(0 << PD4)|(0 << PD5)|(0 << PD6)|(0 << PD7);
  PORTB = 0;
  EICRA = (0<<ISC11) | (0<<ISC10);    // Select low  lewel on INT1
  EIMSK  = (1<<INT1) |  (0<<INT0);    // Enable  INT1 interrupts
  SMCR = (0 << SM2)|(1 << SM1)|(0 << SM0)|(0 << SE);// power down
  
  __enable_interrupt();
  
  while(1)
  {
    if(x)
    {
      PORTB = 1;
      __delay_cycles(800000);
      __delay_cycles(800000);
      __delay_cycles(800000);
      PORTB = 0;
    }
    EIMSK = (1<<INT1)|(0<<INT0);
    DDRD = 0;
    PORTD = (0 << PIND0)|(0 << PIND1)|(0 << PIND2)|(1 << PIND3)|(0 << PIND4)|(0 << PIND5)|(0 << PIND6)|(0 << PIND7);
    DDRB = 0;
    PORTB = 0;
    x = 0;
    SMCR |= (1<<SE);
    __sleep();
    SMCR |= (0<<SE);
    DDRD = (1 <<DDD0)|(1 <<DDD1)|(1 <<DDD2)|(0 <<DDD3)|(1 <<DDD4)|(1 <<DDD5)|(1 <<DDD6)|(1 <<DDD7);
    DDRB = 255;
    PORTD = (0 << PD0)|(0 << PD1)|(0 << PD2)|(1 << PD3)|(0 << PD4)|(0 << PD5)|(0 << PD6)|(0 << PD7);
    PORTB = 0;
  }
}


#pragma  vector = INT1_vect
__interrupt void INT1_vect_INT(void)
{
  EIMSK = (0<<INT1)|(0<<INT0);
  x = 1;
}


Прерывание отрабатывается как надо, засыпает просыпается, все супер, НО если в то время когда светодиод горит нажать повторно кнопку,
и дождаться когда микроконтроллер уснет, отпустить кнопку, все , не реагирует ,только reset помогает.
DpInRock
Уберите физически светодиод.
sKWO
Попробуйте так
Код
if(x)
    {
      x = 0;
      PORTB = 1;
      __delay_cycles(800000);
      __delay_cycles(800000);
      __delay_cycles(800000);
      PORTB = 0;
    }

customizer
Нет sKWO, не работает.
Пока что я сделал так, перед тем как отправить мк в сон
Код
while((PIND&(1 << PD3)) == 0)
      {}

Но это не выход.
Если светодиод погаснет,а на выводе PD3 будет низкий уровень, прога так и будет в нем крутиться ,ожидая высокий уровень.
В спящий режим мк не уйдет, ток будет высокий, батарейка разрядится.
DpInRock,я так понял вы предлагаете убрать светодиод и померить уровень на выводе?Померить не могу тестера нет, а в чем соль?
.
DpInRock
Уберите светодиод. Сообщите об изменениях (если они будут).
customizer
Отключил светодиод,нажал на кнопку ,подождал пока уснет, подключил светодиод,нажал на кнопку ,без изменений.
К сожалению я даже ток потребления не могу померить.
xemul
Цитата(customizer @ Aug 21 2010, 14:24) *
Прерывание отрабатывается как надо, засыпает просыпается, все супер, НО если в то время когда светодиод горит нажать повторно кнопку,
и дождаться когда микроконтроллер уснет, отпустить кнопку, все , не реагирует ,только reset помогает.

Сделайте нормальную обработку дребезга кнопки (по таймеру).
Т.к. INT1 нужен только для просыпания, разрешайте его непосредственно перед __sleep() и запрещайте сразу после просыпания (в __interrupt void INT1_vect_INT()). А таймер, наоборот, запрещайте перед __sleep() и разрешайте после просыпания.
GetSmart
Возможно может помочь перенастройка функции срабатывания INT1, то есть переключение её на фронты и сразу же обратно прямо перед засыпанием. Если в проце есть глюк/фича, то её обычно так можно обойти.
customizer
С фронтами тоже не получилось, буду делать по таймеру.Я думаю эта фича такая.
customizer
Все разгадал!!!
Если кнопка остается нажатой после выполнения этого кода
Код
if(x)
    {
      PORTB = 1;
      __delay_cycles(800000);
      __delay_cycles(800000);
      __delay_cycles(800000);
      PORTB = 0;
    }
EIMSK = (1<<INT1)|(0<<INT0);//<--- этого кода

Происходит прерывание

Код
#pragma  vector = INT1_vect
__interrupt void INT1_vect_INT(void)
{
  EIMSK = (0<<INT1)|(0<<INT0);
  x = 1;
}

В обработчике прерываний прерывания от INT1 запрещается, далее
Код
    DDRD = 0;
    PORTD = (0 << PIND0)|(0 << PIND1)|(0 << PIND2)|(1 << PIND3)|(0 << PIND4)|(0 << PIND5)|(0 << PIND6)|(0 << PIND7);
    DDRB = 0;
    PORTB = 0;
    x = 0;
    SMCR |= (1<<SE);
    __sleep();// <-- И в __sleep(); микроконтроллер уходит с запрещенным прерыванием по INT1

И в __sleep(); микроконтроллер уходит с запрещенным прерыванием по INT1
Все.
Всем спасибо за помощь!
08.gif


Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.