www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [AVR] ISR in eine Klasse stecken


Autor: Stefan Kuhne (sk-ac)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche den Code aus Beitrag "PWM Signal auswerten" in 
mein C++ Projekt zu bekommen.

Irgendwie wollen die Interrupt Methoden nicht mit in die Klasse.
Ich nehme an, ISR wird über ein define überschrieben da ich so:
expected unqualified-id before 'extern'

bekomme.

Ohne KLASSE:: davor kann er natürlich die Attribute nicht finden. Diese 
sind ja in der Klasse.

Hat da jemand eine Lösung?

Danke,
Stefan

Autor: Michael K. (michael007)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
warum schreibt man für einen 8 bit µC ein Programm in C++...
Das versteh' ich net...

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Irgendwie wollen die Interrupt Methoden nicht mit in die Klasse.

In jeder Klasseninstanz eine eigene Instanz des Interrupthandlers? 
..keine gute Idee.. Wenns unbedingt C++ sein muss [1] dann lass die 
Interrupthandlder 'draussen' und mach deine Instanzen stattdessen per 
globaler Variable verfügbar, ein improvisierter 'this'-Zeiger sozusagen 
:-)

HTH

[1] C++ hat viele schöne Konzepte, aber für so einen kleinen µC ein 
bisschen Overkill..

Autor: Stefan Kuhne (sk-ac)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich meine bei Motorola sind das "normale" Methoden, die der Compiler 
dann entsprechend umsetzt.

Dann muss ich wohl doch auf C zurück.
Ich habe auf C++ umgestellt, weil ich mit den Objekten eine bessere 
Übersicht bekommen wollte.

Danke,
Stefan

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
g457 schrieb:
> [1] C++ hat viele schöne Konzepte, aber für so einen kleinen µC ein
> bisschen Overkill..

kommt drauf an, was man alles benutzt.
virtuelle Vererbung oder collections sind definitv overkill.

Aber ein bisschen templates und Klassen machen den Code oft 
übersichtlicher.

vor allem die Möglichkeit datenstrukturen mit Funktionen versehen zu 
können vermisse ich in C.

IgnitionHandler ig;
ig.initExplosion();

ist doch viel schöner als

IgnitionHandler ig;
IgnitionHandler_initExplosion(&ig);

und das enthält überhaupt keinen Overhead.
Oder konstruktoren.
Da entfallen die ganzen init-Aufrufe.

oder Operatorüberladung für Fixpointtypen zB.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Kuhne schrieb:
> Irgendwie wollen die Interrupt Methoden nicht mit in die Klasse.
> Ich nehme an, ISR wird über ein define überschrieben da ich so:
> expected unqualified-id before 'extern'
> bekomme.
>
> Ohne KLASSE:: davor kann er natürlich die Attribute nicht finden. Diese
> sind ja in der Klasse.

Wie genau bist Du vorgegangen? Wichtig ist, daß die Interruptroutinen 
als static deklariert werden, genauso, wie es auch mit aus C-Code 
heraus aufgerufenen C++-Funktionen gemacht werden muss.

Autor: Stefan Kuhne (sk-ac)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:

Hallo,

> Wie genau bist Du vorgegangen?

Ursprung:
ISR(TIM1_OVF_vect) //Overflow
{
  if(!ready)
    overflow ++;
}



Überarbeitet:
ROTATION::ISR(TIMER1_OVF_vect)
//Overflow
{
  if (!ready)
    overflow++;
}

Danke,
Stefan

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ISR(TIM1_OVF_vect) //Overflow

Sieh Dir mal den Aufbau des Macros ISR an, und berücksichtige, daß die 
Funktion als static deklariert sein muss, es also keinen this-Pointer 
innerhalb der Funktion gibt.

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ich auch schon mal versucht mit dem Ergebnis, es künftig bleiben zu 
lassen.
Du musst die ISR in der Klasse auf jeden fall static machen.
Außerdem muss dann sichergestellt sein, dass überhaupt eine Instanz 
schon vorhanden ist, sonst nützt selbst static nix.
Das ganze sollte dann über _attribute_(signal) oder so ähnlich 
funktionieren, damit erstens statt des ret ein reti am Ende der ISR 
steht und zweitens der Interruptvector beschrieben wird.
Aber das Ganze ist halt weder C noch C++-konform, da diese Sprachen per 
se keine Interrupts kennen. Daher sind diese Konstruktionen mehr oder 
minder Krücken des Compilers, die sich jederzeit ändern können 
(Interrupt -> Signal -> ISR).

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael K. schrieb:
> warum schreibt man für einen 8 bit µC ein Programm in C++...
> Das versteh' ich net...
Das kann man wohl über alles sagen, was nicht Assembler ist. ;)

Ich hatte mich auch schon einmal damit beschäftigt und diese "Lösung" 
hier gefunden: 
http://waterproofman.wordpress.com/2007/02/07/avr-...

So ganz hat mich das nicht überzeugt. Es gibt IMO den grundsätzlichen 
Widerspruch, dass man von einer Klasse zwar mehrere neue Instanzen 
erzeugen kann, die damit angesteuerte Hardware aber nicht gleich mit 
erzeugt wird.

Eventuell kann man die ISR ja ganz klassisch quasi in C programmieren 
und die Objekte greifen auf dessen (globale) Daten dann zu. Wenn das nur 
ein Objekt macht, dann hat man ja in der Praxis wieder eine Art 
Kapselung.

Ich könnte mir z.B. ein UART-Objekt (UART mal als nahe liegendes 
Beispiel) vorstellen, dessen Konstruktor ein Zeiger auf die Daten der 
UART-ISR übergeben wird. Der wird in dem Objekt gespeichert (und könnte 
ggf. auch geändert werden). So "bindet" man dann Objekte an die 
Hardware. Will ich eine andere Funktion an der Schnittstelle, binde ich 
ein anderes Objekt daran. Dasselbe Objekt kann ich an unterschiedliche 
UARTs binden (natürlich nur wenn es mehrere gibt).

Ich könnte mir auch gut ein Objekt als eine Art "Torwächter" vorstellen, 
der den Zugang zur SPI oder I²C-Schnittstelle kontrolliert. Oder eine 
abstrakte ADC-Klasse, deren Nachfolger entweder interne oder externe 
ADCs ansprechen...

Ich denke, es gibt schon Gründe, C++ auf Mikrocontrollern einzusetzen. 
(ich persönliche bleibe aber bei C mit Assembler als Notnagel)

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich mache das z.B. so:
// Copyright 2009 Peter Stegemann

#ifndef INTERRUPT_SERVICE_H
#define INTERRUPT_SERVICE_H

#include "Shared/Types.h"

class INTERRUPT_Service
{
  private:
    volatile uint16_t timeMillis;
    volatile uint16_t timeSeconds;

  public:
    // Start processing loop.
    void Start( void);

    // This is for the interrupt, not for you.
    void Process( void);
};

#endif
// Copyright 2009 Peter Stegemann

#include "Interrupt_Service.h"

#include "Ports.h"

#include <avr/interrupt.h>

#define INTERRUPT_TICKS_PER_SECOND  1000
#define INTERRUPT_TICKS_PER_MS    INTERRUPT_TICKS_PER_SECOND / 1000
#define INTERRUPT_CLOCK_FACTOR    ( F_CPU / INTERRUPT_TICKS_PER_SECOND) / 64

static INTERRUPT_Service* INTERRUPT_Singleton;

void INTERRUPT_Service::Start( void)
{
  timeMillis = 0;
  timeSeconds = 0;

  INTERRUPT_Singleton = this;

  // Clear counter before use. This will also clear all other settings.
  TCNT0 = 0;
  // Wakeup often.
  OCR0A = INTERRUPT_CLOCK_FACTOR;
  // Clear timer by match and split clock for timer by 64.
  INPUT_TIMERA = BIT_VALUE( WGM01);
  INPUT_TIMERB = BIT_VALUE( CS01) | BIT_VALUE( CS00);
  // Switch interrupt for compare match on.
  TIMSK0 = BIT_VALUE( OCIE0A);
}

void INTERRUPT_Service::Process( void)
{
  // Time calculation is _always_ done.
  timeMillis++;

  // Second?
  if( timeMillis == 1000)
  {
    timeSeconds++;
    timeMillis = 0;

    // Do something every second.
  }

  // Do something every millisecond.
}

ISR( SIG_OUTPUT_COMPARE0A, ISR_NOBLOCK)
{
  INTERRUPT_Singleton->Process();
}

Autor: netb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gab hier einen, meiner Meinung nach, sehr sinnvollen Patchvorschlag 
von Ron Kreymborg. Der Patch hat die Nummer #6805 (Numeric interrupt 
vectors).

Eine Erklärung und ein Beispiel ist hier zu finden:
http://jennaron.com.au/avr/classinterrupts.html

Leider scheint sich dieser Patch nicht durchgesetzt zu haben, denn 
immerhin ist der Vorschlag schon etwas älter (2007). Schade eigentlich, 
aber ich hoffe immer noch, dass der Patch irgendwann umgesetzt wird.

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.