mikrocontroller.net

Forum: Compiler & IDEs Compiler fehlerhaft oder uC ?


Autor: tronic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wenn ich am Atmega8, die zwei Interrupts eingeschaltet habe,
INT0, INT1 ... scheint es schwierigkeiten zu geben.
Auf dem INT1 hab ich den Clock von der Tastatur, wo
bei jeder fallenden Flanke einen Output-Zustand wechselt.

solange ich folgenden befehl:

GIFR|=(1<<INTF0);

nicht aktiviere, funktioniert es tadellos,
sobald dieser jedoch eingeschaltet ist - entspricht der Output-Zustand
nicht mehr dem des Clocks (nur annähernd).

am INT0 ist die Datenleitung der Tastatur angeschlossen (so
programmiert das auch auf negative Flanke reagiert)

die funktion ISR(INT1_vect)
{} ist aber nicht vorhanden...

interessanterweise, kann ich bei Outputs die immer auf High sind, mit
dem Oszilloskop ein kurzzeitiges low (paar ns) fesstellen. Diese
stimmen genau mit der Datenleitung enthaltende neg. Flanken überrein,
also:

obwohl der externe Interrupt wo die Datenleitung angehängt ist,
aktiviert ist, jedoch keine Funktion hierfür vorgesehen ist. setzt der
Mikrocontroller alle Outputs bei einer negativen Flanke, alle Outputs
kurzfristig auf 0 (paar ns).

wieso das? ist das Hardwarebedingt? wenn ja, ziemlich blöd!

danke für Hilfe
tronic

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hmmm, ich weiß nicht, ob ich Dich jetzt richtig verstanden habe:

Du gibst die externen Interrupts frei, hast keine ISR im Programm und
wunderst Dich, daß der AVR abstürzt?
Der ATmega erkennt den IRQ, holt die Adresse aus dem Interruptvektor
und springt dahin. Da Du ja keine ISR definiert hast, weiß nur der
Compiler, was da nun drinsteht, mit Sicherheit nichts, was den IRQ
sinnvoll bearbeitet und beendet...

Ich verstehe also den Sinn Deiner Frage nicht so ganz.

Gruß aus Berlin
Michael

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> mit Sicherheit nichts, was den IRQ
> sinnvoll bearbeitet

Doch, der default interrupt vector, und der besteht aus einem
Sprung nach Adresse 0.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> obwohl der externe Interrupt wo die Datenleitung angehängt ist,
> aktiviert ist, jedoch keine Funktion hierfür vorgesehen ist.

Wozu aktivierst du ihn, wenn du keine Interrupt-Funktion hast?

Autor: tronic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Doch, der default interrupt vector, und der besteht aus einem
Sprung nach Adresse 0."

ok. aber wieso setzt der Mikrocontroller bei diesem Sprung, bzw.
Interrupt, für paar ns die Ausgänge auf 0 - der dürfte laut Code gar
nichts auf null setzen, bzw. da ja keine Funktion für den INterrupt
vorhanden ist, die so irgendwas integriert hätte?

"Wozu aktivierst du ihn, wenn du keine Interrupt-Funktion hast?"

wozu, einfach so ;) ... ich meine ich könnte ja den zweiten externen
Interrupt vielleicht brauchen, wenn aber dadurch nur schon der erste
interrupt nicht ganz korrekt funktioniert, bzw. dadurch irgendwie
unterbrochen wird... ist mir das ein rätsel.

so sieht mein Code aus:

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

void ini();

ISR(INT1_vect) //Clock
{
clk=!clk;
      if(clk)
      {
        PORTB&=~(1<<PB1);
      }
      else
      {
        PORTB|=(1<<PB1);
      }
}

void ini() //Initialisierung
{
DDRD = 0x00; // PortD als Eingang
DDRC = 0xFF; // PortC als Ausgang
DDRB = 0xFF; // PortB als Ausgang

PORTD=0xff; //Pullup aktivieren

MCUCR|=(1<<ISC11); //Fallende Flanke für Data
MCUCR&=~(1<<ISC10);

MCUCR|=(1<<ISC01); //Fallende Flanke für Clock
MCUCR&=~(1<<ISC00);

GIMSK|=(1<<INT1); //Externe Interrupts einschalten

//GIMSK|=(1<<INT0); =>>> sobald dieser aktiviert wird, funktioniert
es nicht mehr korrekt!! bei jeder neg. Flanke am INT0, wird an jedem
Ausgang für paar ns. der Pegel auf 0 gesetzt. komisch?

GIFR|=(1<<INTF1); //Interruptsroutine anspringen ON
GIFR|=(1<<INTF0);
}

int main()
{

ini();
sei();

PORTC=0xFF;
PORTB=0xFF;

  while(1)
  {}


return 0;
}

Autor: tronic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die variable clk. ist natürlich noch definiert

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie andere oben schon gesagt haben: Du darfst keinen Interrupt
aktivieren, für den Du keinen Handler schreibst! Der Compiler erzeugt
für alle Interrupts, für die kein Handler vorliegt, einen default
Handler, der, wie Jörg schon sagte, aus einem Sprungbefehl zur Adresse
0 besteht. An der Adresse 0 steht der RESET-Vektor. Das heißt, dass
beim Auftreten eines solchen Interrupts der µC geresettet wird. Es ist
völliger Unsinn, einen Interrupt freizugeben, bei dessen Auftreten
nichts definiertes passiert.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spendiere deinem Programm noch eine INT0-ISR.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> wenn aber dadurch nur schon der erste interrupt nicht ganz korrekt
> funktioniert

Der funktioniert völlig korrekt.
Das einzige was hier nicht richtig ist, ist dein Program.

Ein freigegebener Interrupt für den es keinen Handler gibt,
ist ein logischer Fehler.

Du gehst von der Annahme aus, dass ein freigegebener Interrupt
für den es keinen Handler gibt, auch nichts bewirkt. Diese
Annahme ist aber falsch. Die Macher von avr-gcc haben sich
entschieden, dass in so einem Fall nicht einfach nur nichts
geschehen soll (wäre auch möglich gewesen), sondern dass
in diesem Fall das Programm (inklusive Initialisierung der
C-Laufzeitumgebung) wieder von vorne anfangen soll.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BTW: Was soll das da...
> GIFR|=(1<<INTF1); //Interruptsroutine anspringen ON
...bewirken? Diese Anweisung löscht im Prinzip nur das Interrupt-Flag
INTF1. Wenn Du das Flag löschen willst, um sicherzugehen, dass ein
bereits gesetztes Flag keinen Interrupt auslöst, dann musst Du das Flag
vor der Freigabe des Interrupts löschen. Danach geschieht das
automatisch, wenn die ISR ausgeführt wird.

Abgesehen davon löscht die Anweisung "GIFR|=(1<<INTF1);" nicht nur
INTF1, sondern alle Interrupt-Flags in GIFR! Löschen von
Interrupt-Flags sollte man immer ohne "|" machen, um sicherzugehen,
dass nur die gewünschten Flags gelöscht werden. Also wenn überhaupt,
dann "GIFR = (1<<INTF1);". Der "|="-Operator führt eine
Read-Modify-Write-Operation durch, wobei erst das GIFR in ein
Rechenregister eingelesen, anschließend die ODER-Operation mit der
konstanten Maske "(1<<INTF1)" durchgeführt und zum Schluss das ganze
wieder ins GIFR zurückgeschrieben wird. Dabei werden alle Bits, die
vorher (beim Lesen) "1" waren, mit einer 1 beschrieben, wodurch sie,
da es sich um Interrupt-Flags handelt, gelöscht werden. Da das u.U.
nicht erwünscht ist, sollte man das grundsätzlich ohne "|" schreiben.

Autor: tronic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uiii hab ich da doch einiges falsch angenommen... dann
also vielen Dank um die Korrekturen.

die Korrektur von jonny, betreff "GIFR|=(1<<INTF1);" habe ich aber
nicht ganz getscheggt...

>>abei werden alle Bits, die
>>vorher (beim Lesen) "1" waren, mit einer 1 beschrieben, wodurch
sie,
>>da es sich um Interrupt-Flags handelt, gelöscht werden.

mit GIFR=(1<<INTF1); ... werden aber doch auch alle Bits gelöscht, und
nur das INTF1 bit gesetzt ... bisher habe ich das so gelernt: mit dem |
Operator kann bitweise gesetzt werden, ohne die anderen Bits zu
verändern..... hm

mit freundlichen Grüssen
tronic

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> mit GIFR=(1<<INTF1); ... werden aber doch auch alle Bits gelöscht,
> und nur das INTF1 bit gesetzt

Ja. Genau das willst du aber auch.

Das erklärt sich dadurch, dass ein Interrupt Flag dadurch gelöscht
wird, dass man eine 1 an die entsprechende Stelle schreibt.

Du möchtest daher nur eine einzige 1 in das GIFR Register schreiben,
nämlich an die INTF1 Position. Alle anderen Bits sollen beim
Schreibzugriff 0 sein, damit sich das Interrupt Flag Bit nicht
verändert.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Interrupt Flag Register verhalten sich in dieser Hinsicht
anders als die normalen Register:

Eine 1 bedeutet: Bit löschen
Eine 0 bedeutet: Bit nicht verändern

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.