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


von Thomas (Gast)


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?

von Stefan E. (sternst)


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.

von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Im Anhang ist jetzt das Hauptprogramm main.c

von Karl H. (kbuchegg)


Lesenswert?

Kannst du auch noch die hal_smb380_new_acc_read zeigen?

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

von Thomas (Gast)


Angehängte Dateien:

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?

von Karl H. (kbuchegg)


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

1
int main()
2
{
3
  unsigned int c;
4
  unisgned char sampleData;
5
6
  ...
7
8
9
  sampleData = 0;
10
  while( 1 ) {
11
    c = uart_getc();
12
13
    if ( (unsigned char)c == 't' )
14
      sampleData = 1;
15
16
    if ( (unsigned char)c == 's' )
17
      sampleData = 0;
18
19
    if( sampleData ) {
20
      if( hal_smb380_new_acc_read( 0x02, &acc_x ) {
21
        itoa( acc_x, buffer_acc_x, 10 );   
22
        uart_puts( "acc , " );
23
        uart_puts( buffer_acc_x );        // and transmit string to UART
24
        uart_puts( "\r\n" );
25
      }
26
    }
27
  }

von Thomas (Gast)


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.

von Thomas (Gast)


Angehängte Dateien:

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.

von Thomas (Gast)


Lesenswert?

Hat keiner eine Idee??

von Karl H. (kbuchegg)


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.

von Thomas (Gast)


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.

von Karl H. (kbuchegg)


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.

von Thomas (Gast)


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.

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.