Forum: Mikrocontroller und Digitale Elektronik Interrupts funktionieren nicht.


von Stefan G. (Gast)


Lesenswert?

Hallo,
ich programmiere gerade eine PI Regelung, bei der innerhalb der 
Interrupt Service Routine die Regelroutine abgearbeitet werden soll. Da 
das ganze bisher noch garnicht funktioniert, habe ich einfach mal zu 
Beginn der ISR versucht, die LED´s meines STK500 Boards aufleuchten zu 
lassen, um zu sehen ob überhaupt Interupts ausgelöst werden. Dabei habe 
ich festgestellt, daß dies offenbar nicht der Fall ist. Ich werde hier 
gleich mal den (etwas langen - sorry) Programmcode posten. Das Register 
TCCR0 (verantwortlich für Clock value) ist zuerst auf x00 gesetzt, d.h. 
der Timer ist aus. Erst nachdem ein Zeichen über den Terminal gelesen 
wurde, wird das Register auf x06 gesetzt, was dann einer Frequenz von 
14,4 kHz entspricht. Hat jemand von euch eine Idee, warum garkeine 
Interrupts ausgelöst werden? Ich benutze einen ATmega323 und 
CodevisionAVR.

Hier der Code:

#include <mega323.h>

// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>


#define ADC_VREF_TYPE 0x00
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSR|=0x40;
// Wait for the AD conversion to complete
while ((ADCSR & 0x10)==0);
ADCSR|=0x10;
return ADCW;
}

float v_ist;
float e_k;    // Regeldifferenz
float e_k_alt;
float k_p = 1.446;  // Verstärkungsfaktor
float t_i = 0.007343;  // Verzugszeit
float t_0 = 0.017708;  // Abtastzeit
float u_k;        // Stellgröße
float u_k_alt;
int v_soll;
int stell;


// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
  // Falls Interrupt ausgelöst wird, LED´s (-> PORTC) anschalten:
  PORTC = 1;

  // aktuelle Spannung berechnen:
  v_ist = (5.0/1023)*read_adc(0);

  // Regelabweichung e_k berechnen:
   e_k = v_soll - v_ist;

    // Stellgröße u_k berechnen:
     u_k = u_k_alt + k_p*(e_k*(1+t_0/t_i)-e_k_alt);

      // Stellgrößenbegrenzung:
       if (u_k > 5.0) u_k = 5.0;
       else if (u_k < 0.0) u_k = 0.0;

       // Stellgröße in entsprechenden PWM Wert umrechnen:
       stell = (int) (u_k*255/5.0);

       // Pulsbreite setzen:
       OCR0 = stell;

       u_k_alt = u_k;
       e_k_alt = e_k;
}


void main(void)
{


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

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

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

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

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 460,800 kHz
// Mode: Phase correct PWM top=FFh
// OC0 output: Non-Inverted PWM
TCCR0=0x62;
TCNT0=0x00;
OCR0=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
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: TCCR2=0x07: 3600 Hz  -> t_0 = 1/(3600/255) = 70.83 ms
//    TCCR2=0x06; 14400 Hz -> t_0 = 1/(14400/255) = 17,708 ms
//    TCCR2=0x05; 28800 Hz -> t_0 = 1/(28800/255) = 8,85 ms
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
GICR|=0x00;
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 115200
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;

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

// ADC initialization
// ADC Clock frequency: 115,200 kHz
// ADC Voltage Reference: AREF pin
ADMUX=ADC_VREF_TYPE;
ADCSR=0x85;

// Global enable interrupts
#asm("sei")


// Sollspannung über Terminal einlesen:
v_soll = (int) getchar()-48;

// Timer loslaufen lassen:
TCCR2=0x06;
}

von Gerd (Gast)


Lesenswert?

Hallo Stefan,

ich hab zwar noch nicht soviel Ahnung und programmiere auch in Assembler 
aber hast du Global Interrupt enable ausgeführt.
Andernfalls passiert nichts bei einem Interrupt.

Grüße Gerd

von Clemens (Gast)


Lesenswert?

Also wie ich sehe hast du das mit Codevision programmiert. Du hast aber 
einen fehler bei der

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

gemacht.

das müsste denke ich mal

TIMSK=0x40;

heißen.

Mfg Clemens

von Stefan G. (Gast)


Lesenswert?

Hallo Gerd und Colemens,
verdammt, es lag tatsächlich an dem TIMSK bzw. dem TOIE2 (Timer/Counter2 
Overflow Interrupt Enable) Register. Tausend Dank, nun weiß ich 
zumindest daß die Interrupts funktionieren und kann mich wieder dem 
eigentlichen Problem, der PI-Regelung widmen :-)

Grüße und nochmals Danke,
Stefan

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.