Plhавствуйте! Помогите пожалуйста найти ошибку в коде. Хочу разобраться с прерываниями на mega8. Написал два события от прерываний INT0 и INT1 (PD2 и PD3 ). Но при замыкании соответсвующих ножек с землёй происходит вызов подпрограммы для INT0 . Для INT1 подпрограмма INT1 не выполняется.
GICR=0x40+0x80; // включаю прерывания 0 и 1 MCUCR=0x02+0x12; // по спадающему фронту MCUCSR=0x00; GIFR=0xC0;
TIMSK=0x00;
ACSR=0x80; SFIOR=0x00;
// Global enable interrupts #asm("sei") PORTC=0x0F ; PORTD.2=1; // вывожу высокий уровень на ножки порта, чтобы при замыкании с землёй фиксировался спадающий фронт PORTD.3=1; while (1) { // Place your code here if (PORTC==0x0F) {PORTC=0xF0; delay_ms(500); } else if (PORTC==0xF0) {PORTC=0x0F; delay_ms(500); } }; }
Даташит читали внимательно? В МКУКР надо писать 0х0А, а не 0х14. Порт Д у вас настроен на выход, выдаете единицу и коротите его на землю. Я не удивлюсь, если одна из ног уже ластами щелкнула. На вход надо порт Д настраивать, и подтяжку включить. Если так и не заработает - новый камень покупайте.
Для самопроверки настройте прерывания мастером CodeVisionAVR и посмотрите код - пример прерывания в AVR с кнопочками на INT0 INT1 в обучалке http://proavr.narod.ru/03.htm
// Global enable interrupts #asm("sei") PORTC=0x08 ; PORTD.2=1; // вывожу высокий уровень на ножки порта, чтобы при замыкании с землёй фиксировался спадающий фронт PORTD.3=1; while (1) { // Place your code here if (PORTC==0x08) {PORTC=0; delay_ms(500); } else if (PORTC==0) {PORTC=0x08; delay_ms(3000); } }; }
прошил новый камень, теперь всё стало ещё интереснее. Прерывание 0 срабатывает само собой, причём выполняются два условия
Ну как где ошибка. Я уже писал про нее. Сначала вы порт Д на выход настраивали, теперь в третье состояние перевели. Короче, еще раз: в ддрд пишем нули, в портд пишем единицы. Это - вход с подтяжкой. А третье состояние - это болтающийся в воздухе вход. Кстати, внутренняя подтяжка в контролере слабенькая, рекомендую еще снаружи резюки поставить порядка единиц килоОмов.
Я представил исправленный код. Там порт д настрен на выход, и подтяжки включены. Единственное, что я не доконца понимаю, это смысл подключения резюков. Куда их, от Vcc к ножкам Int0 и Int1 ?
почему не работает коснтрукция if (PIND.3==0) then ?
Добавлено спустя 1 минуту 46 секунд: [quote="hadok"]изменил код
// Global enable interrupts #asm("sei") PORTC=0x08 ; PORTD.2=1; // вывожу высокий уровень на ножки порта, чтобы при замыкании с землёй фиксировался спадающий фронт PORTD.3=1; while (1) { // Place your code here if (PORTC==0x08) {PORTC=0; delay_ms(500); } else if (PORTC==0) {PORTC=0x08; delay_ms(3000); } }; }
блин, совсем я запутался. Порт Д как и написано в коде настроен на вход, подтяжки включены.
Delay(5000) - исключительно для отладки, чтобы было видно какое из двух условий программа отрабатывает.
Мало того что при обоих включённых прерываниях они срабатывали друг за другом. Теперь я оставил только INT0 . Но при отработке соответствующей подпрограммы выполняются два условия, то есть никакой реакции на if (PIND.3==1) нету????
Братцы, ну посмотрите Вы мой код, может у Вас он заработает....ну вроде всё из советов сделал....
PORTD.2=1; // вывожу высокий уровень на ножки порта, чтобы при замыкании с землёй фиксировался спадающий фронт PORTD.3=1;
Вот это то зачем, если порт Д на вход настроен? Так! Без паники!!! Сделай следующее: упрости код до минимума, оставь только функции с прерываниями, подключи два светодиода, например к порту С, и попробуй зажечь каждой функцией прерывания свой светодиод.
Или же так: - внешнее прерывание меняет флаг - основная программа смотрит этот флаг и зажигает светодиоды
Минимум строчек кода. Вы там кучу регистров нулями инициализируете - это ни к чему. Там и так после сброса нули. Представьте что было бы если это было бы не так. Инициализировать вам надо только порты и внешние прерывания.
ЗЫ. На асме давно бы уже вам написал как надо, но Си я совсем не знаю, в смысле синтаксис.
PORTD.2=1; - я включаю подтяжку на ножке порта, сконфигурированного как вход.
yak-40 писал(а):Сделай следующее: упрости код до минимума, оставь только функции с прерываниями, подключи два светодиода, например к порту С, и попробуй зажечь каждой функцией прерывания свой светодиод.
вот именно так я делал, только добавил ещё различие по времени (5000).