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.
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; }
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...
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.
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...
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.
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.
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.
Wenn ich mich recht erinnere, heisst der Interrupt "TIMER1_CAPT_vect". Ist in der avr/interrupt.h definiert.
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.
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.
Ich habe jetzt nochmal nachgeschaut, Debug platform und Device sind schon richtig eingestellt, die habe ich noch beim Erstellen des Projekts eingestellt.
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.
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
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.
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.
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"
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
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
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?
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
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
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.
> > 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
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?
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.
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.
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!!!!!!!!
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.