UARTS am Glühen?

Gast #2573990
Lesenswert?

Hallo!

Problem: an die UARTs gesendete Zeichen  werden verschluckt

Aufbau: ATmega2560, UART1: GPS-Empfänger, UART2: ich (Hyperterminal), 
jeweils interruptgesteuert, ISR saukurz

Symptom: ATmega antwortet fleissig auf meine Eingabe übers Terminal. 
Wenn jedoch der GPS-Empfänger seine sekündlichen Quark abgibt, werden 
Zeichen, die ich ("gleichzeitig") per HT gesendet habe, teilweise 
verschluckt (kommen jedenfalls nicht im ATmega an).

Vermutung: zwei Interrupts kollidieren, einer davon wird "wegignoriert"

Frage: wie elegant lösen?

Gruß: Simon
Gast #2574014
Lesenswert?

chick schrieb:
> Wie kommst Du auf diese Vermutung? Und wie soll das denn gehen?

Stelle mir vor, dass, während die eine ISR gerade ihren Dienst 
aufgenommen hat, die andere dazwischenfunkt und die erstere abbrechen 
muss.
Wie das dann gehen soll: gar nicht. Merk ich ja bei mir.  :)

Dünne gerade meine ISR aus....
Gast #2574021
Lesenswert?

Ausdünnen ist der ganz falsche Ansatz. Luafzeiten bleiben immer, wenn 
auch sehr kurz.

Infomier Dich lieber was der Prozessor wirklich macht, wenn zwei 
Interrupts auftauchen. Vermuten hat in der E-Technik nix verloren, es 
gibt Datenblätter, Tutorials, Applikationen. Da wird doch wohl was zu 
finden sein.
Würd Dich gern beraten, kann mich aber nur bei den PICs aus.
#2574022
Lesenswert?

Simon schrieb:
> chick schrieb:
>> Wie kommst Du auf diese Vermutung? Und wie soll das denn gehen?
>
> Stelle mir vor, dass, während die eine ISR gerade ihren Dienst
> aufgenommen hat, die andere dazwischenfunkt und die erstere abbrechen
> muss.

Nicht beim AVR in einer ISR Standardkonfiguration.
Das Auftreten des zweiten Interrupt-Auslösers wird registriert und die 
ISR wird angestossen, wenn die erste fertig abgearbeitet wurde.

In einer UART dauert das Übertragen eines Zeichens wesentlich länger als 
das Abarbeiten der zugehörigen ISR (normalerweise. Wenn man sich an die 
Regel hält: nur das in einer ISR machen, was unbedingt notwendig ist - 
nicht mehr), so dasss das überhaupt kein Problem sein dürfte.
Gast #2574069
Lesenswert?

Und wie sieht das beim Senden aus?
Wenn der Controller ans Terminal Daten (Kursorpositionierungs- und 
Anzeigestrings) schickt und dabei das GPS seinen Senf abgibt, kommt es 
vor, dass Zeichen auf dem Terminal dargestellt werden, die eigentlich 
als Steuerzeichen verstanden und nicht angezeigt werden sollen.

Nimmt die ISR des Empfangens auch Rücksicht und wartet, dass das Senden 
eines Zeichend abgeschlossen ist?
#2574074
Lesenswert?

Simon schrieb:
> Und wie sieht das beim Senden aus?

JEDE ISR wird komplett abgeschlossen, ehe die nächste arbeiten kann. 
Egal ob Timer, ADC, UART, Pinchange, externer Interrupt, etc. etc.

Wenn eine ISR aufgerufen wird, werden die Interrupts global gesperrt und 
mit dem Ende einer ISR werden sie wieder freigegeben.

(Es sei denn du pfuscht da rein und machst in der ISR selber einen 
sei(), was in den meisten Fällen eine ganz schlechte Idee ist)
#2574088
Lesenswert?

Falk Brunner schrieb:
> @  Simon (Gast)
>
>>Vermutung: zwei Interrupts kollidieren, einer davon wird "wegignoriert"
>
> Eher nicht, ich tippe auf schlechte, blockierende Programmierung,
> vielleicht sogar mit Delays, bähh.

Das denke ich auch.

Alleine der Terminus

> Dünne gerade meine ISR aus....

In einer UART ISR gibt es normalerweise nicht viel zum ausdünnen:
Zeichen aus UDR holen und ab damit in den Ringbuffer.
Eventuell noch ein Flag setzen, dass ein \r oder \n reinkam, dann 
braucht die Hauptschleife sich nicht dauernd das letzte empfangene 
Zeichen ansehen.
Aber summa summarum nichts was wesentich länger als 40 oder 50 CPU Takte 
dauert und damit für die restliche Funktion der UART ziemlich 
uninteressant.
Gast #2575865
Lesenswert?

Hi!

Falls du ein Oszi hast: Beim Eintritt in die ISR einen unbenutzten Pin 
auf HIGH setzen und beim Verlassen der ISR auf LOW. Idealerweise für 
jede ISR einen eigenen Pin. Oszilloskope mit 16 Digitalkanäle sind echt 
eine tolle Erfindung!

Gruß
PP
Gast #2576118
Lesenswert?

Wie groß ist dein Empfangs-Buffer für den GPS-UART und wie viele Zeichen 
sendet der GPS-Empfänger maximal?
Wenn der Buffer zu klein ist wird der AVR im Normalfall aktiv warten und 
so werden auch nicht die Bytes von zweiten UART abgeholt.
Gast #2576905
Lesenswert?

Frage zur Kürze einer ISR:
ist die Beispiel-USART_RX_vect, welche im Tutorial nachzulesen ist, 
ungeeignet lang oder in Ordnung?

ISR (USART1_RX_vect)
{
unsigned char nextChar;
nextChar = UDR1;

  if (uart1_str_complete == 0)
  {
    if(  nextChar != '\n' &&
      nextChar != '\r' &&
      uart1_str_count < UART1_MAXSTRLEN-1)
    {
      uart1_string[uart1_str_count] = nextChar;
      uart1_str_count++;
    }
  else
    {   uart1_string[uart1_str_count] = '\0';
      uart1_str_count = 0;
      uart1_str_complete = 1;
    }
  }
}
Gast #2577742
Lesenswert?

Diesmal ist mein Kopf am Glühen, ich suche einen Denkfehler:
Ich verwende die o.g. ISR und in der main folgende Schleife:

while(1)
{
send_GSM ("at");   //sende an GSM-Modul "at" (gefolgt von <CR>)

if(uart1_str_complete == 1)  //wenn die ISR einen vollständigen String 
hat
{
    uart2_puts (uart1_string);  //ans Terminal senden
    uart1_str_complete = 0;     //und von vorn
}

Das Modul antwortet auch artig mit "at<CR><CR><LF>OK<CR><LF>".
Mein Programm "sieht darin aber nur den String "at" und nicht das (viel 
wichtigere) "OK".
Sieht jemand meinen Fehler?
Gast #2577782
Lesenswert?

Du hast es dir nicht aufgemalt. Das war nur der eine Fehler, den zweiten 
musst du noch suchen.

Man sollte auch kopierte Sourcen verstehen, bevor man sie verwendet, 
selbst (oder gerade) wenn sie aus Tutorials stammen.

Oliver
Gast #2577799
Lesenswert?

Lautmalerei der ISR:

Zeichen reingeholt.
Wenn
noch Platz,
und kein LF
und kein CR
und mehr als ein Zeichen Platz
denn Zeichen anfügen
und hochzählen.
Ansonsten
letztes Zeichen NUL
und String fertig melden
und Zähler zurücksetzen.

Malung der Schleife:
Wenn
ein String vollständig, dann
Zähler nullen
String senden
von vorn.

Falsch verstanden?
Gast #2577827
Lesenswert?

Mals dir richtig auf. Du hast 2 Uarts, auf denen gleichzeitig etwas 
passiert. Und gleichzeitig heisst wirklich gleichzeitig. Du hast aber 
ein Programm, welches nur eine Sache gleichzeitig machen kann.

Überleg dir, was mit UDR, nextchar, und vor allem in uart1_string 
passiert.

Oliver
Gast #2577835
Lesenswert?

Also:

während mit UART2 gerade mal gesendet wird flattern in der ISR der UART1 
fleissig Zeichen rein.
Das sollte doch gehen (lt. K-H Buchegger wartet ein Interrupt auf den 
anderen).

Mglw. ist der eine String ja schon wieder fertig während der andere noch 
gar nicht fertig gesendet ist- ist es das?
#2577916
Lesenswert?

Simon schrieb:
> Lautmalerei der ISR:

[ ... textuelle Beschreibung eines Algorithmus ]


Wikipedia:

<< Die Onomatopoesie (auch Onomatopöie, von griech. ὄνομα: ónoma: 
„Name“, und ποίησις: poíēsis: hier „Erschaffung, Herstellung“, folglich 
ὀνοματοποιεῖν: onomatopoiein: „einen Namen prägen, benennen“), deutsch 
Lautmalerei, Tonmalerei, Schallwort, ist die Nachahmung eines 
Naturlautes oder eines sonstigen außersprachlichen akustischen Phänomens 
durch die klanglich als ähnlich empfundene Lautgestalt eines 
sprachlichen Ausdrucks >>


müßtest du die laut-gemalerte ISR dann nicht als .wav oder .mp3 Datei 
anhängen, und sich das anhören wie die Piepstöne von einer C64 
Datasette?
Gast #2577934
Lesenswert?

Wegstaben Verbuchsler schrieb:
> müßtest du die laut-gemalerte ISR dann nicht als .wav oder .mp3 Datei
> anhängen, und sich das anhören wie die Piepstöne von einer C64
> Datasette?

Das erinnert mich an das erste Lied, was ich je auf einem PC gehört 
habe,als nämlich -nach sehrsehr langer Ladezeit- das 1541-II C64-Floppy 
tatsächlich Karma Chameleon vibrierte.

Gut, habe ich halt nicht lautgemalt sondern meine Malung aufgeschrieben.
Gast #2578854
Lesenswert?

Also... ich stehe wirklich auf dem Schlauch. Vermutlich reichen meine 
Kenntnisse nicht aus, den Fehler zu erkennen.
Wäre arg dankbar wenn mir jemand den Fehler zeigen würde. Habe gemalt 
und geschrieben und komme stets aufs gleiche hinaus: alles supi.
Würde jemand an einer Frage aus meinem Fachgebiet verzweifeln, ich würde 
sie ihm auch irgendwann sagen.
Herzlichst- Simon
Gast #2579152
Lesenswert?

Die beiden UART laufen in Hardware völlig unabhängig von deinem 
Programm, und empfangen un senden passiert da gleichzeitig.

Die zugehörigen ISR's sind kurz genug (vermutlich, du zeigst ja nie den 
ganzen Code), daß die abwechselnd die beiden UARTS bedienen können. Aber 
was passiert mit den Daten?

Oliver
Gast #2579227
Lesenswert?

Damit es noch etwas klarer wird:

Simon schrieb:
> während mit UART2 gerade mal gesendet wird flattern in der ISR der UART1
> fleissig Zeichen rein.
> Das sollte doch gehen (lt. K-H Buchegger wartet ein Interrupt auf den
> anderen).

Das geht, aber wo flattern die Daten hin?
Und wie sehen diese aus?
Wie viele Strings kann dein Programm zur weiteren Verarbeitung 
abspeichern?

Was kann hier alles passierern:
> uart2_puts (uart1_string);  //ans Terminal senden
wenn gleichzeitig dein GPS sendet?

Was passiert, wenn, wie in deinem GPS-String, mehrere CFs/LFs 
nacheinander kommen?

Fragen über Fragen ;)

Oliver
Moderator (Firma: Titel) Persönliche Seite #2579255
Lesenswert?

Nur mal kurz um die Dimensionen klarzustellen:
  uC = schnell
UART = langsam
 GPS = langsamer
User = am langsamsten

Kurz: da ist ein Fehler im weitgehend unbekannten Programm. So ein paar 
nach und nach auftretende UART Interrupts steckt jeder uC locker weg...

Simon schrieb:
> Wäre arg dankbar wenn mir jemand den Fehler zeigen würde.
Die Fehlerursache ist, dass du den Parser zur Hälfte in die ISR gepackt 
hast. Für eine exakte Analyse wäre arg hilfreich, wenn du dein aktuelles 
Programm zeigen würdest...
Gast #2579257
Lesenswert?

Gibts nen Kochrezept um die vielen Fragen zu umkochen? In etwa, den 
kompletten String, sobald er fertig ist, zu kopieren und mit der Kopie 
weiterzuarbeiten damit die ISR das Original neu beschreiben kann?
War so meine Idee..
Gast #2579263
Lesenswert?

Mein Miniprogramm:

int main(void)
{
while(1)
{
  if(uart1_str_complete == 1)  //GSM
        {
    uart1_str_complete = 0;
    uart2_puts (uart1_string);
  }

}

ISR (USART1_RX_vect) //GSM
{
unsigned char nextChar;
nextChar = UDR1;

  if (uart1_str_complete == 0)
  {
    if(  nextChar != '\n' &&
      nextChar != '\r' &&
      uart1_str_count < UART1_MAXSTRLEN-1)
    {
      uart1_string[uart1_str_count] = nextChar;
      uart1_str_count++;
    }
  else
    {
      uart1_str_complete = 1;
      uart1_string[uart1_str_count] = '\0';
      uart1_str_count = 0;
    }
  }
}

void uart1_putc(unsigned char c)
{
    while (!(UCSR1A & (1<<UDRE1)))
    {
    }
    UDR1 = c;
}

void uart1_puts (char *s)
{
    while (*s)
    {
        uart1_putc(*s);
        s++;
  }
uart1_putc('\r');
}
#2579282
Lesenswert?

1
while(1)
2
{
3
send_GSM ("at");   //sende an GSM-Modul "at" (gefolgt von <CR>)
4

5
if(uart1_str_complete == 1)  //wenn die ISR einen vollständigen String
6
hat
7
{
8
    uart2_puts (uart1_string);  //ans Terminal senden
9
    uart1_str_complete = 0;     //und von vorn
10
}

uart1_str_complete ist eigentlich ein etwas fälschlicher Name. 
Eigentlich sollte das uart1_line_complete heissen.

Und immer schön drann denken:
Die ISR meldet dir, wenn eine ZEILE fertig übertragen wurde. Auf den 
String "AT\n" antwortet das Modem aber mit 2 Zeilen!
Und zu dem Zeitpunkt, an dem du das erste mal "AT" zum Modem schickst, 
kann es durchaus eine Zeitlang dauern, bis das Modem seinerseits mit dem 
"AT\nOK\n" antwortet. Was macht dein Programm in der Zwischenzeit?
Und auch drann denken: Ein uart2_puts braucht seine Zeit, bis er etwas 
ausgegeben hat. Zb. das "AT" welches in der ertsen Antwortzeile des 
Modems kommt. Du gibst dieses AT aus, aber in der Zwischenzeit überträgt 
das Modem schon die zweite Zeile der Antwort, das "OK", welches in 
welchen Variablen abgelegt wird? (werden würde, wenn uart1_str_complete 
richtig stehen würde)

Du willst Dinge 'gleichzeitig' machen?
Gut. Dann musst du aber in deinem Programm an jeder einzelnen Stelle 
berücksichtigen und bedenken, was in den jeweils anderen Programmpfaden 
alles passieren könnte. Im Moment tust du das nicht. Deine Denkweise 
geht immer noch seriell: Zuerst passiert das, dann passiert das.
Gast #2579502
Lesenswert?

Sitz leider grad nicht am "Arbeitsplatz" (sondern im Schafstall) und 
kanns nicht testen, aber sollte ich denn in die ISR eine Abfrage 
einbauen, ob eine vermeintlich fertige String-Zeile nur aus CR bzw LF 
besteht und diese verwerfen? Ist es das?
Gast #2579517
Lesenswert?

Überlass alle Auswertungen dem Hauptprogramm. Da dein GPS ja nun auch 
noch andere Antworten schicken kann, und dein Programm irgendwann einmal 
mehr machen wird, als die empfangenen Strings einfach wieder zu senden, 
brauchst du ein Konzept, um eine unbekannte Anzahl von Strings empfangen 
und für die weitere Bearbeitung Speichern zu können.

du
#2579534
Lesenswert?

@  Simon (Gast)

>einbauen, ob eine vermeintlich fertige String-Zeile nur aus CR bzw LF
>besteht und diese verwerfen? Ist es das?

Nein, das ist nur eine kleine Verbesserung. Dein Problem ist u.a. das 
blockiernde Senden der String. Während dieser Zeit ist deine CPU tot für 
alles andere. Lösung? Strings kopieren und mit TX-ISR senden. Oder 
gleich ein FIFO nutzen.

MFG
Falk
Moderator Persönliche Seite #2579548
Lesenswert?

Simon schrieb:

> Das Modul antwortet auch artig mit "at<CR><CR><LF>OK<CR><LF>".

Du hast ECHO eingeschaltet, deshalb "siehst" Du alles alles, was Du 
sendest, nochmal als Echo.

Ich nehme "at<CR><CR><LF>OK<CR><LF>" mal auseinander:

Du sendest at<CR>
Du siehst: at<CR>      # das ist das Echo
Du siehst: <CR><LF>    # das ist der Zeilenvorschub, vom Modem
                         generiert.
Du siehst: OK<CR><LF>  # das ist die Antwort OK mit erneutem
                         Zeilenvorschub

Du würdest Dir das Leben einfacher machen, wenn Du das Echo abschaltest. 
Das ist nur sinnvoll bei Terminal-Verbindungen, damit der Mensch, der da 
rumtippt, auch sieht, was er tippt. Bei rechnergesteuerten Anwendungen 
ist das nicht sehr sinnvoll. Bei Modems kann man das echo mit ATE0<CR> 
abstellen.
Am besten speicherst Du diese Einstellung im Modem ab. Die Antworten 
reduzieren sich dann auf das wesentliche, nämlich das, was du auch 
auswerten willst.

Gruß,

Frank

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