roboforum.ru

Технический форум по робототехнике.

проблема с прерываниями

проблема с прерываниями

hadok » 26 дек 2010, 17:15

Plhавствуйте!
Помогите пожалуйста найти ошибку в коде. Хочу разобраться с прерываниями на mega8. Написал два события от прерываний INT0 и INT1 (PD2 и PD3 ). Но при замыкании соответсвующих ножек с землёй происходит вызов подпрограммы для INT0 . Для INT1 подпрограмма INT1 не выполняется.
Код: Выделить всёРазвернуть
#include <mega8.h>
#include <delay.h>   
           

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{       
   PORTC.3=1; 
delay_ms(1000);
PORTC.3=0; 

 
SREG=1;
}

// External Interrupt 1 service routine   


interrupt [EXT_INT1] void ext_int1_isr(void)
{

PORTC.4=1; 
delay_ms(1500);
PORTC.4=0; 
SREG=1;
}

// Declare your global variables here

void main(void)
{

PORTC=0x00;
DDRC=0xFF;

// Port D initialization
PORTD=0x00;
DDRD=0xFF;

TCCR0=0x00;
TCNT0=0x00;


TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

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); }
      };
}

Re: проблема с прерываниями

Radist » 26 дек 2010, 18:55

Даташит читали внимательно? В МКУКР надо писать 0х0А, а не 0х14. Порт Д у вас настроен на выход, выдаете единицу и коротите его на землю. Я не удивлюсь, если одна из ног уже ластами щелкнула. На вход надо порт Д настраивать, и подтяжку включить. Если так и не заработает - новый камень покупайте.

Re: проблема с прерываниями

avr123.nm.ru » 26 дек 2010, 22:58

hadok писал(а): при замыкании соответсвующих ножек с землёй
В своем малом курсе по AVR я рекомендую "замыкать" через резистор 200-500 Ом. :good:

И PROTEUS использовать.

Re: проблема с прерываниями

hadok » 27 дек 2010, 00:26

Radist писал(а):В МКУКР надо писать 0х0А, а не 0х14



смотрел пример в книжке по поводу прерываний, опирался на него
Вложения
mega1.JPG
mega.JPG

Re: проблема с прерываниями

avr123.nm.ru » 27 дек 2010, 01:00

Для самопроверки настройте прерывания мастером CodeVisionAVR и посмотрите код - пример прерывания в AVR с кнопочками на INT0 INT1 в обучалке http://proavr.narod.ru/03.htm :Bravo:

Re: проблема с прерываниями

hadok » 27 дек 2010, 01:08

делал уже, действительно Radist прав......а книжка нет, вот и верь потом букварям.......

а у меня так и не заработало, всё равно срабатывает только одно прерывании не зависио от номера ножки (D2 D3)

возможно и правда "камень" полетел.....

Re: проблема с прерываниями

hadok » 29 дек 2010, 01:38

изменил код
Код: Выделить всёРазвернуть
#include <mega8.h>
#include <delay.h>   
           

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{       
  if (PIND.2==1){ PORTC.3=0; 
  delay_ms(5000);
  PORTC.3=1;     }
  else
{ PORTC.4=1; delay_ms(2000); PORTC.4=0;}

 
SREG=1;
}

// External Interrupt 1 service routine   


interrupt [EXT_INT1] void ext_int1_isr(void)
{

PORTC.4=0; 
delay_ms(1500);
PORTC.4=0; 
SREG=1;
}

// Declare your global variables here

void main(void)
{

PORTC=0x00;
DDRC=0xFF;

// Port D initialization
PORTD=0x00;
DDRD=0x00;

TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
GICR|=0x40;   // включаю прерывания 0
MCUCR=0x02;  // по спадающему фронту                 
MCUCSR=0x00;
GIFR=0xC0;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;

// 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); }
      };
}



прошил новый камень, теперь всё стало ещё интереснее. :crazy: Прерывание 0 срабатывает само собой, причём выполняются два условия
Код: Выделить всёРазвернуть
if (PIND.2==1){ PORTC.3=0;  
  delay_ms(5000);
  PORTC.3=1;     }
  else
{ PORTC.4=1; delay_ms(2000); PORTC.4=0;}
последовательно

ну вот где у меня ошибка вкралась :shock:

Re: проблема с прерываниями

Radist » 29 дек 2010, 08:41

Ну как где ошибка. Я уже писал про нее. Сначала вы порт Д на выход настраивали, теперь в третье состояние перевели. Короче, еще раз: в ддрд пишем нули, в портд пишем единицы. Это - вход с подтяжкой. А третье состояние - это болтающийся в воздухе вход.
Кстати, внутренняя подтяжка в контролере слабенькая, рекомендую еще снаружи резюки поставить порядка единиц килоОмов.

Re: проблема с прерываниями

hadok » 29 дек 2010, 16:17

Я представил исправленный код. Там порт д настрен на выход, и подтяжки включены. Единственное, что я не доконца понимаю, это смысл подключения резюков. Куда их, от Vcc к ножкам Int0 и Int1 ?

почему не работает коснтрукция if (PIND.3==0) then ?

Добавлено спустя 1 минуту 46 секунд:
[quote="hadok"]изменил код
Код: Выделить всёРазвернуть
#include <mega8.h>
#include <delay.h>   
           

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{       
  if (PIND.3==1){ PORTC.3=0; 
  delay_ms(5000);
  PORTC.3=1;     }
  else if (PIND.3==0)
{ PORTC.4=1; delay_ms(2000); PORTC.4=0;}

 
SREG=1;
}

// External Interrupt 1 service routine   


interrupt [EXT_INT1] void ext_int1_isr(void)
{

PORTC.4=0; 
delay_ms(1500);
PORTC.4=0; 
SREG=1;
}

// Declare your global variables here

void main(void)
{

PORTC=0x00;
DDRC=0xFF;

// Port D initialization
PORTD=0x00;
DDRD=0x00;

TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
GICR|=0x40;   // включаю прерывания 0
MCUCR=0x02;  // по спадающему фронту                 
MCUCSR=0x00;
GIFR=0xC0;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;

// 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); }
      };
}

Re: проблема с прерываниями

Radist » 29 дек 2010, 20:22

Внешние резюки подтягивают вход к плюсу. Использование внешних резюков повышает помехоустойчивость.

Если по прежнему проблема в том, что инт0 работает, а инт1 нет, то инт1 не разрешен.

Re: проблема с прерываниями

yak-40 » 29 дек 2010, 20:41

hadok писал(а):Там порт д настрен на выход, и подтяжки включены.

Как это? Внешние прерывания (int0, int1)подключены к PD.2,PD.3, они должны быть настроены на вход!
И ещё, delay(5000) в прерывании это круто! :shock:

Добавлено спустя 9 минут 25 секунд:
Чёто код какой-то мутный, чем больше смотрю, тем больше удивляюсь :shock:
Код: Выделить всёРазвернуть
PORTC.4=0;  
delay_ms(1500);
PORTC.4=0; 

Как это понять? выставить ноль на портс.4, подождать 1,5 сек, потом выставить опять ноль на этой же ноге?

Re: проблема с прерываниями

hadok » 29 дек 2010, 20:43

блин, совсем я запутался. Порт Д как и написано в коде настроен на вход, подтяжки включены.

Delay(5000) - исключительно для отладки, чтобы было видно какое из двух условий программа отрабатывает.

Мало того что при обоих включённых прерываниях они срабатывали друг за другом. Теперь я оставил только INT0 . Но при отработке соответствующей подпрограммы выполняются два условия, то есть никакой реакции на if (PIND.3==1) нету????


Братцы, ну посмотрите Вы мой код, может у Вас он заработает....ну вроде всё из советов сделал.... :O:

Код: Выделить всёРазвернуть
PORTC.4=0;  
delay_ms(1500);
PORTC.4=0; 

Это я от отчаяния выключил таким образом подпрограмму от прерывания...., хотя и само прерывание INT1 само по себе не разрешено.....

Re: проблема с прерываниями

yak-40 » 29 дек 2010, 20:59

Код: Выделить всёРазвернуть
PORTD.2=1;  // вывожу высокий уровень на ножки порта, чтобы при замыкании с землёй фиксировался спадающий фронт
PORTD.3=1;

Вот это то зачем, если порт Д на вход настроен? :shock:
Так! Без паники!!!
Сделай следующее: упрости код до минимума, оставь только функции с прерываниями, подключи два светодиода, например к порту С, и попробуй зажечь каждой функцией прерывания свой светодиод.

Re: проблема с прерываниями

Radist » 29 дек 2010, 21:16

Или же так:
- внешнее прерывание меняет флаг
- основная программа смотрит этот флаг и зажигает светодиоды

Минимум строчек кода. Вы там кучу регистров нулями инициализируете - это ни к чему. Там и так после сброса нули. Представьте что было бы если это было бы не так. Инициализировать вам надо только порты и внешние прерывания.

ЗЫ. На асме давно бы уже вам написал как надо, но Си я совсем не знаю, в смысле синтаксис.

Re: проблема с прерываниями

hadok » 29 дек 2010, 21:28

PORTD.2=1; - я включаю подтяжку на ножке порта, сконфигурированного как вход.




yak-40 писал(а):Сделай следующее: упрости код до минимума, оставь только функции с прерываниями, подключи два светодиода, например к порту С, и попробуй зажечь каждой функцией прерывания свой светодиод.



вот именно так я делал, только добавил ещё различие по времени (5000).


Rambler\'s Top100 Mail.ru counter