Input Capture Interrupt Problem

#780323
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.
#780334
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
1
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...
#780371
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...
#780454
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.
Gast #780489
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.
#780512
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.
Gast #780514
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
1
//...
2
  while(1) {
3
    asm volatile ("nop");
4
  }
5
/*ODER*/
6
#define DEBUG_NOP() asm volatile ("nop") 
7

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

hth. Jörg
Gast #780527
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.
#780826
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.
Gast #780835
Lesenswert?

1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3

4
int main(void)
5
{
6
  TIMSK1 = 1 << ICIE1;
7
  TCCR1B = ((1 << ICNC1) | (1 << CS10));
8
  sei();
9
  while (1) {
10
  //sogar das geht ;)
11
    asm volatile(";");
12
  }
13
  return 0;
14
}
15

16
ISR(TIMER1_CAPT_vect)
17
{
18
  DDRD = 0xff;
19
  PORTD = 0xff;
20
}

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

hth. Jörg
evtl. hilft ja ein "make clean" bzw. "clean current configuration"
Gast #780849
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
#780854
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?
Gast #780875
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
#780883
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
#780895
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.
#780922
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
Gast #781006
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.
Angehängte Dateien:
#781168
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!!!!!!!!
Gast #781453
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
#781719
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren