Peter Fleury Uart Lib: Problem mit Rx-Interrupt und getc()

Gast #1291003
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?
Gast #1292138
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?
Angehängte Dateien:
#1292158
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
  }
Gast #1296606
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.
Angehängte Dateien:
#1300283
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.
Gast #1300324
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.
Gast #1301792
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren