Не работает прерывание

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Здасте Всем :) Пишу программу для ATmega16A. При нажатии на кнопочку (INT0) должно измениться направление движения огонька светодиодика. Вот код

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

#include "avr/io.h"  //
#include<avr/interrupt.h>
#include<avr/boot.h>

#define F_CPU 1000000UL // 1MHz
#include <util/delay.h>

char trig = 1;
char a = 1;

ISR(INT0_vect) // прерывание по вектору INT0
{
	trig = (~trig) & 1; // если кнопка нажата меняем направление движения огонька
}


int main(void)
{
	
	SREG = 128;
	GICR |= _BV(INT0);
	
	DDRA = 0;		// порт A на ввод
	PORTA = 0xFF;   // подтянуть внутренние резисторы
	
	DDRB = 0;		// порт B на ввод
	PORTB = 0xFF;	// подтянуть внутренние резисторы
	
	DDRD = 0;		// порт D на ввод
	PORTD = 0xFF;	// подтянуть внутренние резисторы
	
	DDRC = 0xFF;	// порт C на вывод
	PORTC = 0xFF;	// потушить светодиоды
	
	while(1)
	{
		
		//_delay_ms(100);
		
		if (trig) // усли кнопка не надата работаем
		{
			if (a)
			{
				a = a << 1;
			}
			else
			{
				a = 1;
			}
		}
		else // если нажата кнопка то trig изменит своё значение и движение огонька изменится
		{
			if(a)
			{
				a = a >> 1;
			}
			else
			{
				a = 128;
			}
		}
	}
}
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Да, так вот.. Прерывание не происходит, хотя что я уже ни делал. И ещё, странно себя ведут циклы. Они почему то с первого раза не видят, что переменные "trig" и "a" больше 0 и при моделировании при проходе первый раз циклы считают, что эти переменные не "1" а "0" ничего не понимаю :dont_know:

P.S. Моделировал в AtmelStudio6.
Последний раз редактировалось Грендайзер Пт фев 07, 2014 12:19:37, всего редактировалось 1 раз.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Попробуйте объявить char trig = 1; как volatile char trig = 1;

Так, и ещё разрешить глобально прерывания функцией sei();
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Скажите, а выражение

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

ISR(INT0_vect) // прерывание по вектору INT0
{
   trig = (~trig) & 1; // если кнопка нажата меняем направление движения огонька
}
разве не должно само по себе всё организовать... В примерах которые я смотрел, никто в ручную глоб. прерывания не выставлял...
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Это выражение только лишь определяет нужный вектор и вставляет в него переход на подпрограмму-обработчик. А вот флаг I нужно выставлять при инициализации вручную. Примеры без этого "в студию". (выставить этот флаг можно не только командой SEI, но и записью 1 в соответствующий бит SREG или непосредственно вызовом любого обработчика прерывания, но это хитрое хакерство)
Последний раз редактировалось Engineer_Keen Пт фев 07, 2014 13:12:53, всего редактировалось 2 раза.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

Надо включить глобально прерывания.
Контактная информация:
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Engineer_Keen писал(а):Это выражение только лишь определяет нужный вектор и вставляет в него переход на подпрограмму-обработчик. А вот флаг I нужно выставлять при инициализации вручную. Примеры без этого "в студию".
Опаньки, не доглядел, команда sei() и впрямь есть. Моя вина. Пример же вот
http://www.avr-tutorials.com/interrupts ... rogramming

Что же касается работы, всёравно ничерта не выходит. Прерывание не выполняется, циклы один хрен ничё не видят. Компилято правда такое вот сообщение выдаёт:
Целевой объект "PreBuildEvent" пропущен из-за невыполненного условия; выражение ('$(PreBuildEvent)'!='') равно (''!='').
Может студия криво встала. Дома у меня стоит AVRStudio 4.19. Так на ней циклы себя нормально вели.

Прошу прощения, моя вина. Не правильно интерпритировал действия отладчика. Он почему то как то не совсем ясно указывает на текущий выполняемый оператор (стрелка как то слишком шустро прыгает в какие то непонятные места). Это что касается циклов. Что же касается прерывания то оно работает почему то по спадающему фронту, хотя должно (если верить даташиту) если нога в нуле.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Для ATMega16 тип срабатывания прерывания зависит от битов ICS01 и ICS00 регистра MCUCR
00 - по низкому уровню (по умолчанию)
01 - по любому изменению фронта
10 - по спаду
11 - по фронту

В принципе, особой разницы между 00 и 10 я как-то не вижу.

Опять же, повторюсь по поводу объявления trig как volatile. Без этого оптимизатор компилятора может в основном цикле просто оптимизировать trig, не учтя возможных изменений этой переменной в функции прерывания, которая напрямую в main не вызывается, и оптимизатор не подозревает о том, что что-то может изменить её "в другом потоке".
volatile как раз запрещает компилятору как-либо оптимизировать переменную.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

WiseLord писал(а):В принципе, особой разницы между 00 и 10 я как-то не вижу.
Если закоротить ногу на землю, то в первом случае прерывание будет вызываться постоянно - пока нога на земле, а во втором один раз.
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

WiseLord писал(а):Для ATMega16 тип срабатывания прерывания зависит от битов ICS01 и ICS00 регистра MCUCR
00 - по низкому уровню (по умолчанию)
01 - по любому изменению фронта
10 - по спаду
11 - по фронту

В принципе, особой разницы между 00 и 10 я как-то не вижу.
Ну на мой взгляд 00 - это когда я нажал кнопку и процессор не сможет вернуться к выполнению основной программы пока я кнопку не отпущу. Он вышел из прерывания и сразу в него вернклся...
А вот 10 это уже проверка фронта. Т.е. нажал я процессор отработал прерывание и опять к выполнению основной программы. Так вот 00 - это по умолчанию, а уменя по умолчанию даже не по спадающему фронту, а по обоим фронтам моделировать начал, лишь после того как я явно указал MCUCR = 0 симмулятор начал срабатывать... по спадающему фронту :shock: :evil: Вообщем вечерком проверю в железке...
WiseLord писал(а): Опять же, повторюсь по поводу объявления trig как volatile. Без этого оптимизатор компилятора может в основном цикле просто оптимизировать trig, не учтя возможных изменений этой переменной в функции прерывания, которая напрямую в main не вызывается, и оптимизатор не подозревает о том, что что-то может изменить её "в другом потоке".
volatile как раз запрещает компилятору как-либо оптимизировать переменную.
Да, спасибо, я именно так и сделал.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Engineer_Keen писал(а):Если закоротить ногу на землю, то в первом случае прерывание будет вызываться постоянно - пока нога на земле, а во втором один раз.
Т.е. как только функция-обработчик прерывания завершится, она снова начнёт выполняться снова (если флаги прерываний не были изменены в самом этом прерывании)?

ОК, буду знать.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Да, выполнит одну команду и вернется в обработчик.
Опытный кот
Сообщения: 758
Зарегистрирован: Вс фев 10, 2013 15:26:00

Сообщение nirq »

При нажатии на кнопочку (INT0) должно измениться направление
Дребезг.
Читать лень.
Ответить

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