Вопросы от нуба по внешним прерываниям

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 2
Зарегистрирован: Ср авг 27, 2014 22:01:19

Сообщение technonoob »

Добрый день.
Есть несколько вопросов по внешним прерываниям. Использую atmega8535.
1. Почему обработка прерывания не прекращается?
К INT0 через кнопку подключён +5V. Прерывание должно срабатывать по ниспадающему фронту:

Код: Выделить всё

GICR|=(0<<INT1) | (1<<INT0) | (0<<INT2);
MCUCR=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00);
MCUCSR=(0<<ISC2);
GIFR=(0<<INTF1) | (1<<INTF0) | (0<<INTF2); 
Как только напряжение подаётся на микроконтроллер, прерывание начинает выполняться постоянно. Если нажать на кнопку (которая к +5V подключена), то прерывание перестаёт выполняться. Где логика? Настройка регистра MCUCR на другие типы событий ни к чему не приводит.

2. Имеются проблемы с наводками на лапке. Как решить?
Сейчас схема подключена через программатор к компьютеру. Наблюдаю остановку выполнения моего зацикленного прерывания при касании рук к клавиатуре. То же происходит при касании к макетной плате. Была такая же проблема с портами ввода, решилась включением pullup резисторов (pullup же, да?).

Пока всё, спасибо. На всякие случай прикладываю код прошивки. C, CodeVision AVR


main.c
Спойлер

Код: Выделить всё

/*
* InlineController.c
*
* Created: 10.08.2014 20:01:38
*/

#define F_CPU 8000000UL  // 8 MHz

#include <io.h>
#include <delay.h>
#include "semafor.c"

#define MODE_AUTO 0x01
#define MODE_MANUAL 0x02

#define LIGHT_GREEN 0x01
#define LIGHT_RED 0x02

#define BIT(x,n) (((x) >> (n)) & 1)

interrupt [EXT_INT0] void ext_int0_isr(void){
	char oldPort = PORTA;
	PORTA = 0xFF;
    delay_ms(200);
    PORTA = oldPort;
}

void main(void){
	unsigned short int isAutoMode = 1;
    unsigned short int isRedNow = 1;
       
    //SREG|=(1<<7);
	GICR|=(0<<INT1) | (1<<INT0) | (0<<INT2);
    MCUCR=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00);
    MCUCSR=(0<<ISC2);
    GIFR=(0<<INTF1) | (1<<INTF0) | (0<<INTF2);   
	
    

    //вывод
    //отключение подтягивающих резисторов. Без понятия зачем, но работает
    PORTA = 0;
    DDRA = 0xFF;

    //ввод
    //включение подтягивающих резистров. Пока не знаю, что это за хрень, но без него
    //всё работает, как говно
    PORTC = 0xFF;
    DDRC = 0x00;   
    
    #asm("sei")
    
    //инициализируем светофор. Включаем красный свет
    semafor_init();

	
    while(1)
    {
        //если нажата кнопка переключения режима работы
        if (!(PINC & (1<<PINC1))){
            isAutoMode = !isAutoMode;
            //возможно стоит добавить задержку?
            continue;
        }

        //если автоматический режим работы, сделаем переключение на зеленый и обратно
        if(isAutoMode){
            semafor_switch_to_green();
            semafor_switch_to_red();
            continue;
        }else{
			//если нажата кнопка переключения света светофора
            if (!(PINC & (1<<PINC0))){
       			isRedNow = !isRedNow;
                if(isRedNow){
                    semafor_switch_to_green();
                }else{
                    semafor_switch_to_red();
                } 
			}         
                                        
        }
    }
}
semafor.c (для полноты картины)
Спойлер

Код: Выделить всё

void semafor_switch_to_green(){
    //красный и желтый
    PORTA = 0x06;
    delay_ms(2000);
    
    //зеленый горит
    PORTA = 0x01;
    delay_ms(5000);
}

void semafor_switch_to_red(){
    //зеленый мигает        
    PORTA = 0x00;
    delay_ms(500);
    PORTA = 0x01;
    delay_ms(500);
    PORTA = 0x00;
    delay_ms(500);
    PORTA = 0x01;
    delay_ms(500);
    PORTA = 0x00;
    delay_ms(500);
    PORTA = 0x01;
    delay_ms(500);
    PORTA = 0x00;
        
    //желтый горит        
    PORTA = 0x02;
    delay_ms(2000);
        
    //красный горит
    PORTA = 0x04;
    delay_ms(5000);
}

void semafor_init(){
    //красный горит
    PORTA = 0x04;
    delay_ms(5000);
}

Пробовал использовать код из этого сообщения. http://radiokot.ru/forum/viewtopic.php? ... r#p2110148 Такая же реакция, как и раньше.
Реклама
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

Добрый день.
Попробуйте дописать

Код: Выделить всё

DDRD &= ~(1<<2); //PD2 вход(прерывание)
PORTD |= (1<<2); //вкл подтяжка 
то есть вход прерывания на вход и подтяжка вкл. Кнопку через резистор к минусу.
Бороться с помехами внешними резисторами подтяжки и конденсаторы по питанию МК 0,1 мкф.
Реклама
Родился
Сообщения: 2
Зарегистрирован: Ср авг 27, 2014 22:01:19

Сообщение technonoob »

Rtmip писал(а):Бороться с помехами внешними резисторами подтяжки и конденсаторы по питанию МК 0,1 мкф.
Спасибо, заработало. Я делал вот так и очевидно здесь ошибка:

Код: Выделить всё

DDRD = 0xFF;
PORTD = 0xFF;
В чем принципиальная разница в этом случае?

Ещё помехи ушли после задания этих регистров. Трюк с конденсатором работает только для микроконтроллеров (только для atmega?) или это общий приём?
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

Конечно, могли быть наводки(помехи), Вы очевидно, не включив подтяжку нужных Вам пинов порта пытались получать
с них данные(прерывание), но когда вывод висит в воздухе, не подключен никуда(похоже внешних резисторов подтяжки тоже нет)
кроме кнопки, получаете на нем свои помехи(наводки) от чего угодно, которые МК уже может определять как некое событие(прерывание).
Вообще, лучше кнопки или что-то еще подключать и с последовательно включенным резистором, чтобы при случайном замыкании на
плюс или минус не сжечь вывод(порт).
Когда делали "DDRD = 0xFF;" получали настройку порта на выход, в этом разница.
Конденсаторы по питанию нужно ставить во всех схемах с цифровыми микросхемами, как можно ближе к самой микросхеме,
об этом много и подробно написано практически везде :) это "трюк" для всех :)
Реклама
Эиком - электронные компоненты и радиодетали
Ответить

Вернуться в «AVR»