|
AVR-IAR и внешнее прерывание, обработка INT0 |
|
|
|
Feb 12 2009, 10:31
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 13-02-07
Пользователь №: 25 311

|
Добрый день уважаемые. Имею очень простой вопрос, как в IAR обработать внешнее прерывание. До этого програмил в CVAVR, но вот решил мигрировать. Опишу задачу. Нужно обработать внешнее прерывание INT0, по нижнему уровню. Посмотрел примеры, вопросы ответы, нашел более менее подходящий кусок по обработке прерывания при перемолнении таймера счетчика, кусок работает. Написал для обработки INT0- Не работает... Привожу код. CODE #include <iom128.h> #include <inavr.h> #include <ina90.h>
//volatile char flag;
//Обработка прерывания INT0*** #pragma vector = 0x04 //#pragma type_attribute=__interrupt //void my_handler(void) __interrupt void INT0_ISR(void) { __disable_interrupt(); //отключаем глобальные прерывания //flag=flag++; PORTD_Bit6 = 0; //смотрим по состоянию ножки выполнилось ли прерывание }
int main( void ) { DDRD_Bit7 = 1; //конфигурируем биты DDRD_Bit6 = 1; PORTD_Bit6 = 1;
DDRE=0xFF; //конфигурируем порты DDRF=0xFF; DDRB=0xFF;
EIMSK|= 1<<0; //Разрешаем INT0 EICRA &= ~(1<<0); // по нижнему уровню __enable_interrupt(); //разрешаем глобальные прерывания
while (1) { __delay_cycles(1000000); PORTD_Bit7 = 1; //смотрим не виснет ли __delay_cycles(1000000); PORTD_Bit7 = 0;
PORTE=EIMSK; //смотрим текущее состояние PORTF=SREG; PORTB=EIFR; } }
Если закоментировать обработку прерывания, то: Код EIMSK=0x01; SREG=0x82; EIFR=0xF0; P.S. Компилируется без ошибок. Моделирую в Proteuse, за неимением железа под рукой... Мб глюк протеуса, но врядли ибо аналогичное в CVAVR работает без проблем. В чем я ошибся?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
Feb 12 2009, 10:45
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 23-10-08
Из: Набережные Челны
Пользователь №: 41 132

|
Цитата(mr_ia @ Feb 12 2009, 13:31)  __interrupt void INT0_ISR(void) { __disable_interrupt(); //отключаем глобальные прерывания //flag=flag++; PORTD_Bit6 = 0; //смотрим по состоянию ножки выполнилось ли прерывание } А где потом __enable_interrupt(); в цикле обработке прерывания
|
|
|
|
|
Feb 12 2009, 10:48
|

Местный
  
Группа: Свой
Сообщений: 343
Регистрация: 24-01-07
Из: Новосибирск
Пользователь №: 24 714

|
Как минимум, в том, что прерывание отработает только один раз Цитата Код __interrupt void INT0_ISR(void) { __disable_interrupt(); //отключаем глобальные прерывания //flag=flag++; PORTD_Bit6 = 0; //смотрим по состоянию ножки выполнилось ли прерывание } P.S. сорри, пока писал, оказалось что повторился.
|
|
|
|
|
Feb 12 2009, 10:59
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 13-02-07
Пользователь №: 25 311

|
если добавить __enable_interrupt(); в обработку прерывания то результат не меняется. Т.е. протеус, мб в нем конечно дело, не меняет PORTD_Bit6 в 0
т.е. думаю прерывание вообще не обрабатывается. и на других ногах PORTF,E,B ничего не меняется с момента старта эмулирования.
Если обработку прерывания закомментировать то PORTF,E,B по крайней мере показывают состояние EIMSK, SREG, EIFR;
|
|
|
|
|
Feb 12 2009, 11:09
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 23-10-08
Из: Набережные Челны
Пользователь №: 41 132

|
Цитата(mr_ia @ Feb 12 2009, 13:31)  while (1) { __delay_cycles(1000000); PORTD_Bit7 = 1; //смотрим не виснет ли __delay_cycles(1000000); PORTD_Bit7 = 0;
PORTE=EIMSK; //смотрим текущее состояние PORTF=SREG; PORTB=EIFR; } В начальном состоянии PORTD_Bit6 в 0 и в прерывании ты хочешь его установить в 0, а в цикле обратно в состояние 1 не возвращаешь.
|
|
|
|
|
Feb 12 2009, 11:33
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(mr_ia @ Feb 12 2009, 13:31)  Моделирую в Proteuse, за неимением железа под рукой... Мб глюк протеуса, но врядли ибо аналогичное в CVAVR работает без проблем. В чем я ошибся? В AVRStudio Ваш пример работает... Несколько замечаний по самой программе: 1. Запрешать прерывания в обработчике прерываний не имеет смысла: при входе в него - прерывания запрещены; при выходе - разрешаются вновь. 2. Устанавливать таким образом: EICRA &= ~(1<<0); уровень сигнала - несколько странно (уровень определяется двумя битами) 3. Если уровень ни INT0 стал низким и не меняется, то при выходе из прерывания - тут же произайдёт новое прерывание по INT0 (правда, успеет выполниться одна команда основного цикла). Т.е., обычно, в прерывании по уровню что-то делают с условием срабатывания. 4. Если меняете EICRA, то делают это до разрешения прерывания в EIMSK и очищают флаг прерывания (см. даташит).
|
|
|
|
|
Feb 12 2009, 11:34
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 13-02-07
Пользователь №: 25 311

|
Ногу дергаю кнопкой(в протеусе). изначально INT0 он же PORTD_0 притянут к 1, по схеме вопросов нет (сама простая да и код из CVAVR работает на ней без проблем). Т.е. думаю проблема в коде IARa. На счет преимущества готового железа это конечно, но его под рукой сейчас нет, и в ближайшее время не будет.
Почему PORTD_Bit6 в 0? изначально устанавливаю его в 1, и перевожу в 0 ТОЛЬКО в прерывании.
int main( void ) { DDRD_Bit7 = 1; //конфигурируем биты DDRD_Bit6 = 1; PORTD_Bit6 = 1;
//Обработка прерывания INT0*** #pragma vector = 0x04 //#pragma type_attribute=__interrupt //void my_handler(void) __interrupt void INT0_ISR(void) { __disable_interrupt(); //отключаем глобальные прерывания //flag=flag++; PORTD_Bit6 = 0; //смотрим по состоянию ножки выполнилось ли прерывание }
|
|
|
|
|
Feb 12 2009, 12:05
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 13-02-07
Пользователь №: 25 311

|
Цитата(Палыч @ Feb 12 2009, 15:33)  В AVRStudio Ваш пример работает... Несколько замечаний по самой программе: 1. Запрешать прерывания в обработчике прерываний не имеет смысла: при входе в него - прерывания запрещены; при выходе - разрешаются вновь. 2. Устанавливать таким образом: EICRA &= ~(1<<0); уровень сигнала - несколько странно (уровень определяется двумя битами) 3. Если уровень ни INT0 стал низким и не меняется, то при выходе из прерывания - тут же произайдёт новое прерывание по INT0 (правда, успеет выполниться одна команда основного цикла). Т.е., обычно, в прерывании по уровню что-то делают с условием срабатывания. 4. Если меняете EICRA, то делают это до разрешения прерывания в EIMSK и очищают флаг прерывания (см. даташит). Спасибо что попробовали в AVRStudio, но хочется то что бы в IAR заработало... По пункту 2 полностью согласен. По пункту 3 попрошу уточнить. Если EICRA=0x00 т.е. 0 и 1 биты в 0. Как только разрешены глобальные прерывания, происходит соответсвенно обработка INT0, в теле обработки я например устанавливаю EIMSK 0 бит в 0, и запрещаю прерывания для INT0, тогда зацикливаться не будет? я правильно думаю? Вообщем то пока писал проверил. Добавил в обработку прерывания запрет для всех INT EIMSK=0x00; В CVAVR помогло. В IAR нет...  Цитата(clpe @ Feb 12 2009, 15:56)  DDRE=0xFF; //конфигурируем порты DDRF=0xFF; DDRB = 0xFF; - без этой строки работает Простите а Вы в чем компилировали/проверяли? у меня нет  DDRB = 0xFF; - без этой строки работает совершенно безобидная на мой взгляд строка...
|
|
|
|
|
Feb 12 2009, 12:17
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 23-10-08
Из: Набережные Челны
Пользователь №: 41 132

|
Нет всетаки виноват протеус... У меня работает: Proteus 7.4 sp3 iar5.11b. ваш код CODE #include <ioavr.h> #include <inavr.h> #include <ina90.h>
//Обработка прерывания INT0*** #pragma vector = 0x04
__interrupt void INT0_ISR(void) { PORTD_Bit6 = 0; //смотрим по состоянию ножки выполнилось ли прерывание }
int main( void ) { DDRD_Bit7 = 1; //конфигурируем биты DDRD_Bit6 = 1; PORTD_Bit6 = 1;
DDRE=0xFF; //конфигурируем порты DDRF=0xFF; DDRB = 0xFF;
EIMSK|= 1<<0; //Разрешаем INT0 EICRA &= ~(1<<0); // по нижнему уровню __enable_interrupt(); //разрешаем глобальные прерывания
while (1) { __delay_cycles(1000000); PORTD_Bit7 = 1; //смотрим не виснет ли __delay_cycles(1000000); PORTD_Bit7 = 0;
PORTE=EIMSK; //смотрим текущее состояние PORTF=SREG; PORTB=EIFR; } } А на счет DDRB = 0xFF просто я запутался
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Эскизы прикрепленных изображений
|
|
|
|
|
Feb 12 2009, 12:53
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(mr_ia @ Feb 12 2009, 15:05)  Спасибо что попробовали в AVRStudio, но хочется то что бы в IAR заработало... Выше я говорил о том, что Ваша программа, оттранслированная IAR, нормально симулируется AVRStudio. Поскольку, аналогичная программа из CVAVR нормально симулируется в протеусе и Ваша программа, оттранслированная IAR у "чужих" тоже нормально симулируется, то, имхо, в настройках проекта IAR у Вас какая-то бяка...
|
|
|
|
|
Feb 12 2009, 13:29
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(mr_ia @ Feb 12 2009, 13:31)  нашел более менее подходящий кусок по обработке прерывания при перемолнении таймера счетчика, кусок работает. Написал для обработки INT0- Не работает... А кто будет делать: EXTINT = EXTINT_EINT0; // Clear the EXT interrupt flag VICVectAddr = 0; // Dummy write to signal end of interrupt А вообще исходник бредовый, и разговоры об эмуляции периферийного железа всякими приблудами - тоже  Вместо многочасового тыка в "эмуляторе" надежнее и проще уделить 15 минут чтению документации и со знанием дела, уверенно написать эти несколько строк.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|