mikrocontroller.net

Forum: Compiler & IDEs Interruptssteuerung Atmel


Autor: A. R. (redegle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kann mir vielleicht jemand sagen, wo ich im Internet eine gute Erklärung 
zur Interruptsteuerung bei einem Atmel finde?

Ich hab mich an einem Programm für einem Atmega2560 probiert jedoch ohne 
Erfolg.

Ziel:
- Ich gebe eine PWM aus (Zähler 5). Dies funktioniert.
- Ich lasse den Counter 1 bis 15625 hochzählen.
- Bei einem Overflow soll per Interrupt der Duty-Cyle erhöht werden.
 #include <avr/io.h>
 #include <avr/interrupt.h>

int main(void)
{

/*
Hinweis:
16Bit-Register immer direkt hintereinander auslesen
*/


// Alle Ports als Ausgänge
  DDRA = 0b11111111;
  DDRB = 0b11111111;
  DDRC = 0b11111111;
  DDRD = 0b11111111;
  DDRE = 0b11111111;
  DDRF = 0b11111111;
  DDRG = 0b11111111;
  DDRH = 0b11111111;
  DDRJ = 0b11111111;
  DDRK = 0b11111111;
  DDRL = 0b11111111;

  //Timer_Counter 5
  TCCR5A = 0b10100010;    //PWM Konfirguration
  TCCR5B = 0b00011001;  //PWM Konfirguration
  TCCR5C = 0b00000000;  //PWM Konfirguration
  ICR5   = 1024;          // Zähler auf den Endwert 1024
  // 3 PWMs verügbar
  OCR5A = 0;      // PINL3 
  OCR5B = 0;      // 
  OCR5C = 0;      // 

  // Timer 1 Initialisieren
  // Als Timer verwenden. // Vorteiler 1
  // 16Mhz Takt, zählen bis 15625 --> 1024 Overflows pro Sekunde 
  TCCR1A = (0<<WGM10) | (0<<WGM11);
  TCCR1B = (1<<WGM12) | (1<<WGM13)|(0<<CS12) |(0<<CS11)| (1<<CS10);
  ICR1 = 15625;  


  // Interrupts aktivieren
  sei();
  TIMSK5 = (1<<TOIE5);
  //Dauerschleife
  while(1)
  {
  }

return 0;
}

ISR(TIMER1_OVF_vect)
{
    //Duty-Cyle erhöhen
    if(OCR5A<1024)
    {
      ++OCR5A;
    }
    else
    {
      OCR5A=0;
    }
    // Interruptbit zurücksetzten
    TIFR5=0;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. R. schrieb:
> Hallo,
>
> kann mir vielleicht jemand sagen, wo ich im Internet eine gute Erklärung
> zur Interruptsteuerung bei einem Atmel finde?

Im Datenblatt steht alles was du wissen musst.

>   //Timer_Counter 5
>   TCCR5A = 0b10100010;    //PWM Konfirguration
>   TCCR5B = 0b00011001;  //PWM Konfirguration
>   TCCR5C = 0b00000000;  //PWM Konfirguration
>   ICR5   = 1024;          // Zähler auf den Endwert 1024

Super!
Das macht es so wahnsinnig einfach da nachzuvollziehen, was du da 
eigentlich alles eingestellt hast.

Nur weiter so!
Schiess dir weiter selber ins Knie und freu dich daran.


>   TCCR1A = (0<<WGM10) | (0<<WGM11);
>   TCCR1B = (1<<WGM12) | (1<<WGM13)|(0<<CS12) |(0<<CS11)| (1<<CS10);

Na also: Geht doch auch anders!
Warum hier und beim Timer 5 nicht?


> // Interrupts aktivieren
>  sei();
>  TIMSK5 = (1<<TOIE5);

Ähm. Wolltest du dich nicht an den Overflow vom Timer 1 klemmen?
Zumindest hast du eine ISR für den geschrieben. Hier gibst du aber den 
Interrupt für den Overflow vom Timer 5 frei!


> ISR(TIMER1_OVF_vect)
> {
>     //Duty-Cyle erhöhen
>     if(OCR5A<1024)
>     {
>       ++OCR5A;
>     }
>     else
>     {
>       OCR5A=0;
>     }
>     // Interruptbit zurücksetzten
>     TIFR5=0;

Was immer du hier zurücksetzen willst: lass es
Das Flag, welches zum Aufruf der ISR geführt hat, wird automatisch durch 
den Aufruf zurückgesetzt.

Autor: A. R. (redegle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Im Datenblatt steht alles was du wissen musst.

Wo finde ich z.B. den unteren Befehl oder was er genau macht außer das 
Interrupt aufrufen?
Sicherung der Register, löschen des Interruptbit etc.
ISR(TIMER1_OVF_vect)
{
}

Im Datenblatt finde ich den Interruptvektor aber nicht die notwendigen 
Befehle zum aufrufen.

>Na also: Geht doch auch anders!
>Warum hier und beim Timer 5 nicht?

Weil der Timer 5 vor längerer Zeit programmiert wurde.
Ich habe das Programm lediglich erweitert.
Der Programmierstil verändert sich mit der Zeit.

>Ähm. Wolltest du dich nicht an den Overflow vom Timer 1 klemmen?
>Zumindest hast du eine ISR für den geschrieben. Hier gibst du aber den
>Interrupt für den Overflow vom Timer 5 frei!

Das könnte der Fehler sein danke für den Hinweis.
Ist es normal, dass das Overflowflag in der Simulation nicht gesetzt 
wird?

>Was immer du hier zurücksetzen willst: lass es
>Das Flag, welches zum Aufruf der ISR geführt hat, wird automatisch durch
>den Aufruf zurückgesetzt.

Mit Aufruf meinst du diese Funktion?
ISR(TIMER1_OVF_vect)
{
}

Habe Interrupts bis jetzt nur bei nem PIC in Assembler programmiert.

Autor: A. R. (redegle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aktuelle Version des Programms.
 #include <avr/io.h>
 #include <avr/interrupt.h>

int main(void)
{

/*
Hinweis:
16Bit-Register immer direkt hintereinander auslesen
*/

// Alle Ports als Ausgänge
  DDRA = 0b11111111;
  DDRB = 0b11111111;
  DDRC = 0b11111111;
  DDRD = 0b11111111;
  DDRE = 0b11111111;
  DDRF = 0b11111111;
  DDRG = 0b11111111;
  DDRH = 0b11111111;
  DDRJ = 0b11111111;
  DDRK = 0b11111111;
  DDRL = 0b11111111;

  //Timer_Counter 5
  TCCR5A = (1<<COM5A1 | 0<<COM5A0 | 1<<WGM51); // Port PINL3 als Fast PWM max. 16Bit (clear on compare),   
  TCCR5B = (1<<WGM53  | 1<<WGM52  | 0<< CS52 | 0<<CS51 | 1<<CS50); // Fast PWM, Prescaller = 1
  ICR5   = 1024;          // Zähler auf den Endwert 1024
  // 3 PWMs verügbar
  OCR5A = 0;      // PINL3 
  OCR5B = 0;      // PWMB nicht in gebrauch
  OCR5C = 0;      // PWMC nicht in gebrauch

  // Timer 1 Initialisieren
  // Als Timer verwenden. // Vorteiler 1
  // 16Mhz Takt, zählen bis 15625 --> 1024 Overflows pro Sekunde 
  TCCR1A = (0<<WGM10) | (0<<WGM11);
  TCCR1B = (1<<WGM12) | (1<<WGM13)|(0<<CS12) |(0<<CS11)| (1<<CS10);
  ICR1 = 15625;  


  // Interrupts aktivieren
  sei();          // Setzt Globales Interrupt Enable
  TIMSK1 = (1<<TOIE1);  // Overflowflag des Timers 1 setzten

  //Dauerschleife
  while(1)
  {
  }

return 0;
}

ISR(TIMER1_OVF_vect)
{
    //Duty-Cyle erhöhen
    if(OCR5A<1024)
    {
      ++OCR5A;
    }
    else
    {
      OCR5A=0;
    }
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. R. schrieb:
>>Im Datenblatt steht alles was du wissen musst.
>
> Wo finde ich z.B. den unteren Befehl oder was er genau macht außer das
> Interrupt aufrufen?

Den 'Befehl' findest du dort gar nicht.
Aber das das eine Interrupt Funktion einleitet kann man wissen.
Und alles dazu nötige findet sich im Kapitel über Interrupts.

> Sicherung der Register, löschen des Interruptbit etc.

Wozu brauchst du das?
Als C-Programmierer interessiert dich das alles nicht.
Alles was du wissen musst ist: Wenn eine ISR betreten wird, wird das 
entsprechende Flag, welches die Abarbeitung ausgelöst hat wieder 
gelöscht. Das steht bei jedem Interrupt-Flag bei allen Registern im 
Datenblatt immer dabei. Einzige Ausnahme: Der RxD Interrupt der UART. 
Dieses Interrupt Anforderung wird erst dann zurückgenommen, wenn das UDR 
Register ausgelesen wird. Aber auch das steht im Datenblatt. Wo? Na bei 
der Beschreibung des Interrupt Request Bits im entsprechenden Register 
der UART.

> Im Datenblatt finde ich den Interruptvektor aber nicht die notwendigen
> Befehle zum aufrufen.

Du rufst auch einen Interrupt nicht auf.
Eine Interrupt Funktion wird von der Hardware aufgerufen. Ein bestimmtes 
Ereignis tritt ein und als Folge davon kommt eine Handlungskette ins 
laufen, die darin mündet, dass deine ISR-Funktion aufgerufen wird.

> Ist es normal, dass das Overflowflag in der Simulation nicht gesetzt
> wird?

Der Simulator hat zwar so seine Bugs, aber das Overflwo Flag wird recht 
zuverlässig gesetzt. Leg einen Breakpoint in die ISR und sieh nach ob 
sie aufgerufen wird.


> Mit Aufruf meinst du diese Funktion?

Ja.
Sobald ein Ereignis eintritt (wie zb ein Overflow) merkt sich die CPU 
das mit einem Bit in einem Register. Bei nächster Gelegenheit und 
freigegebenen Interrupts wird dann die ISR aufgerufen und das 
entsprechende Anforderungsbit wieder gelöscht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt

Autor: A. R. (redegle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe!
Ich habe das Problem gefunden.
Ich darf den Timer nicht im "Clear Timer on Compare Match (CTC) Mode" 
verwenden.

Autor: A. R. (redegle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Programm:
Erzeugung eines Dreicks von 0 bis 5V mittels einer 10Bit PWM mit einer 
Periodendauer von 2Sekunden.
Vielleicht hat jemand ein paar Verbesserungsvorschläge.

 #include <avr/io.h>
 #include <avr/interrupt.h>


volatile int Temp=0;
// Jeder Zugriff auf die Variable Temp erfolgt als Zugriff auf den Speicher, es werden keine Register verwendet.

int main(void)
{
  
/*
Hinweis:
16Bit-Register immer direkt hintereinander auslesen
*/

// Alle Ports als Ausgänge
  DDRA = 0b11111111;
  DDRB = 0b11111111;
  DDRC = 0b11111111;
  DDRD = 0b11111111;
  DDRE = 0b11111111;
  DDRF = 0b11111111;
  DDRG = 0b11111111;
  DDRH = 0b11111111;
  DDRJ = 0b11111111;
  DDRK = 0b11111111;
  DDRL = 0b11111111;

  //Timer_Counter 5
  TCCR5A = (1<<COM5A1 | 0<<COM5A0 | 1<<WGM51); // Port PINL3 als Fast PWM max. 16Bit (clear on compare),   
  TCCR5B = (1<<WGM53  | 1<<WGM52  | 0<< CS52 | 0<<CS51 | 1<<CS50); // Fast PWM, Prescaller = 1
  ICR5   = 1024;          // Zähler auf den Endwert 1024
  // 3 PWMs verügbar
  OCR5A = 0;      // PINL3 
  OCR5B = 0;      // PWMB nicht in gebrauch
  OCR5C = 0;      // PWMC nicht in gebrauch

  // Timer 1 Initialisieren
  // Als Timer verwenden. // Vorteiler 1 // Modus normel zählt bis 65536
  // 16Mhz Takt
  TCCR1A = (0<<WGM10) | (0<<WGM11);
  TCCR1B = (0<<WGM12) | (0<<WGM13)|(0<<CS12) |(0<<CS11)| (1<<CS10);


  // Interrupts aktivieren
  sei();          // Setzt Globales Interrupt Enable
  TIMSK1 = (1<<TOIE1);  // Overflowenable des Timers 1 setzten
  TCNT1 = 49911;  
  //Dauerschleife
  while(1)
  {
  }

return 0;
}

ISR(TIMER1_OVF_vect)
{
  //int Temp=0; Wird ggf. in ein Register geschrieben und nach der ISR überschrieben
  TCNT1 = 49911;  // Startwert des Timers, damit 1024 Interrupts pro Sekunde ausgeführt werden
  //Duty-Cyle erhöhen

  if(Temp==0)// Temp 0 --> aufzählen
  {
    if(OCR5A==1023)
    {
      OCR5A=1024;
      Temp=1;
    }
    else
    {
      ++OCR5A;
    }
  }

  if(Temp==1)// Temp 1--> abzählen
  {
    if(OCR5A==1)
    {
      OCR5A=0;
      Temp=0;
    }
    else
    {
      --OCR5A;
    }
  }
}

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  A. R. (redegle)

>Erzeugung eines Dreicks von 0 bis 5V mittels einer 10Bit PWM mit einer
>Periodendauer von 2Sekunden.

Easy.

>Vielleicht hat jemand ein paar Verbesserungsvorschläge.

Dein "manuelles Vorlanden" des Timers ist eine Steinzeitmethode und 
somit Schrott.

>Ich darf den Timer nicht im "Clear Timer on Compare Match (CTC) Mode"
>verwenden.

Das Gegenteil ist der Fall. Nutze den CTC Modus und du wirst einen 
superschicken PMW- und Funktionsgenerator haben. Der Rest ist eine 
triviale Fleißaufgabe för den Schöler!

MFG
Falk

Autor: A. R. (redegle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das Gegenteil ist der Fall. Nutze den CTC Modus und du wirst einen
>superschicken PMW- und Funktionsgenerator haben. Der Rest ist eine
>triviale Fleißaufgabe för den Schöler!

Könntest du das bitte etwas genauer erläutern?
Im CTC Modus wird ein Interrupt erst beim overflow ausgelöst oder kann 
ich da das "Output Compare Flag" verwenden?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  A. R. (redegle)

>Im CTC Modus wird ein Interrupt erst beim overflow ausgelöst oder kann

Nö, beim CTC gibt es keinen Overflow, "nur" einen Compare Match 
Interupt, das reicht aber. Dait hat man eine feste, zuverlässige 
Zeitbasis, in der man eine Tabelle oder Berechung für die Kurvenform 
durchgehen kann. Etwa so, wenn gleich das ein anderes Problem ist.

Beitrag "Re: 16 unabhängig arbeitende Oszillatoren ?"

MFG
Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.