Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Внешнии прерывания atmega8L
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
failguru
Прописал прерывание по спаду на INT0, а оно вызывается два раза подрят, причем когда отсоединяю землю еще два раза, пробовал и высокий уровень через 5кОм, и задержку менять, ничего не помогает(((( пишет подряд две "G"
Код
#include <io.h>
#include <delay.h>
extern void wrlcd(int rsi, int rwi, int arg);
extern void initlcd();
int i=0;
char fl=1;
interrupt [EXT_INT0] int_0(void){
     wrlcd(1,0,(int)'G');
    delay_ms(200);
}
void main(){
    delay_ms(100);
    initlcd();
        wrlcd(1,0,(int)'E');
        wrlcd(1,0,(int)'C');
        DDRD.2=0;               //порт с INT0 на вход
        PORTD.2=1;              //подтяжка
        MCUCR=0b00000010;       //прерывание по спаду
        GICR=0b01000000;        //врубаю INT0
        #asm("sei")
        while(1){
            delay_ms(200);
        }
}

ХЭЛП
aaarrr
Цитата(failguru @ Nov 10 2011, 01:05) *
оно вызывается два раза подрят, причем когда отсоединяю землю еще два раза

Так дребезг, наверное.
failguru
ничесе дребезг) задержка 200милисек!!!
aaarrr
Цитата(failguru @ Nov 10 2011, 01:10) *
ничесе дребезг) задержка 200милисек!!!

А толку-то в этой задержке? Фронт ловится снова во время выполнения прерывания.
failguru
что делать? как же кнопки делают на INT0 INT1 wacko.gif
x736C
Таймаут по таймеру и маскирование прерываний INT0, INT1.
aaarrr
Цитата(failguru @ Nov 10 2011, 01:20) *
что делать? как же кнопки делают на INT0 INT1 wacko.gif

Для кнопок совсем не нужны INTx, если только они не служат для пробуждения процессора из спячки. Обычно кнопки опрашиваются по таймеру с программным антидребезгом.
ILYAUL
Цитата(aaarrr @ Nov 10 2011, 01:48) *
Для кнопок совсем не нужны INTx, если только они не служат для пробуждения процессора из спячки.

И в таком случае используют только одно из Х INT прерываний суммируя сигналы со всех кнопок.
failguru
Цитата
Таймаут по таймеру и маскирование прерываний INT0, INT1.

если под маскированием подразумевается вставка cli и sei в начало и в конец функции обработчика прерываний то не помогает, а что таймаут по таймеру даст?
ILYAUL
Цитата(failguru @ Nov 10 2011, 11:53) *
если под маскированием подразумевается вставка cli и sei в начало и в конец функции обработчика прерываний то не помогает, а что таймаут по таймеру даст?


Это не предметно - код в студию
failguru
Код
#include <io.h>
#include <delay.h>
extern void wrlcd(int rsi, int rwi, int arg);
extern void initlcd();
int i=0;
char fl=1;
interrupt [EXT_INT0] int_0(void){
     wrlcd(1,0,(int)'G');
    delay_ms(200);
}
void main(){
    delay_ms(100);
    initlcd();
        wrlcd(1,0,(int)'E');
        wrlcd(1,0,(int)'C');
        DDRD.2=0;               //порт с INT0 на вход
        PORTD.2=1;              //подтяжка
        MCUCR=0b00000010;       //прерывание по спаду
        GICR=0b01000000;        //врубаю INT0
        #asm("sei")
        while(1){
            delay_ms(200);
        }
}
Палыч
Дребезг контактов можно подавить двумя способами;
1. Аппаратный - поставить RS-триггер. Вероятно, не хотите ставить...
2. Программный. В этом случае необходимо после первого изменения состояния кнопки не реагировать на её изменение в течении некоторого времени, большего чем время дребезга (обычно, для этого задействуют таймер).

В Вашем случае:
1. При входе в процедуру прерывания нужно запретить прерывания от INT.
2. Запустить таймер на время Т, большее чем время дребезга.
3. Перед выходом из процедуры прерывания по INT сбросить флаг прерывания по INT.
4. При истечении времени Т (прерывания от таймера) настроить прерывания по INT для фиксации последующих нажатий кнопки; остановить таймер.

P.S. Описанное выше Вам рекомендавал x736C в сообщении #6
rx3apf
Цитата(Палыч @ Nov 10 2011, 14:11) *
3. Перед выходом из процедуры прерывания по INT сбросить флаг прерывания по INT.

Не нужно - прерывания от INT будут запрещены, поэтому повторного вызова не произойдет.
Цитата
4. При истечении времени Т (прерывания от таймера) настроить прерывания по INT для фиксации последующих нажатий кнопки; остановить таймер.

А вот тут-то нужно сбросить прерывание от INT, поскольку при дребезге флаг прерывания уже установлен и только дожидается, чтобы прерывания разрешили...
failguru
да, в этом дело похоже, что дожидается. а как сбросить?
aaarrr
Цитата(Палыч @ Nov 10 2011, 14:11) *
2. Программный. В этом случае необходимо после первого изменения состояния кнопки не реагировать на её изменение в течении некоторого времени, большего чем время дребезга (обычно, для этого задействуют таймер).

Лучше фиксировать не первое попавшееся изменение, а стабильность уровня сигнала кнопки в течение промежутка времени, превышающего время дребезга.
rx3apf
Цитата(failguru @ Nov 10 2011, 16:46) *
да, в этом дело похоже, что дожидается. а как сбросить?

Записью "1" в соответствующий бит GIFR. Чтение даташитов - за отдельную плату wink.gif
failguru
Вот в таком варианте работает. Странно почему надо устанавливать флаг в GIFR. Типо он думает что еще обрабатывается прошлое прерывание)
Остался один вопрос. Когда убираешь землю, мол фронт возрастает, а он все равно прерывание вызывает. Тоже дребезг??? И как исправить.

Код
interrupt [EXT_INT0] int_0(void){
    GICR=0x00;
    wrlcd(1,0,(int)'G');
    TCNT0=0;
    TCCR0=0b00000101;                  //включаю счетчик с делителем 1024 (1/(8мГц/1024)*256=0.033 секунды переполнение)
}
interrupt [TIM0_OVF] void tin(void) {
    i++;
    if(i==30){                        //проходит примерно секунда!!!!!!
        GIFR=0b01000000;               //устанавливаю флаг
        GICR=0b01000000;               //включаю опять внешнее прерывание
        TCCR0=0x00;                    //торможу счетчик
        i=0;
    }
}
void main(){
    delay_ms(100);
    initlcd();
        wrlcd(1,0,(int)'E');
        DDRD.2=0;               //порт с INT0 на вход
        PORTD.2=1;              //подтяжка
        TIMSK=0b00000001;
        MCUCR=0b00000010;       //прерывание по спаду
        GICR=0b01000000;        //врубаю INT0
        #asm("sei")
        while(1){
            delay_ms(500);
        }
}
rx3apf
Цитата(failguru @ Nov 10 2011, 17:31) *
Два раза пишет все равно с таймером!!!!!!!!!!!!!!!

Прочитайте написанное выше ВНИМАТЕЛЬНО.
failguru
уже два раза не пишет, все ок. теперь осталось только когда отжимаю кнопку срабатывает, а не должен
ILYAUL
Цитата(failguru @ Nov 10 2011, 17:54) *
уже два раза не пишет, все ок. теперь осталось только когда отжимаю кнопку срабатывает, а не должен


Как при нажатии так и отпускании кнопки - есть дребезг. Остальное Вы уже знаете
rx3apf
Цитата(failguru @ Nov 10 2011, 17:31) *
Вот в таком варианте работает. Странно почему надо устанавливать флаг в GIFR. Типо он думает что еще обрабатывается прошлое прерывание)

Если что-то кажется странным - прочитайте даташит.
Палыч
Цитата(rx3apf @ Nov 10 2011, 14:21) *
Не нужно - прерывания от INT будут запрещены, поэтому повторного вызова не произойдет.
При дребезге условие прерывания может возникнуть в интервал времени от входа в прерывание до запрещения этого прерывания, поэтому сбросить флаг всё-таки нужно.

Цитата(rx3apf @ Nov 10 2011, 14:21) *
А вот тут-то нужно сбросить прерывание от INT, поскольку при дребезге флаг прерывания уже установлен и только дожидается, чтобы прерывания разрешили...
Естественно. При инициализации большинства устройств желательно сбрасывать флаги - мало ли что было на входах до этого...

Цитата(aaarrr @ Nov 10 2011, 16:52) *
Лучше фиксировать не первое попавшееся изменение, а стабильность уровня сигнала кнопки в течение промежутка времени, превышающего время дребезга.

Не всегда это лучше. Пример: "ручная" синхронизация времени устройств, когда важно уловить "начало" нажатия на кнопку.
aaarrr
Цитата(Палыч @ Nov 10 2011, 20:03) *
Не всегда это лучше. Пример: "ручная" синхронизация времени устройств, когда важно уловить "начало" нажатия на кнопку.

На кнопку нажимает спринтер Болт? Или у нее дребезг 0.5с?
rx3apf
Цитата(Палыч @ Nov 10 2011, 20:03) *
При дребезге условие прерывания может возникнуть в интервал времени от входа в прерывание до запрещения этого прерывания, поэтому сбросить флаг всё-таки нужно.

Оно же не может произойти рекурсивно ? Мы вошли в обработчик прерывания, ну получили еще одно (флаг выставился), но запрещаем-то перед выходом из обработчика. А раз прерывание запрещено - то повторного вызова обработчика не будет.


Цитата(aaarrr @ Nov 10 2011, 20:08) *
На кнопку нажимает спринтер Болт? Или у нее дребезг 0.5с?

Кнопки разные бывают, частота опроса тоже может быть весьма разной. Вполне можно представить ситуацию, когда и десяток mS критичен.
Палыч
Цитата(aaarrr @ Nov 10 2011, 20:08) *
Или у нее дребезг 0.5с?
Пару-тройку лет назад мне попались внешне очень привлекательные китайские кнопки со временем дребезга более 120 мс.

Цитата(aaarrr @ Nov 10 2011, 20:08) *
На кнопку нажимает спринтер Болт?
Бывает, что момент наезда механизма на концевик нужно зафиксировать поточнее...
ILYAUL
Цитата(Палыч @ Nov 10 2011, 20:26) *
Бывает, что момент наезда механизма на концевик нужно зафиксировать поточнее...

Тогда уж АЦП - время принятия решения ~ 27ms (и достаточно надёжно - сбоев замечено не было) , но ведь можно и меньше или больше .
aaarrr
Цитата(Палыч @ Nov 10 2011, 20:26) *
Пару-тройку лет назад мне попались внешне очень привлекательные китайские кнопки со временем дребезга более 120 мс.

И мне попадались. Точнее, не мне - клиенту понравились. Дрянь редкостная, да ведь не объяснишь sad.gif Но это все же исключение.

Цитата(Палыч @ Nov 10 2011, 20:26) *
Бывает, что момент наезда механизма на концевик нужно зафиксировать поточнее...

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