mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Peter Fleury Uart Lib: Problem mit Rx-Interrupt und getc()


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe ein Programm für eine ATmega88 geschrieben, das kontinuierlich 
Daten aus mehreren Sensoren ausliest (SPI) und diese via UART versendet. 
Gestartet wird der Auslese- und Sendevorgang in dem ich ein t(=transmit) 
sende und gestoppt werden soll der kontinuierliche Datenstrom mit dem 
senden eines s(=stop).
Die Routinen für den SPI Zugriff sind sehr kurz gehalten und laufen 
atomar, d.h. in dieser Zeit sind keine Interrupts erlaubt.
Nach dem auslesen der Sensordaten (Integer), wandel ich diese mit der 
itoa()-Funktion aus der stdlib in einen String um und versende dann 
anschließend die Daten.

Nun habe ich folgendes Problem, wenn ich keine Pause (7ms) in die 
kontinuierliche Schleife einfüge dann bekommt der µC das senden von 
s(=stop) nie mit und ich kann den Datenstrom nur durch einen Reset 
stoppen. Die 7ms sind mir aber zu lang.
Hat dafür jemand eine Lösung?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal den Code posten. Du kannst dir noch so viel Mühe mit einer 
Beschreibung geben, wir wissen dann trotzdem noch nicht, was genau 
dein aktueller Code macht. Eine Beschreibung entspricht schließlich 
immer dem, was du denkst oder möchtest, nicht unbedingt dem, was 
tatsächlich passiert.

Autor: Thomas (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang ist jetzt das Hauptprogramm main.c

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du auch noch die hal_smb380_new_acc_read zeigen?

Edit: In deinem Programm sind mir zuviele wartende Schleifen drinnen.

Autor: Thomas (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Karlheinz: wartende Schleifen?
Ich warte halt mit
while( !hal_smb380_new_acc_read( 0x02, &acc_x)){};
darauf, bis der Sensor wieder einen neuen Wert ausgibt

Und die _delay_ms(7);
wurden nötig, da der µC keinen RX-Interrupt mehr angenommen hat.

Die Warteschleifen sind ja nicht unbedingt schlecht, in der Zeit könnte 
ja ein RX-Interrupt auftreten und verarbeitet werden, oder?

Hast du einen besseren Vorschlag wie ich das programmieren kann?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas schrieb:

> Hast du einen besseren Vorschlag wie ich das programmieren kann?

Wartende Schleifen sind immer schlecht.
In einem µC funktioniert der Status-Gedanke meistens am besten.
Dein Programm (die Hauptschleife) ist in einem Zustand. Irgendwelche 
Ereignisse verändern den Zustand. Aber: Es wird nicht gewartet. 
Reaktionen erfolgen nur aus Zustandsänderungen heraus.
Bei dir wäre zb ein Zustand: Daten vom Sensor holen und verschicken - 
kurz sampleData, der entweder TRUE oder FALSE sein kann

int main()
{
  unsigned int c;
  unisgned char sampleData;

  ...


  sampleData = 0;
  while( 1 ) {
    c = uart_getc();

    if ( (unsigned char)c == 't' )
      sampleData = 1;

    if ( (unsigned char)c == 's' )
      sampleData = 0;

    if( sampleData ) {
      if( hal_smb380_new_acc_read( 0x02, &acc_x ) {
        itoa( acc_x, buffer_acc_x, 10 );   
        uart_puts( "acc , " );
        uart_puts( buffer_acc_x );        // and transmit string to UART
        uart_puts( "\r\n" );
      }
    }
  }

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,
danke schon mal für die Anregung.
Das sieht (viel) besser aus, ich werde den Code die nächsten Tage mal 
umschreiben.

Autor: Thomas (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl-Heinz,
ich hab das Programm jetzt mal umgeschrieben, siehe Dateien im Anhang. 
Allerdings mein eigentliches Problem bekomme ich damit nicht gelöst.

Wenn ich das Main-Programm mit dem auskommentierten Bereich in der 
Endlosschleife laufen lasse, dann funktioniert das starten der 
Übertragung mit dem senden von 't' wenn ich dann ein 's' sende dann 
stopt das Programm auch, aber etwas verzögert.
Wenn ich nun den auskommentierten Bereich auch ausführen lasse, dann 
kann ich das Proagramm wieder mit 't' starten aber auf das senden von 
's' reagiert das Programm nicht mehr, auch nicht verzögert ( ich hab mal 
1 Min gewartet). Daten liest das Programm weiterhin aus und sendet diese 
auch noch.

Irgendwie habe ich das Gefühl, dass der RX-Interrupt nicht mehr 
bearbeitet wird.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat keiner eine Idee??

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde mal die ganzen CRITICAL_REGION Makros weglassen. Du benutzt 
Hardware-SPI, daher können die Interrupts die ganze Zeit über enabled 
bleiben.

Wenn du das Gefühl hast, dass der RX-Interrupt nicht mehr angesprungen 
wird, dann mach dir in die ISR eine Ausgabe rein. Nein, nicht über UART; 
schalte eine LED ein. In der mainLoop setzt du nach jeder Ausgabe die 
LED wieder zurück. Wenn du dann Zeichen versendest, müsste die LED 
zumindest blinzeln. Dann weißt du, dass die ISR aufgerufen wird.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
was ich schon mal probiert habe war, die Makros durch cli() und sei() zu 
ersetzen hat aber auch nichts geändert. Ich werde die Makros heute Abend 
mal ganz raus machen und schauen ob das was bringt.

Ich habe zwar keine LED (spezielles Board) aber einige Port-Pins habe 
ich noch frei. Werde das dann mal mit einem Oszi prüfen.

Könnte es evtl. auch am RS232/USB-Wandler (FT232RL) liegen? Dort 
flackern allerdings die beiden RX- und TX-LEDs.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas schrieb:

> Könnte es evtl. auch am RS232/USB-Wandler (FT232RL) liegen? Dort
> flackern allerdings die beiden RX- und TX-LEDs.

Häng doch dein Oszi an den Rx Pin vom µC, dann weißt du mit Sicherheit 
ob da was ankommt, wenn du die Taste drückst bzw. wieviel Verzögerung 
dir der FT232 einbaut.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl-Heinz: Danke schon mal!

Ich hab das Problem jetzt genauer lokalisieren können, es liegt am 
USB/Seriell-Wandler (FT232RL). Der FT232RL gibt (bei Baudraten >=9600) 
die RX-Daten nicht aus, während er kontinuierlich mit TX-Daten versorgt 
wird.

Ob das ein Problem des Chips, des Treibers oder der USB-Geschwindigkeit 
(USB 1.0 / USB 2.0) ist konnte ich noch nicht genauer eingrenzen. Für 
Vorschläge, wie ich das genauer bestimmen kann wäre ich sehr dankbar.

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.