Forum: Mikrocontroller und Digitale Elektronik UART-Interrupt haengt das Programm auf (Atmega8)


von Andrea R. (drea)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich habe ein riesiges Problem mit meinem ATmega8.
Ich habe ein kleines Programm geschrieben, um ein bischen mit den
Interrupt rumzuspielen. Es soll lediglich eine Ausgabe auf den UART
machen und damit ein Fenster auf meinem Terminal darstellen. Danach
soll es warten bis man ein Programm gewählt hat und dann das
dazugehörige Programm starten. Wenn das Programm läuft soll es durch
ein "e" vom Terminal gestopt werden können. Mein Problem ist nun,
dass wenn ich den Interrupt aktiviere, mein Programm sich aufhängt. Es
zeigt zwar noch das Fenster an, aber in dem Moment wenn die Interrupts
aktiviert werden gibt er das Fenster noch mal aus und das Unterprogramm
läuft nicht ab.
Wenn ich die Interrupts nicht aktiviere, sondern das Programm
blockierend betreibe, läuft es einwandfrei.
Die Interrupts und der UART funktionieren auch, denn die habe ich
vorher schon mit einem anderen Programm getestet. Allerdings habe ich
bei dem anderen Programm nur mit dem UART ein Zeichen empfangen.
Leider weiß ich nicht mehr weiter. Ich habe die ativierung der
Interrputs auch schon an andere Stellen verschoben, doch leider hilft
das auch nichts.
Es wäre schön, wenn noch jemand eine Idee hätte oder mir sagen kann,
was ich falsch mache.

Danke

von Thomas S. (tstuetz)


Lesenswert?

Was passiert wenn du eine Taste gedrückt hast ?
Bei einem uController sollte es NIE ein Ende von main() geben
=> Endlosschleife!

du hast sowohl im hauptprogramm (main) als auch im RX-Interrupt das
auslesen des RX-Puffers drin - ist das korrekt so ?

Gruss

von Niels H. (monarch)


Lesenswert?

Die Variable ist global UND lokal (in main) definiert.
Da hast du dich bestimmt verkaspert! Aber schön, das du an das volatile
gedacht hast :)

von MooseC (Gast)


Lesenswert?

Ein Problem sehe ich dem doppeltem Uart auslesen. Einmal im Interrupt
und einmal im main. Wenn Du den Interrupt freigibst fängt die
Uart-Serviceroutine alle empfangen Daten weg und im main kannst Du mit
dem RXC bit nicht mehr sehen, ob etwas ankam. Du solltest den Empfang
dann schon komplett im Interrupt mit einem Spooler oder mit eigenen
Flags aubauen und dann verwenden.

Dann noch ein Tip: lege die opulenten Bildschirmmasken lieber im Flash
ab und gebe sie von dort aus. Deine sternchenumrandete Maske hat
bereits 420 Bytes im RAM belegt und der Mega8 hat "nur" 1k RAM.

MooseC

von MooseC (Gast)


Lesenswert?

Korrektur: 490 Bytes

von Niels H. (monarch)


Lesenswert?

Ürgs, meinte die "zeichen" variable, die lokal und global definiert
ist.

das war bestimmt nicht so gedacht.

von Andrea R. (drea)


Lesenswert?

Vielen lieben Dank für die ganzen Antworten!
Ich habe das doppelte UART auslesen raus genommen, ist wohl beim
Probieren so da rein gerutscht. Aber das Programm läuft erst richtig,
wenn ich in der UART Initialisierung den Interrupt fürs senden
auskommentiere. Allerdings verstehe ich nicht wieso das Probleme macht,
weil ich den Interrupt doch gar nicht benutze.
Was soll´s, jetzt läuft es. Die anderen Sachen die ihr gepostet habt
werde ich mir gleich anschauen.

Danke noch mal

von Andrea R. (drea)


Lesenswert?

Hab grade versucht, die Maske im Flash abzulegen, aber es hat leider
nicht geklappt. Ich hab erst einen String im Flash abgelegt mit PROGMEM
und dann wollte ich ihn auf den UART ausgeben. Leider kam aber nur
Datenschrott an. Dann habe ich es direkt mit PSTR versucht,
aber auch da kommt nur Datenschrott an. Muß ich da noch irgendwas
beachten, irgend einen cast oder so was?

von Peter Dannegger (Gast)


Lesenswert?

@Andrea Runge,

Dein Programm muß und wird sich solange merkwürdig verhalten, bis Du
die Antwort von Thomas Stütz liest.

"sollte nie" ist etwas untertrieben, es muß "darf nie" heißen.


Peter

von Niels H. (monarch)


Lesenswert?

;-(
Ich find meine doppelte deklaration der Variable "zeichen" auch
ziemlich wichtig! heul

Die Zeile "uint8_t zeichen;" in main() muss raus, sonst kann das
nicht funktionieren!

von Werner B. (Gast)


Lesenswert?

Du gibst Rx UND Tx Interrupt frei, hast aber nur eine ISR für den RX
definiert. Das kann nur schiefgehen weil der TX Interrupt immer anliegt
solange kein zeichen im sendebuffer steht.

von Andrea R. (drea)


Lesenswert?

Hey Niels,

hab sebstverständlich gleich die doppelte Deklaration entfernt!!
(komischer weise hat es auch mit dieser funzt)
Tschuldige, dass ich das nicht explizit erwähnt hatte :-)


Die Endlosschleife habe ich auch gleich angefügt.
Da sie ja so wichtig ist, könnt ihr mir ja bestimmt auch erklären
warum??

von Werner B. (Gast)


Lesenswert?

Weil Du kein Betriebssystem hast zu dem main() am ende zurückkehren
kann.

von Werner B. (Gast)


Lesenswert?

Strukturiere das doch mal etwas übersichtlicher um
1
volatile char zeichen = '\0';
2
3
SIGNAL( rx...) {  zeichen = UDR; }
4
5
main() {
6
  init_CharacterFormatOfRS232();
7
  enable_RX_TX_and_RXCIE();
8
  sei();
9
  while(1) { /* betriebssystem :) */
10
     while(zeichen != '1') /* TuNix */
11
     while(zeichen != 'e') {
12
        /* TuWasSinnvolles */
13
     }
14
   }
15
}

Den TX Interrupt darfst Du defintiv nicht freigeben denn der ist immer
aktiv solange kein zeichen im sendebuffer steht.

von Werner B. (Gast)


Lesenswert?

Mist Strichpunkt nach /* TuNix */ vergessen :)

von Andrea R. (drea)


Angehängte Dateien:

Lesenswert?

Hier ist mal die neuste Ausgabe von meinem Programm.
So weit funzt es auch. Nur kann ich die Ausgabemaske noch nicht im
Flash ablegen bzw. nicht wieder auslesen.

von Werner B. (Gast)


Lesenswert?

Da brauchst Du etwas mehr dafür

Der Flash ist ein eigener Adressbereich beim AVR (Harward Architektur)
und kann aus C nicht so einfach angesprochen werden wie unter der
üblichen Von Neumann Architektur anderer Prozessoren.
Vereinfacht ausgedrückt: Flash und Ram liegen auf den geleichen
addressen und die normalen C Pointerfunktionen greifen immer auf das
RAM zu. Für Daten im Flash muss man sich etwas verrenken.
Siehe hierzu das Tutorial auf dieser Webseite.

Ums kurz zu machen; Dein code mal für Flash umgestrickt (ungetestet).
1
/* Es hat sich die Konvention eingbürgert an Funktionen die 
2
   Datem aus dem Flash verarbeiten die Endung "_P" anzuhängen */
3
void uart_puts_P (prog_char *s)
4
{
5
    char c;
6
    do
7
    {                        /* so lange *s != '\0' also ungleich dem
8
"String-Endezeichen" */
9
        c = pgm_read_byte(s);  // lese byte aus flash
10
        if(c == '\0')
11
             break;
12
        uart_putc(c);
13
        s++;
14
    } while(1);
15
}
16
17
18
void disp1(void)
19
{  
20
   /* PSTR ist ein makro dass dem compiler sagt dass die daten nicht
21
ins RAM kopiert werden sollen */   
22
uart_puts_P(PSTR("*******************************************************************\n\r"));
23
  uart_puts_P(PSTR("**                                                 
24
             **\n\r"));
25
  uart_puts_P(PSTR("**       1  Starte Blinklicht                      
26
             **\n\r"));
27
  uart_puts_P(PSTR("**       2  Starte Nightrider                      
28
             **\n\r"));
29
  uart_puts_P(PSTR("**       e  Stop Programm                          
30
             **\n\r"));
31
  uart_puts_P(PSTR("**                                                 
32
             **\n\r"));
33
  uart_puts_P(PSTR("*******************************************************************\n\r"));
34
35
}

von Andrea R. (drea)


Lesenswert?

Vielen lieben Dank,

das werde ich auf alle Fälle noch mal ausprobieren! :-)

von Andrea R. (drea)


Lesenswert?

@Werner:

Hab´s grade ausprobiert und es läuft super!!

Vielen lieben Dank!!!!!!!

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.