Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.88/124: Рейтинг темы: голосов - 124, средняя оценка - 4.88
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
1

Внешнее прерывание INT0. ATmega8

19.02.2014, 10:22. Просмотров 24346. Ответов 41
Метки нет (Все метки)

Я считаю что код правильный, но он не работает )))) Симуляция в Proteus показывает что прерывание есть, но потом порт PB0 становится вообще не понятно каким...Помогите разобраться, третий день ничего не получается.

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

#define F_CPU 8000000

void LED_ON() {

DDRB |= (0<<PB0); //PB0 как выход
PORTB |= (1<<PB0); // PB0 лог.1

}

/*Обработчик прерывания*/
ISR(INT0_vect) {
//_delay_ms(50); //защита от дребезга
LED_ON();
}

int main (void) { //главная цикл программы

/*Настройка портов*/
DDRD &= ~(1<<PD2); //INT0 как вход
PORTD |= (1<<PD2);  // PD2 лог.1

sei(); //разрешаем прерывания глобально
GICR |= (1<<INT0); //Разрешаем прерывания по INT0
MCUCR |= (1<<ISC01)|(0<<ISC00); //Прерывания по ниспадающему фронту

while(1) {

}

}
Файл Протеус прикрепляю.

[13.7 Кб]
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.02.2014, 10:22
Ответы с готовыми решениями:

внешнее прерывание INT0 ATtiny2313
Как изобразить прерывание в AtmelStdio7 ну хоть какое то хоть блин любое.... Сначала пробовал на...

Не работает внешнее прерывание в ATMega8 (CodeVisionAVR 3.10)
Среда CodeVisionAVR 3.10, вот код #include &lt;mega8.h&gt; interrupt void ext_int0_isr(void) {...

Прерывание INT0
Нарвался вот на неприятное дело :) Делаю (теперь уже сделал) системку управления ближним и дальним...

Прерывание INT0
Здравствуйте. Использую Attiny2313, на INT0 висит TSOP. В прерывании отправляются данные по USORT....

Прерывание INT0 Atmega88
Пытаюсь использовать прерывание INT0. В avr studio и протеусе все работает хорошо, но в железе...

41
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 10:26 2
))) сам косяк нашёл))) а как проверять с помощью GIFR статус? ну типа нажата горит светодиод, не нажата не горит.

Код
if (GIFR == (1<<INTF0)) зажигаем!! ))) , иначе тушим?
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
19.02.2014, 10:43 3
Неправильно. Потому что в GIFR могут оказаться взведены и другие биты, а не только интересующий Вас. Надо маскировать:
Код
if (GIFR & (1<<INTF0))
зажигаем;
else
тушим;
0
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 10:52 4
Опять не понимаю, всё вроде правильно, а он зажигается и не тухнет!!!
Код
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define F_CPU 8000000

void LED_ON() {

if (GIFR & (1<<INTF0)) {

DDRB |= (1<<PB0); //PB0 как выход
PORTB |= (1<<PB0); // PB0 лог.1

} else {

DDRB |= (1<<PB0); //PB0 как выход
PORTB |= (0<<PB0); // PB0 лог.0

}
}

/*Обработчик прерывания*/
ISR(INT0_vect) {
//_delay_ms(50); //защита от дребезга
LED_ON();
}

int main (void) { //главная цикл программы

/*Настройка портов*/
DDRD |= (0<<PD2); //INT0 как вход
PORTD |= (1<<PD2);  // PD2 лог.1

sei(); //разрешаем прерывания глобально
GICR |= (1<<INT0); //Разрешаем прерывания по INT0
MCUCR |= (1<<ISC01)|(0<<ISC00); //Прерывания по ниспадающему фронту

while(1) {};
}
0
19.02.2014, 10:52
hixFF
0 / 0 / 0
Регистрация: 30.01.2010
Сообщений: 641
19.02.2014, 11:13 5
в си я не силен, но процедура tid_on по-моему, с ошибкой.

плюс, флаг intf сбрасывается при уходе по вектору прерывания.

если нужно сделать так, чтобы по первому нажатию загорался, а по второму- гас лучше будет смотреть состояние ножки светодиода и переключать на обратное
0
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 11:24 6
Цитата Сообщение от hixFF
в си я не силен, но процедура tid_on по-моему, с ошибкой.

плюс, флаг intf сбрасывается при уходе по вектору прерывания.

если нужно сделать так, чтобы по первому нажатию загорался, а по второму- гас лучше будет смотреть состояние ножки светодиода и переключать на обратное
Да, так нужно и сделать. Как проверить что прерывание отсутствует?
0
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 11:30 7
Код
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define F_CPU 8000000

void LED_ON() {

DDRB |= (1<<PB0); //PB0 как выход
PORTB |= (1<<PB0); // PB0 лог.1

}

void LED_OFF() {

DDRB |= (1<<PB0); //PB0 как выход
PORTB |= (0<<PB0); // PB0 лог.0

}

/*Обработчик прерывания*/
ISR(INT0_vect) {
//_delay_ms(50); //защита от дребезга
LED_ON();
}

int main (void) { //главная цикл программы

/*Настройка портов*/
DDRD |= (0<<PD2); //INT0 как вход
PORTD |= (1<<PD2);  // PD2 лог.1

sei(); //разрешаем прерывания глобально
GICR |= (1<<INT0); //Разрешаем прерывания по INT0
MCUCR |= (1<<ISC01)|(0<<ISC00); //Прерывания по ниспадающему фронту

LED_OFF();

}
Я считаю что приведённый выше код должен работать так, есть прерывание внешнее горит светодиод, прерывания нет не горит светодиод. В чём я ошибаюсь?
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
19.02.2014, 11:32 8
Класно соединить обработчик прерывания с функцией проверки флага . Flag сие ISR(INT0_vect) сбрасывает в ноль поэтому всегда будет выполнятся } else {
0
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 11:36 9
Цитата Сообщение от YTYOUT
Класно соединить обработчик прерывания с функцией проверки флага . Flag сие ISR(INT0_vect) сбрасывает в ноль поэтому всегда будет выполнятся } else {
а что скажите насчёт кода под спойлером, чуть выше.
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
19.02.2014, 12:57 10
Цитата Сообщение от Miymfromi
есть прерывание внешнее горит светодиод, прерывания нет не горит светодиод. В чём я ошибаюсь?
Вы ошибаетесь в принципе! Прерывание же по фронту - значит, Вы хотите, чтобы LED горел только во время спадающего фронта и не горел всё остальное время. :-)
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
19.02.2014, 13:09 11
Цитата Сообщение от Miymfromi
Я считаю что приведённый выше код должен работать
Sorry, но Ваш код - ошибка на ошибке. Вот такой код должен работать, причём без всяких прерываний:
Код
#include <avr/io.h>

#define F_CPU 8000000
#include <util/delay.h>  //СНАЧАЛА F_CPU, а уж потом этот #include!

int main (void) {  //главная функция программы

/*Настройка портов*/
DDRB  = (1 << PB0);  //пин со светодиодом как выход
DDRD  = (0 << PD2);  //пин с кнопкой как вход
PORTD = (1 << PD2);  //подтяжка к плюсу питания на кнопочном пине

while (1) {  //главный цикл программы
if (PIND & (1 << PD2) {  //кнопка нажата?
PORTB &= ~(1<<PB0);  //если не нажата, то PB0=лог.0 - LED off
}
else {
PORTB |= (1<<PB0); //в противном случае PB0=лог.1 - LED on
}
}
}
0
kytikot
0 / 0 / 1
Регистрация: 27.01.2010
Сообщений: 3,435
19.02.2014, 13:36 12
Добавлю 5 копеек

Код
#define   LED   PB0
#define   LED_ON   (PORTB|=(1<<LED))
#define   LED_OFF  (PORTB&=(~(1<<LED)))
0
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 13:37 13
Цитата Сообщение от OtyxPM
Цитата Сообщение от Miymfromi
Я считаю что приведённый выше код должен работать
Sorry, но Ваш код - ошибка на ошибке. Вот такой код должен работать, причём без всяких прерываний:
Код
#include <avr/io.h>

#define F_CPU 8000000
#include <util/delay.h>  //СНАЧАЛА F_CPU, а уж потом этот #include!

int main (void) {  //главная функция программы

/*Настройка портов*/
DDRB  = (1 << PB0);  //пин со светодиодом как выход
DDRD  = (0 << PD2);  //пин с кнопкой как вход
PORTD = (1 << PD2);  //подтяжка к плюсу питания на кнопочном пине

while (1) {  //главный цикл программы
if (PIND & (1 << PD2) {  //кнопка нажата?
PORTB &= ~(1<<PB0);  //если не нажата, то PB0=лог.0 - LED off
}
else {
PORTB |= (1<<PB0); //в противном случае PB0=лог.1 - LED on
}
}
}
Спасибо за код. Но я интересовался внешними прерываниями, а кнопка это как имитатор этих самих прерываний. Вот только не знаю как сделать выбор вариантов вкл или выкл в прерывании.
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
19.02.2014, 13:48 14
Цитата Сообщение от Miymfromi
Но я интересовался внешними прерываниями, а кнопка это как имитатор этих самих прерываний. Вот только не знаю как сделать выбор вариантов вкл или выкл в прерывании.
Когда прерывание по спадающему фронту - Вы не можете определить момент отпускания кнопки. Будь это другой AVR - хотя бы ATmega88, - можно было бы воспользоваться другим типом прерываний, PCINT - они срабатывают по обоим фронтам.

Но раз у Вас древний ATmega8, то придётся выкручиваться. Варианты:
1) перепрограммировать фронт INT0 при каждом срабатывании ISR;
2) присоединить кнопку сразу к двум входам INT0 и INT1, и настроить прерывания на разные фронты;
3) применить другой алгоритм - например, по одному нажатию вкл., по следующему выкл, и так далее.
0
kytikot
0 / 0 / 1
Регистрация: 27.01.2010
Сообщений: 3,435
19.02.2014, 13:49 15
Тебе сначала нужно научиться писать правильные куски кода. А то, честно говоря, ты не можешь зажечь/погасить светодиод, потому что путаешь нужные действия для этого. А уже потом браться за прерываяния.
0
Johmmy0007
1 / 1 / 0
Регистрация: 30.08.2011
Сообщений: 9,944
19.02.2014, 13:53 16
Цитата Сообщение от OtyxPM
Цитата Сообщение от Miymfromi
Но я интересовался внешними прерываниями, а кнопка это как имитатор этих самих прерываний. Вот только не знаю как сделать выбор вариантов вкл или выкл в прерывании.
Когда прерывание по спадающему фронту - Вы не можете определить момент отпускания кнопки. Будь это другой AVR - хотя бы ATmega88, - можно было бы воспользоваться другим типом прерываний, PCINT - они срабатывают по обоим фронтам.

Но раз у Вас старый древний ATmega8, то придётся выкручиваться. Варианты:
1) перепрограммировать фронт INT0 при каждом срабатывании ISR;
2) присоединить кнопку сразу к двум входам INT0 и INT1, и настроить прерывания на разные фронты.
вроде в даташите написано - можно по любому изменению.
хотя у евстифеева не написано. Как на самом деле?
0
HotD
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
19.02.2014, 13:57 17
Цитата Сообщение от Miymfromi
есть прерывание внешнее горит светодиод, прерывания нет не горит светодиод. В чём я ошибаюсь?
Прерывание происходит очень быстро. Вы можете даже глазом не успеть заметить то, что светодиод включился на время обработчика прерывания.
0
Miymfromi
0 / 0 / 0
Регистрация: 15.09.2012
Сообщений: 159
19.02.2014, 13:58 18
Цитата Сообщение от OtyxPM
Цитата Сообщение от Miymfromi
Но я интересовался внешними прерываниями, а кнопка это как имитатор этих самих прерываний. Вот только не знаю как сделать выбор вариантов вкл или выкл в прерывании.
Когда прерывание по спадающему фронту - Вы не можете определить момент отпускания кнопки. Будь это другой AVR - хотя бы ATmega88, - можно было бы воспользоваться другим типом прерываний, PCINT - они срабатывают по обоим фронтам.

Но раз у Вас древний ATmega8, то придётся выкручиваться. Варианты:
1) перепрограммировать фронт INT0 при каждом срабатывании ISR;
2) присоединить кнопку сразу к двум входам INT0 и INT1, и настроить прерывания на разные фронты;
3) применить другой алгоритм - например, по одному нажатию вкл., по следующему выкл, и так далее.
Про PCINT на ATmega48. Опишите алгоритм. Спасибо.
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
19.02.2014, 14:28 19
Если он полезет в настройки PCINT , то коллеги мы его потеряем :)
пусть в самом прерывании INT0 перенастраивает фронт и добавит флажок горит погашен. И будет ему счастье.
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
19.02.2014, 14:46 20
Цитата Сообщение от kytikot
Добавлю 5 копеек

Код:
#define LED PB0
#define LED_ON (PORTB|=(1<<LED))
#define LED_OFF (PORTB&=(~(1<<LED)))

Меня ругали за код в дефайнах. Если это WinAVR или AVR Toolchain, то inline. В IAR inline по другому делается, как-то через #pragma. И то на определенной оптимизации inline не работает.
0
19.02.2014, 14:46
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.02.2014, 14:46

ATtiny84 и прерывание INT0
Здравствуйте! Прошу помощи в таком вопросе. В ATtiny84 задействовано прерывание INT0, регистрация...

Не срабатывают внешние прерывания INT0/INT1 в Atmega8
Помогите разобраться новичку в МК, в чем может быть проблема. Пытаюсь освоить самостоятельно...

Прерывание по изменению уровня на INT0 в ATmega16
Предисловие. Проект частотомера в AVR Studyo 4. При использовании режима Power-down Mode...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru