Перейти к содержанию
    

Прерывания в CodeVisionAVR: как?

Прошу помочь найти косяк в программе. В железе не работает , AVRStudio подвисает при попытке выйти из прерывания. Причём, аналогичное происходит и при использовании прерывания от таймера.

 

// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
unsigned char adc_data;
// Read the 8 most significant bits
// of the AD conversion result

// Place your code here
  adc_data=ADCH;
  adc_data=(adc_data>>1); // j не больше 127
  if(adc_data==1) adc_data=0;// j==1 исключается - особенность функции poworot
  if(i_adc_buf==2) i_adc_buf=0;
  else ++i_adc_buf;
  j=(adc_buf[0]+adc_buf[1]+adc_buf[2]+adc_data)/4; //рекурсия
  adc_buf[i_adc_buf]=j;

}

 

Куска хватит или нужно всё?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Замените

if(i_adc_buf==2) i_adc_buf=0;
  else ++i_adc_buf;

на

if(i_adc_buf>=2) i_adc_buf=0;
  else ++i_adc_buf;

ИМХО у вас типичная ошибка возникает - выход указателя за границы массива.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Заменил - симулятору не полегчало. Всё по прежнему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Делать фильтрацию внутри прерывания это моветон. Кольцевой буфер сделайте и считайте ваше плавающее среднее в main-е.

А насчет зависания не совсем понял. Зависает сам симулятор? Или программа в симуляторе?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...А насчет зависания не совсем понял. Зависает сам симулятор? Или программа в симуляторе?
Загрузка процессора при симулировании - 97% (1,3 ГГц) при попытке выйти из прерывания. И выхода собственно и не происходит. Через пару минут я просто останавливаю. И в железе не работает.

Сама программа коротенькая, не возьмётесь просимулировать своим симулятором? Мне нужно только увидеть в симуляторе выход из прерывания. Дальше я попробую сам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Покажите остальной код, и МК укажите какой у вас. Сообразим..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как на этом движке дать вложение? Или дать программу текстом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : Подсос С АЦП и без таймеров

Version : 3-5
Date	: 30.09.2009
Author  :
Company :
Comments:  Пропущенный участок работает в железе без проблем.

Chip type		   : ATmega164
Program type		: Application
Clock frequency	 : 16.000000 MHz
Memory model		: Small
External RAM size   : 0
Data Stack size	 : 256
*****************************************************/
 #pragma savereg- // Выключить автоматическое сохранение регистров
 #include <mega164.h>
 #include <delay.h>
 #define start_ADC ADCSRA|=(1<<6);// Запуск АЦП
 #define ADC_VREF_TYPE 0x60

 char i=0,j_tec=0,j_max=130,t_i=0,adc_data=0,i_adc_buf,k;
 //i - номер фазы коммутации обмоток ШД
 //j-tec - текущее положение ротора ШД 0<=j_tec<=j_max
 //j-max - максимальное число полушагов ротора
 //t_i - период коммутации фаз (0-16ms,130-8,193-4,224-2,239-1)
 //i_adc_buf - номер в буфере АЦП

 signed char j=0;
  //j=1 пр. часовой,j=-1 по часовой,иначе - координата.
 char step[]={16,80,64,96,32,160,128,144};// комбинации фаз
 char adc_buf[3]={0,0,0};// Кольцевой буфер для усреднения АЦП

 void SW_step(void)
 {
 if (i==7)i=0;
 else ++i;
 PORTA=step[i];
 }

 void SSW_step(void)
 {if (i==0)i=7;
  else --i;
 PORTA=step[i];
 }



  void poworot (void)

{
 if (j==-1)goto L0;
 if (j!=1)goto L3;
 if (j_tec==j_max)return;
L1: SSW_step();
 j_tec++;
 return;
L0: if (j_tec==0)
{
 return;
}
L2: SW_step();
 j_tec--;
 return;
L3: if(j<0)
{
 return;
}
 if(j>j_tec) goto L1;
 if(j<j_tec) goto L2;
}


// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
unsigned char adc_data;
// Read the 8 most significant bits
// of the AD conversion result

// Place your code here
 adc_data=ADCH;
 adc_data=(adc_data>>1); // j не больше 127
 if(adc_data==1) adc_data=0;// j==1 исключается - особенность функции poworot
 if(i_adc_buf>=2) i_adc_buf=0;
 else ++i_adc_buf;
 j=(adc_buf[0]+adc_buf[1]+adc_buf[2]+adc_data)/4; //рекурсия
 adc_buf[i_adc_buf]=j;

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=T State2=T State1=T State0=0
PORTA=0x00;
DDRA=0xF1;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=0 State6=0 State5=0 State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0xE0;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-15: Off
// Interrupt on any change on pins PCINT16-23: Off
// Interrupt on any change on pins PCINT24-31: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;

// ADC initialization
// ADC Clock frequency: 125.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: Off, ADC3: Off
// ADC4: Off, ADC5: Off, ADC6: Off, ADC7: Off
DIDR0=0xFF;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x8F;

goto L11;

   k=0;
   j=1;
   while(j_tec!=125)
   {
	poworot();
	delay_ms(2);
   }
   delay_ms(2000);

   j=-1;
   while(j_tec!=20)
   {
	poworot();
	delay_ms(50);
   }
   delay_ms(2000);



   j=70;
   while(k<200)
   {
	poworot();
	delay_ms(1);
	k++;
   }
   delay_ms(2000);
L11:




  #asm("sei") // Разрешить прерывания

ADMUX=1;// Первый канал АЦП
  start_ADC;
  while (1)
  {
poworot();
delay_ms(2);

start_ADC;
  }


}

Изменено пользователем Александр К.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вот:

#pragma savereg- // Выключить автоматическое сохранение регистров

Потому и не работает ( http://telesys.ru/wwwboards/mcontrol/287/m...es/136890.shtml ).

 

PS: уберите тег [коде][/коде] вокруг [кодебокс][/кодебокс], я вас запутал немножко.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Потому и не работает ...

Спасибо. Посмотрел по ссылке, но не понял - почему нельзя использовать штатную команду? Я в прерывании регистры не использую, все переменные - глобальные. И почему ж нельзя? Глюк CV?

-----------------------------------------------------------------------------------------------------------

Исправил и проверил. Всё нормально. Ещё раз спасибо.

Вопрос остался ...

Изменено пользователем Александр К.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Регистры общего назначения и SREG. Они используются практически при каждой операции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не понял - почему нельзя использовать штатную команду? Я в прерывании регистры не использую, все переменные - глобальные.
Как это не используете? А unsigned char adc_data и результаты промежуточных вычислений где по-вашему хранятся?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В регистрах. Но их (регистров) больше, чем переменных. И все переменные - глобальные. Пересечений нет.

Вот фрагмент на асемблере. После остановки симулятора указатель показывает на адрес 180.

+00000172:   E7AA        LDI     R26,0x7A         Load immediate
+00000173:   E0B0        LDI     R27,0x00         Load immediate
+00000174:   91EC        LD      R30,X            Load indirect
+00000175:   E0F0        LDI     R31,0x00         Load immediate
+00000176:   64E0        ORI     R30,0x40         Logical OR with immediate
+00000177:   93EC        ST      X,R30            Store indirect
+00000178:   9508        RET                      Subroutine return
+00000179:   91E9        LD      R30,Y+           Load indirect and postincrement
+0000017A:   91F9        LD      R31,Y+           Load indirect and postincrement
+0000017B:   9630        ADIW    R30,0x00         Add immediate to word
+0000017C:   F039        BREQ    PC+0x08          Branch if equal
+0000017D:   EA80        LDI     R24,0xA0         Load immediate
+0000017E:   E09F        LDI     R25,0x0F         Load immediate
+0000017F:   9701        SBIW    R24,0x01         Subtract immediate from word
+00000180:   F7F1        BRNE    PC-0x01          Branch if not equal
+00000181:   95A8        WDR                      Watchdog reset
+00000182:   9731        SBIW    R30,0x01         Subtract immediate from word
+00000183:   F7C9        BRNE    PC-0x06          Branch if not equal
+00000184:   9508        RET                      Subroutine return
+00000185:   95F1        NEG     R31              Two's complement
+00000186:   95E1        NEG     R30              Two's complement
+00000187:   40F0        SBCI    R31,0x00         Subtract immediate with carry
+00000188:   9508        RET                      Subroutine return
+00000189:   2400        CLR     R0               Clear Register 

 

Я в этом не понимаю ... Конкретный косяк не видно?

Очень хочется не сохранять все РОН при прерывании.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...