mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART0 Probleme LPC2148


Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein seltsames Phänomen beim Senden über UART0. Ich benutze den 
UART0 ohne Interrupts, 19200, FIFO ein, Taktfrequenz 60MHz.
Ich fang die Sendung mit einem Portmonitor auf und muss folgendes 
feststellen:

Wenn ich 16 Zeichen sende, sieht es gut aus.
Sobald ich mehr als 16 sende, fängt er an Teile zu wiederholen.
Nun hat der LPC2148 einen internen Fifo von 16Byte. Ob da was schief 
geht.

Hab mal probiert, nach jedem zeichen eine gewisse Zeit zu warten - aber 
erst bei 500mus Pause sieht es normal aus.

Hat jemand eine Idee?

Autor: Marc Karnate (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
poste doch mal den Code, vielleicht kann man dir dann helfen.

gruß
marc

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DWORD UART0Init( DWORD baudrate, BOOL ringBuffer )
{
    DWORD Fdiv = 60000000 / (16 * baudrate);

    //PINSEL0 = 0x00050005;       /* Enable RxD1 and TxD1, RxD0 and TxD0 
*/
  PINSEL0 = (PINSEL0 & ~0x0000000F) | 0x00000005;

    U0LCR = 0x83;               /* 8 bits, no Parity, 1 Stop bit    */
    //Fdiv = ( Fpclk / 16 ) / baudrate ;  /*baud rate */
    U0DLL = Fdiv % 256;
    U0DLM = Fdiv / 256;
    U0LCR = 0x03;               /* DLAB = 0                         */
    U0FCR = 0x07;    /* Enable and reset TX and RX FIFO. */

    return (TRUE);
}

// Write character to Serial Port
void UART0put(BYTE ch)
{
    while (!(U0LSR & 0x20));
    U0THR = ch;
}

gesendet wird innerhalb eines Interrupts (100ms Zyklus)
beispielhaft mal nur die Werte von i, bereits da tritt das Problem auf

for(i = 0; i < MP_SEND_BLOCK_LEN; i++) // 27 Zeichen
{
  //UART0put(sendBuf[i]);
  UART0put(i);
}

wenn ich in der Sendeschleife so 500mus warte, sieht es gut aus. Das 
kann es aber ja wohl nicht sein oder?

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das Problem inzwischen weiter untersucht. Wenn ich den FiFo 
verwende, sendet er die ersten 16 zeichen und dann die restlichen. Beim 
nächsten Durchgang sendet er den rest von vorher + Rest des FiFos. Er 
löscht offensichtlich den Inhalt eines unvollständigen Fifos nicht.

Ohne Fifo (U0FCR = 0x00;) ändert sich nichts - als ob er das nicht 
macht. Normalerweise müßte es dann ja funktionieren.

Bei meinen Recherchen bin ich auf ein Dokument zu diesem Thema gestoßen 
- hier ein Auszug:

Applications using a UART to send data, normally
have implemented a software-based buffer (of for
example 80 bytes) to feed the transmitter. The
LPC2000 UART has a 16 byte transmit FIFO that can
generate an interrupt when it is empty. There is however
Sometimes users try to write bytes to the FIFO as
long as the THRE (Transmitter Holding Register
Empty) bit is set. This will not work. It appears that
whenever the THRE bit is set (interrupt) the FIFO is
empty and a maximum of 16 bytes can be moved into
the FIFO.

Das ganze Dokument ist unter 
http://www.standardics.nxp.com/support/documents/m... 
zu finden.

Übrigens ist das bei allen üblichen Samples offensichtlich falsch. Die 
zeigen alle das gleiche Problem.

Hat jemand eine Lösung? Wie kann man senden ohne fifo?

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Dokument drückt damit etwas unglücklich aus, dass man das FIFO nicht 
nutzt, wenn man es per THRE zu füllen versucht. Weil bereits nach dem 
ersten Byte THRE gelöscht wird, und daher nie mehr als 1 Byte verwendet 
wird ist.

Ein Designfehler der PC-UART, die ihren FIFO erst später verpasst bekam.

Eine Fehlfunktion entsteht durch die Verwendung von THRE nicht.

Tip: Wenn bei Chips, die schon ein Weilchen draussen sind (die LPC2000 
haben alle die gleiche UART), alle Samples gleichermassen falsch sind, 
dann haben entweder alle seit Jahren ein ernstes Problem mit der Optik, 
oder man selber etwas falsch verstanden.

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kann mir eigentlich auch nicht vorstellen, das das falsch sein 
sollte. Fakt ist aber das Phänomen, was ich bereits geschildert habe.

Beispiel: zyklisches Senden (aller 100ms) der Zahlen von 0-26 mit Fifo 
ohne Interrupt - Überwachung mit Portmonitor.

1. Sendung:
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17 18 19 1a

2. Sendung (100ms später)
10 11 12 13 14 15 16 17 18 19 1a 00 01 02 03 04
05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14
15 16 17 18 19 1a

3. Sendung (wieder 100ms später)
15 16 17 18 19 1a 00 01 02 03 04 05 06 07 08 09
0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19
1a

so geht das weiter. Es scheint so, das bei einer Sendung mit nicht ganz 
belegtem FiFo dieser bei der nächsten Sendung weiter benutzt wird. 
Selbst wenn ich den Fifo abschalte (U0FCR = 0x00;) verhält es sich so.
Gibt es evtl. einen Trick, wie man dieses Problem umgehen kann oder mach 
ich irgendetwas falsch?

Übrigens kann ich kein IRQ für UART0 verwenden, da die Sendung selbst 
(und auch eine ANtwort) in einer Interruptroutine stattfinden.

Über Hilfe wäre ich sehr dankbar, da ich an dieser Stelle einfach nicht 
weiter komme.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sind die Interrupts unterbrechbar konfiguriert?

Anonsten müsste man mehr vom Programm sehen. Etwas Info über den 
verwendeten Compiler wäre auch hilfreich.

> Übrigens kann ich kein IRQ für UART0 verwenden,
> da die Sendung selbst (und auch eine ANtwort)
> in einer Interruptroutine stattfinden.

Klar kann man. UART mit Interrupt bedeutet ja, statt ins FIFO in einen 
Puffer im Speicher zu schreiben, der per Interrupt abgearbeitet wird. 
Wenn dieser Puffer hinreichend gross ist, ist das von erheblichem 
Vorteil, da der Interrupt-Handler des Timers nicht auf die UART warten 
muss.

Generell sind nennendswerte Warteschleifen in einer Interrupt-Routine 
fragwürdig, jedenfalls wenn es nicht um exakte Zeiten geht.

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem ist im konkreten Fall ein sauberer 100ms Zyklus - also 
zeitkritisch. Momentan wird der Zyklus per Timer erzeugt - im Endfall 
dann aber per extern über ein genaues Signal. Innerhalb des Zyklus muss 
einiges berechnet werden und vor allem Daten an extern per UART gesendet 
und die ANtwort gelesen werden.
Besteht die Möglichkeit, in einer Interruptroutine trotzdem UART mit 
Interrupt zu machen - unterbrechbare Rotine (hab ich keine Ahnung, da 
bisher nur AVR-ERfahrung).

Die Warteschleife muss sein - die Gegenstation antwortet auch 
unmittelbar danach und die empfangenen Werte sind wichtig für den 
nächsten Zyklus.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Besteht die Möglichkeit, in einer Interruptroutine trotzdem UART
> mit Interrupt zu machen

Klar doch.

> da bisher nur AVR-Erfahrung

Bei ARM hat man zwar mehr Freiheit was verschachtelte Interrupts angeht, 
und auch ein paar Probleme mehr, aber die Prinzien sind gleich.

100 Millisekunden würde ich nicht als zeitkritsch ansehen, es sei denn 
es müssen exakt 100000 Mikrosekunden sein.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, zur Orientierung: Ein Interrupt-Handler für UART braucht auf 
60MHz LPC2000 mit allem FIFO-Gedöns schlimmstenfalls 3-4 Mikrosekunden.

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, es geht um eine Teleskopsteuerung wo es sehr genau sein muss, da 
sonst falsch nachgeführt wird. Also je genauer um so besser. Deshalb 
löse ich den Takt auch außen rum mit diskreter Elektronik, da auch noch 
andere Takte zur Synchronisation benötigt werden.

Dann würde ich die unterbrechbare Variante nehmen. EIn kleiner Tipp, was 
da zu tun ist?

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK das mit den Nestet Interrupts hab ich jetzt im Griff. UART mit 
Interrupt zeigt die beschriebenen Probleme nicht. Ohne Interrupt ist 
demnach offensichtlich nicht zu gebrauchen.

Ich habe den Zyklusinterrupt als unterbrechbar gemacht. Damit können die 
UART-Interrupts auch innerhalb der Zyklusroutine bedient werden.
Wenn ich nun beide UARTS am Laufen habe, sollte man die auch als Nested 
implementieren?

Eine Frage hätt ich noch zur Priorität von Interrupts:

(*(&VICVectCntl1+INT_VECT_NUM)) = 0x20 | UART0_INT;

Was bedeutet der Wert 0x20 und in welchen Bereichen kann der Wert 
liegen?

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Sinn von 0x20 möchte ich die Lektüre vom User Manual des LPC2148 
nahelegen. Ggf. auch die Dokumentation der verwendeten ARM PrimeCell 
PL190 (www.arm.com).

> Wenn ich nun beide UARTS am Laufen habe, sollte man die auch als Nested
> implementieren?

Alle Interrupts deren Handler recht lange ackert / wartet, sollten 
unterbrechbar sein. UART Interrupts gehören üblicherweise nicht dazu, 
müssen also nicht unbedingt unterbrechbar sein.

Autor: Thomas S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn dein Teleskop mit 100ms Auflösung nachgeführt wird, sollte doch ein 
genauer Takt des LPC völlig ausreichend sein.
Interrupt im Interrupt funktioniert sehr gut. Welche Softwareumgebung 
benutzt du ?
Hast du die Fifos mal ausgeschaltet ? Was macht das ganze dann ?

thomas

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Prinzip reciht der Takt von LPC aus, ich muss aber hardwareseitig 
noch andere Takte ableiten. Das mach ich dann mit externer Schaltung und 
führe den 100ms Takt per EINT rein.
Ich benutze WinArm.
Wie gesagt mit Interrupt läuft das ganze, habe auch nested im Griff. 
Derzeit versuche ich, am UART1 die Modemsignale ans Laufen zu bekommen, 
da meine Gegenstelle damit arbeitet.

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo A. K. ja genau das wollte ich UART mit IRQ und Timer IRQ nur 
funktioniert das bei mir nicht sie Beitrag LPC2148 hast du vielleicht 
eine Beispiel das funktioniert?

Autor: Martin Cibulski (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michael,

gerade habe ich diesen Thread gelesen und dass Du eine Teleskopsteuerung 
entwickelst. Ich möchte auch eine Teleskopsteuerung bauen, ein modulares 
System mit dem LPC2148 als Hauptprozessor und einem AVR mega16/32 (?) 
für die Motorsteuerung.
Du schreibst von Modemsignalen, da würde mich interessieren, wofür man 
die braucht bei einer Teleskopsteuerung. Nicht dass ich bei meinem 
Entwurf etwas vergesse, was dann später fehlt.

Dies ist mein erstes Projekt mit ARM-Prozessoren, meine alte Steuerung 
lief mit einem AVRmega128. Ich habe zunächst mit dem AT91SAM7S256 
experimentiert, möchte aber wohl lieber den LPC2148 verwenden. Besonders 
die Echtzeituhr mit Batteriepufferung ist von Vorteil bei einer 
Teleskopsteuerung.

Vielleicht können wir uns zu dem Thema austauschen ?

Mit freundlichen Grüßen
Martin Cibulski
http://www.martin-cibulski.de/atm/

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.