UART-Interrupt haengt das Programm auf (Atmega8)

OP #213639
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
Angehängte Dateien:
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
Gast
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
OP
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
OP
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?
Gast
@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
Gast
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.
OP
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??
Gast
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.
Gast
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
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 21 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.