www.mikrocontroller.net

Forum: Compiler & IDEs Input Capture Interrupt Problem


Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich wäre euch sehr dankbar für jeden Hinweis. Ich bin gerade dabei, mir 
die Interrupt-Programmierung mit Hilfe von dem GCC-Tutorial 
beizubringen. Habe den entsprechenden Teil gelesen und ein Programm für 
ATMega168 geschrieben (einfach nur zum lernen). Jetzt versuche ich das 
Programm mit dem Simulator zu simulieren und habe folgendes Problem: Bei 
der Simulation der Flanke am ICP springt der Simulator nicht zum 
ISR-Code sonder zum Anfang von main und beginnt von vorne. Ich verstehe 
nicht was ich falsch gemacht habe.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, den Code vergessen!


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

int main(void)
{
  sei();
  TIMSK1 = 0x08;
  TCCR1B = 0x82;
  while (1)  { }
  return 0;
}



ISR(TIMER1_CAPT_vect)
{
  DDRD = 0xff;
  PORTD = 0xff;
}

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast den falschen Interrupt freigegeben! Bitte gewöhn Dir gleich eine 
lesbarere Schreibweise für die I/O-Register an, siehe 
Bitmanipulation. Wenn Du geschrieben hättest
TIMSK1 = 1 << ICIE1;
dann wäre alles i.O. und ich hätte nicht erst im Datenblatt nachsehen 
müssen, was Du da eigentlich gemacht hast. Das Bit, das Du gesetzt hast, 
ist ein reserviertes (nicht belegtes) Bit. Das hätte Dir aber auch im 
I/O-View im Simulator auffallen können...

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die schnelle Antwort. Ich habe mich nach der 
Bitreihenfolge im Tutorial gerichtet und habe nicht beachtet, dass der 
ICIE-Bit bei 168 woanders sein kann. Ich werde es gleich mal 
ausprobieren. Besten Dank.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Witali Gustschin wrote:
> Vielen Dank für die schnelle Antwort. Ich habe mich nach der
> Bitreihenfolge im Tutorial gerichtet und habe nicht beachtet, dass der
> ICIE-Bit bei 168 woanders sein kann.
Eben deshalb immer die Schreibweise mit Bitnamen verwenden. Da ist es 
für den Programmierer völlig egal, an welcher Stelle das Bit wirklich 
steht und solche Sachen passieren einfach nicht. Man muss dann natürlich 
noch wissen, in welchem Register das Bit steht, aber das ist ja 
zumindest in Deinem Fall korrekt...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist mir grad noch aufgefallen:
Die globale Interrupt-Freigabe mit sei() sollte man erst dann machen, 
wenn man alle I/O-Register initialisiert hat! Wenn man das schon vor der 
Initialisierung macht, kann es zu unschönen Nebeneffekten kommen.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweis! Ich habe den Code entsprechend geändert. Es sieht 
jetzt so aus:

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

int main(void)
{
  TIMSK1 = 1 << ICIE1;
  TCCR1B = ((1 << ICNC1) | (1 << CS10));
  sei();
  while (1)  { }
  return 0;
}



ISR(SIG_INPUT_CAPTURE1)
{
  DDRD = 0xff;
  PORTD = 0xff;
}

Wenn ich jetzt im Simulator eine Flanke am ICP (Port B, Bit 0 laut 
Datenblatt) simuliere wird die Endlosschleife zwar verlassen aber der 
Pfeil springt nicht wie erwartet zum ISR-Code sonder zum Anfang von main 
und beginnt von vorne.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht muss ich irgendwelche Dateien einbinden oder so. Ich habe da 
zwar gar keine Ahnung aber wo wird die Funktion ISR definiert? Ich habe 
in den Projektdateien im Ordner External Dependancies geschaut und nicht 
mit ISR gefunden.

Autor: Heiko_S (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich mich recht erinnere, heisst der Interrupt "TIMER1_CAPT_vect". 
Ist in der avr/interrupt.h definiert.

Autor: Jojo S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du das mit dem AVRStudio gemacht hast: da gibt es zwei Stellen wo 
der Zeilprozessor eingestellt wird: in den 'Projekt / Configuration 
Options' und unter 'Debug / Select Platform and Device'. In den 
Projektoptionen ist es wichtig damit richtig compiliert wird, es wird 
ein define gemacht und das wird z.B. im io.h abgefragt. Die andere 
Einstellung ist für den Simulator damit die richtige Hardware 
eingestellt wird.

Autor: Jojo S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die Int-Vektoren sind Deviceabhängig und beide Namen liefern das gleiche 
Ergebniss. Im gcc und den Libs wird gerne mal was umbenannt bei neueren 
Versionen.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt nochmal nachgeschaut, Debug platform und Device sind 
schon richtig eingestellt, die habe ich noch beim Erstellen des Projekts 
eingestellt.

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

Bewertung
0 lesenswert
nicht lesenswert
Schuss ins Blaue:

Dreh mal hier

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

die Reihenfolge um.

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

Die io.h stellt ein paar Makros bereit, die ja nach eingestelltem
Prozessortyp variiert werden. Wenn interrupt.h davon abhängt
dann hat er mit der falschen Reihenfolge die falsche Einstellung.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die ISR heißt "ISR(TIMER1_CAPT_vect)" (kann man aus dem Namen im 
Datenblatt 'basteln', steht außerdem in <avr/iomx8.h>, DIE datei wird 
aber automatisch eingebunden, die sollst DU NICHT einbinden).

Mach mal aus der Endlos-Schleife ein
//...
  while(1) {
    asm volatile ("nop");
  }
/*ODER*/
#define DEBUG_NOP() asm volatile ("nop") 

  while(1) {
    DEBUG_NOP();
  }
dann hast du ein bischen Zeit den pin zu togglen.

hth. Jörg

Autor: Jojo S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe die 2. Version ins AVRStudio reinkopiert und es funktioniert ohne 
Probleme. Der Interrupt wird nur bei der fallenden Flanke am PB.0 
ausgelöst, für die steigende Flanke muss noch das Bit ICES1 im TCCR1B 
gesetzt werden.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
an Jahannes Stratmann

Und die ISR-Routine wird auch abgearbeitet? Bei mir wird der Interrupt 
auch ausgelöst, also die while-Schleife wird bei fallender Flanke 
verlassen. Nach Verlassen der Schleife sollte der Pfeil doch in die 
ISR-Routine springen, oder? Stattdessen springt er bei mir an den Anfang 
von main.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/interrupt.h>
#include <avr/io.h>

int main(void)
{
  TIMSK1 = 1 << ICIE1;
  TCCR1B = ((1 << ICNC1) | (1 << CS10));
  sei();
  while (1) {
  //sogar das geht ;)
    asm volatile(";");
  }
  return 0;
}

ISR(TIMER1_CAPT_vect)
{
  DDRD = 0xff;
  PORTD = 0xff;
}

So geht's bei mir (wenn man PINB0 togglet)

hth. Jörg
evtl. hilft ja ein "make clean" bzw. "clean current configuration"

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An Jörg X.

Und die ISR-Routine wird auch angesprungen und abgearbeitet?

Wie mache ich "make clean" bzw. "clean current configuration"?

Danke für die Antwort

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die ISR wird angesprungen und auch korrekt wieder verlassen.

>Wie mache ich "make clean" bzw. "clean current configuration"?

Wenn du das AVR-Studio zum Programmieren/compilieren nutzt, führen viele 
Wege nach Rom ;) :
 - F12
 - "Build"->"Clean"
 - das blaue Kreuz, in der GCC-Tool bar

hth, Jörg

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sagt mal, woher weiß der Compiler was ISR(..) bedeutet? Das sollte doch 
eigentlich in irgend einer in das Projekt eingebundener Datei definiert 
sein, oder??? Ich habe alle eingebundenen Dateien durchsucht und keine 
Definition für ISR gefunden. Oder verstehe ich etwas falsch?

Ich habe im Code ISR einfach durch Klaus ersetzt und der Compiler frist 
es und bringt keine Fehlermeldungen. Ist das normal?

Autor: Witali G. (witali)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Meine Projekt-Dateien schauen so aus.

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider weiß der Compiler nichts von Interrupt-Funktionen. Wenn du da 
Klaus hinschreibst, findet er halt eine Funktion mit Namen Klaus, was 
ihn höchsten zu der Warnung veranlasst, daß die nicht vorher deklariert 
wurde. Nur wird eine Funktion Klaus niemals vom Interrupt angesprungen.

Die "Magie" einer Interruptfunktion steckt im Makro ISR, das in 
<avr/interrupt.h> definiert ist, und in den Makros für die 
Interruptnamen. Die sind prozessorabhängig, und daher muß vor 
<avr/interrupt.h> <avr/io.h> eingebunden sein, damit das funktioniert. 
Es ist eigentlich nie verkehrt, <avr/io.h> immer als oberstes #include 
hinzuschreiben.

Verschreibt man sich bei ISR oder dem Interruptnamen, wird das 
entsprechende Makro nicht ausgeführt. Für den Compiler steht dann da 
eine normale Funktion.

Oliver

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich dachte, bei einem unbekannten Ausdruck wird der Compiler eine 
Fehlermeldung bringen, wie ich es aus Visual C++ kenne. Er bringt nicht 
einmal die Warnung dass Klaus nicht deklariert wurde.

Zwei Warnungen meldet er:

../ds.c:21: warning: return type defaults to `int'
../ds.c: In function `Klaus':

../ds.c:24: warning: control reaches end of non-void function

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

Bewertung
0 lesenswert
nicht lesenswert
Witali Gustschin wrote:
> ich dachte, bei einem unbekannten Ausdruck

wo ist denn da eine unbekannter Ausdruck?

Da ist nichts unbekannt!
Du definierst eine Funktion!

> Zwei Warnungen meldet er:
>
> ../ds.c:21: warning: return type defaults to `int'
> ../ds.c: In function `Klaus':

Alleine diese Warnung muss dich schon stutzig machen.
Eine ISR hat keinen Returntyp (void Funktion).
Wenn der Compiler da also laut Standardregeln eine int
Funktion daraus macht, dann hat er das ISR Makro nicht
richtig gesehen.

Dinge auf die man aufpassen muss
* #include <avr/io.h>
  #include <avr/interrupt.h>

  Am besten in der Reihenfolge, dann kann schon mal mit der
  Prozessorerkennung nicht viel schief gehen

* Der Name des Vectors in der ISR muss stimmen.
  Nicht darauf verlassen, dass der Compiler schon meckern
  wird. Lieber 3 mal (mit der prozessorspezifischen ioxxx.h)
  abklären, ob der Name stimmt. Im AVR Studio wird der der
  Name der Prozessorspezifischen ioxxx.h nach dem ersten
  Compilieren unter 'External Dependencies' angezeigt und
  lässt sich von dort aus auch öffnen.

* Sowohl beim Compiler als auch beim Simulator muss der
  übereinstimmende, korrekte Prozessor eingetragen sein.

* Bei der Interruptfreigabe darauf achten, dass auch der
  richtige Interrupt durch schreiben des richtigen Wertes
  in das richtige Register freigegeben wird

* Nur die Interrupts freigeben, für die auch tatsächlich eine
  ISR existiert

* sei() muss aufgerufen werden

Wenn diese Dinge stimmen, dann kann eigentlich nichts mehr
schief gehen. Es sei denn bei der Installation des Compilers
bzw. AVR-Studio ist irgendetwas schief gelaufen.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>
> Alleine diese Warnung muss dich schon stutzig machen.
> Eine ISR hat keinen Returntyp (void Funktion).
> Wenn der Compiler da also laut Standardregeln eine int
> Funktion daraus macht, dann hat er das ISR Makro nicht
> richtig gesehen.


Wo sieht der Compiler das ISR Makro und was mache ich damit er das 
richtig sieht?

>
> Wenn diese Dinge stimmen, dann kann eigentlich nichts mehr
> schief gehen. Es sei denn bei der Installation des Compilers
> bzw. AVR-Studio ist irgendetwas schief gelaufen.

Es sollte doch eigentlich alles stimmen. Es haben einige hier meinen 
Code auf ihren Rechnern im AVR-Studio simuliert und es ging problemlos.

Wie kann die Installation z. B. schief gelaufen sein? Was sollte man bei 
der Installation beachten, dass alles in Ordnung ist?

Danke

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Witali Gustschin schrieb:

> Es sollte doch eigentlich alles stimmen. Es haben einige hier meinen
> Code auf ihren Rechnern im AVR-Studio simuliert und es ging problemlos.

Ich sehe keinen richtigen Code von dir. Deine Angaben zu Code sind 
alle von anderen geäandert und kommentiert worden. Hast du mal den Code 
von anderen simuliert?

Autor: Jojo S. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
doch, Witali hat im 7. Posting seinen Code geschrieben, und der läuft 
auch hier. AVRStudio 4.13 und gcc von 2007/12.
Die ISR-Vektornamen sind auch beide ok, werden aus iom8x.h geholt:
/* Timer/Counter1 Capture Event */
#define TIMER1_CAPT_vect    _VECTOR(10)
#define SIG_INPUT_CAPTURE1    _VECTOR(10)

Ich habe beim Simulator das 'View / Disassembler' eingeschaltet, da 
sieht man besser was passiert. Nach dem rücksetzen von PB.0 braucht man 
noch 4 Einzelschritte bis die ISR angesprungen wird.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An  Johannes Stratmann

Ich habe WinAVR installiert und AVR-Studio benutzt den Compiler daraus. 
Vielleicht ist das die Ursache warum es bei mir nicht geht, obwohl es 
bei dir geht.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hurra!!!

Ich habe jetzt auf meinem privaten Rechner ausprobiert und das 
funktioniert. Die Versuche davor habe ich auf dem Rechner in der Arbeit 
durchgeführt. Jetzt  ist zumindest klar, dass auf dem Notebook dort mit 
der Installation was nicht in Ordnung ist. Ich werde morgen WinAVR und 
AVR-Studio neu installieren. Ich danke euch allen für eure 
Unterstützung. Einfach Spitze, dass es hier diese Seite und euch alle 
gibt, die sich für einen Anfänger wie ich Zeit nehmen.

VIELEN HERZLICHEN DANK!!!!!!!!

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die sicherste Methode zur Überprüfung, ob bei er Deklaration der ISR 
alles in Ordnung ist, ist ein Blick in das .lss-File. Da sieht man die 
Vektortabelle, die defaultmässig mit <__bad_interrupt> gefüllt wird.

00000000 <__vectors>:
   0:  0c 94 2a 00   jmp  0x54  ; 0x54 <__ctors_end>
   4:  0c 94 47 00   jmp  0x8e  ; 0x8e <__bad_interrupt>
   8:  0c 94 47 00   jmp  0x8e  ; 0x8e <__bad_interrupt>
...
50:  0c 94 47 00   jmp  0x8e  ; 0x8e <__bad_interrupt>

Hat alles mit der oder den ISR's geklappt, finden sich da die 
entsprechenden <_vector_xx>-Einträge.

Oliver

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aha...  und wo finde ich dieses .lss-File

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Witali Gustschin wrote:
> aha...  und wo finde ich dieses .lss-File
Wenn du mit AVRStudio arbeitest, dann musst Du erstmal dem Programm 
erklären, dass Du überhaupt ein .lss-File haben möchtest. Standardmäßig 
wird das nämlich nicht erzeugt. Also unter "Project | Configuration 
Options" in dem Tab "General" unten bei "Generate List File" ein Häkchen 
machen. Das List-File wird dann im selben Verzeichnis wie das Projekt 
(Sourcecode) abgelegt. Im Project-Tree im AVRStudio kannst Du es dann 
unter "Other Files" finden.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweis!!!

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.