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?
Hi, poste doch mal den Code, vielleicht kann man dir dann helfen. gruß marc
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?
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/microcontrollers/pdf/tn05007.pdf 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?
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.
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.
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.
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.
> 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.
Ach ja, zur Orientierung: Ein Interrupt-Handler für UART braucht auf 60MHz LPC2000 mit allem FIFO-Gedöns schlimmstenfalls 3-4 Mikrosekunden.
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?
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?
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.
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
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.
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?
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/
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.