Forum: Compiler & IDEs Codeoptimierungsproblem


von Polat (Gast)


Lesenswert?

Hallo zusammen,
kann mir jemand sagen warum der Code nicht funktioniert??

Problem ist, dass die Interruptroutine mehrmals ausgeführt wird, obwohl 
ich nur ein Zeichen über die Serielle Schnittstelle sende.

Meine Vermutung war, dass die Variable "UART_ReceivedChar " nicht 
richtig funktioniert obwohl es als volatile deklariert ist 
(Codeoptimierung)
deshalb die Frage auch wie ich die Codeoptimierung ausschalten kann.

SIGNAL(SIG_UART_RECV)
{
    /* Indicate that the UART has received a character */
    UART_RxChar = inp(UDR);
    gemessen_2 = (gemessen_2 + 1);
    UART_ReceivedChar = 1;
    cli();

    /* Store received character */

}


int main (void) {
 for (;;) {
 sei();

    while(!UART_ReceivedChar)
    UART_ReceivedChar = 0;
    UartPrintF ("test %05d ", gemessen_2);
    gemessen_2=0;
}}

von Joerg Wunsch (Gast)


Lesenswert?

Weil Du bereits den allerersten Punkt der FAQ nicht
gelesen hast. ;-)

Die Frage kommt nun wirklich in der Woche dreimal...

http://savannah.nongnu.org/download/avr-libc/doc/avr-libc-user-manual/main.html

Von dort zur FAQ weiterklicken (den Rest aber auch mal mit
lesen ;-).

von Christian Schifferle (Gast)


Lesenswert?

Warum schaltest du die Interrups immer an und aus.
Es reicht, wenn du den Befehl sei() vor der for-Schleife einbaust. Das 
cli() in der Interrupt-Routine kannst du weglassen.
Ich gehe mal davon aus, dass du den UART Receive Interrupt aktiviert 
hast.

Gruss
Christian

von Peter D. (peda)


Lesenswert?

cli(); im Interrupt ist Blödsinn, das ist doch schon aus.

Es sei denn der Compiler ist so verrückt und schummelt Dir im 
Interrupteintritt ein "SEI" mit rein.

Dann muß es nämlich krachen, da das Interruptflag erst beim Lesen von 
UDR gelöscht wird. Und daher ruft sich der Interrupt nach dem 
eingeschmuggelten "SEI" einfach wieder selber auf.

Sieh Dir doch mal das Assemblerlisting an, ob da ein fehlerhaftes "SEI" 
mit drin ist.


Peter

von mikki merten (Gast)


Lesenswert?

@polat
Du solltest dich mal mit dem UART Status-Register UCSRA bzw. USR 
beschäftigen. Der RX Interrupt wird ja auch ausgeführt, wenn ungültige 
oder gar kein Zeichen im Receive-Buffer steht. Mal ganz abgesehen von 
dieser unsinnigen CLI/SEI Sequenz.

von Joerg Wunsch (Gast)


Lesenswert?

@Peter: nein, der Compiler macht das nicht freiwillig.
Eine mit SIGNAL() deklarierte ISR läßt die Interrupts
abgeschaltet.  Lediglich eine mit INTERRUPT() deklarierte
würde sie einschalten.  RTFdoc.

von Polat (Gast)


Lesenswert?

Hallo nochmal,
Danke, dass ihr euch das Problem angeschaut habt.
Ich habe aber inzwischen heraus gefunden, dass ich nach der While 
schleife keine Geschweifte-klammern hatte und dadurch eben die nächste 
Anweisung (UART_ReceivedChar = 0;) immer ausgeführt wurde.Mit Klammern 
siehe unten funktioniers.

while(!UART_ReceivedChar) {}
    UART_ReceivedChar = 0;

<<Warum schaltest du die Interrups immer an und aus.
Die For-Schleife zählt eigentlich eine Variable hoch und in der Zeit 
darf keine Interrupt ausgelöst werden.

Nochmal Danke!

von Polat (Gast)


Lesenswert?

<<Warum schaltest du die Interrups immer an und aus?

also jetzt habe ich den Code nochmal angeschaut, und würde gern wissen, 
wie Ich alle interrupts in der Zeitkritischen Pfase (mein For Schleife) 
ausschalten kann.Würde der Code unten funktionieren?

int main (void) {

 sei();
   for (;;) {

    sei();
          while(!UART_ReceivedChar){}
          UART_ReceivedChar = 0;
    cli();
          For (......){ Zähler++;
          }
   }
}

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
Noch kein Account? Hier anmelden.