Hallo zusammen, ich habe einen dspic30F6014A und Zeitkritische Aufgaben zu bewältigen. Dazu gehört unter anderem, über einen gewissen Zeitraum Aufgaben zu erledigen und die Ergebnisse dann zu Übertragen mittels UART. Dazu habe ich mir einen FIFO gebaut in dem ich die Ergebnisse schreibe und die UART soll sich diese dann abholen. Ich habe eine Zeitschleife die 100ms läuft. Nach dem schreiben in den FIFO soll sofort wieder mit den eigentlichen Aufgaben weiter gemacht werden. Das klappt auch alles soweit ganz gut, bis auf den entscheidenden Punkt, das die Übertragung der Daten (9-15 ASCII Zeichen) bis zu 15 ms dauert und die Zeitschleife erst dann wieder startet, was bedeutet: Diese ist dann 110-115 ms statt die geforderten 100ms. Ich kann zwar einen Teilsatz der Daten (5 Zeichen) in den UART Sende Buffer schreiben und dann weiter machen ohne das zu viel Zeit verloren geht (2-3ms wären OK), allerdings bei den kompletten Strings habe ich halt besagtes Problem. Alle von der Bibliothek zur Verfügung gestellten Funktionen haben das gleiche Problem mit der Übertragungsgeschwindigkeit wenn die strings größer sind als der eigentliche Sendebuffer der UART. Ich bin langsam am verzweifeln, habe schon das Netz durchforstet Bücher gewälzt, aber nirgends eine brauchbare Lösung gefunden. Vielleicht hat ja einer von euch auch schon mal ein gleichartiges Problem gehabt und kann mir irgendwie dabei helfen. Schonmal vielen Dank im voraus. Gruß Christian
Head Banger schrieb: > Ich habe eine Zeitschleife die 100ms läuft. Da liegt der Fehler. Warum benutzt du keinen Timer dafür und erledigst die Abarbeitung der Queue per ISR?
Hallo Werner, erstmal Danke für die schnelle Antwort. Habe mich da etwas unklar ausgedrückt. Die "Zeitschleife" ist ein 1ms Tick, realisiert mit dem Timer1. Alle anderen Aufgaben, auch das Empfangen von Befehlen und deren Verarbeitung, laufen und stören den eigentlichen Ablauf der Schleife nicht. An den Berechnungen die Ausgeführt werden liegt es auch nicht. Habe ja schon viele Möglichkeiten durchgespielt. Ich kann alles anlassen und schalte nur das Senden ab, schon läuft alles so wie gewünscht. Senden von UART_Buffer größe läuft auch, nur halt strings die länger sind halten auf. Das verschieben in den UART Buffer läuft mit Zeigern um unnötige kopiervorgänge zu minimieren. Das er hier verzögert wird höchstwarscheinlich daran liegen: while(!U1STAbits.TRMT); da er hier wartet bis der Sender wieder bereit ist und die anderen Zeichen verarbeiten kann. Aber ich weiss halt nicht wie ich das anders lösen kann das alle Zeichen des strings gesendet werden. Gruß
> Senden von UART_Buffer größe läuft auch, nur halt strings die länger sind > halten auf. Puffer (unmittelbar oder mittelbar) vergrößern oder Nachrichten verkürzen. Das war jetzt einfach.
Head Banger schrieb: > Das er hier verzögert wird höchstwarscheinlich daran liegen: > while(!U1STAbits.TRMT); > da er hier wartet bis der Sender wieder bereit ist und die anderen > Zeichen verarbeiten kann. Aber ich weiss halt nicht wie ich das anders > lösen kann das alle Zeichen des strings gesendet werden. Du wartest nicht per Polling auf das Freiwerden des Sendepuffers, sondern löst einen ISR aus, wenn das UART bereit ist, ein neues Zeichen aufzunehmen. Das sollte der PIC können.
Das sollte man eigentlich denken. Bei Polling wäre die Zeitverzögerung ja auch erklärbar. Es geht ja nicht drum das der Sendevorgang nicht klappt, sondern nur um diese 10-15ms Verzögerung die ich mir in dieser Anwendung absolut nicht leisten kann. void UART_TX(int bufSize) { while(bufSize) { FIFO_Get(sendBufPTR,&U1TXREG); // Zeichen in UART TX FIFO zum senden schreiben bufSize--; // while(U1STAbits.UTXISEL); while(!U1STAbits.TRMT); } } Diese Schleife kann ja erst weiterarbeiten wenn das Transmit Shift Register wieder leer ist und die nächsten Zeichen aufnehmen kann und sobald die bufSize dann abgearbeitet ist wird weiter gemacht. Übrigens der FIFO ist 64 Zeichen groß.
Du redest immer von zeitkritisch und benutzt dann Timer und Polling... Das widerspricht sich ! Der UART erzeugt einen INT wenn der Sendebuffer leer ist, da stellst du das nächste Zeichen ein, wenn es eines gibt, oder schaltest den INT ab (TXIE). Wenn ein Zeichen in den FIFO geschrieben wird, wird der TXIE eingeschaltet...
@ Head Banger (headbanger82) >ja auch erklärbar. Es geht ja nicht drum das der Sendevorgang nicht >klappt, sondern nur um diese 10-15ms Verzögerung die ich mir in dieser >Anwendung absolut nicht leisten kann. Ja eben, du schreibst die Daten im Pollingbetrieb. Sprich, nach jedem Zeichen wartest du, bis der Sendepuffer wieder frei ist. Während der Übertragung ist deine CPU damit blockiert. Und gerade bei langsamen 9600 Baud ist das ein volle Millisekunde, die pro Byte verplempert wird. Das Gegenteil davon ist Interruptbetrieb, dann klingelt jedes Mal der Interrupt, wenn ein neues Zeichen gesendet werden kann. Die CPU lädt dieses in den USRT und macht dann wieder andere Sachen. >Übrigens der FIFO ist 64 Zeichen groß. Ein FIFO nützt dir wenig, wenn du den nicht intelligent nutzt. Siehe oben. Was du hier hast ist ein klassisches Beispiel für blockierenden Programmfluß. Das Gegenteil lautet Multitasking.
Klappt jetzt. habe mich da gestern wohl etwas blöd angestellt. Vielen Danke erst mal. Zu dem Timer: Das funktioniert ganz gut. Da wird ein INT ausgelöst wenn der in Überlauf geht (1ms) und ein counter immer hochgezählt. So weiss ich genau wie viel Zeit vergangen ist und kann das in eine do while Schleife als Bedingung setzten und immer wenn die gewünschte Zeit abgelaufen ist, führt er die dann geforderten Aufgaben aus und geht wieder zurück in die do while. Ist eigentlich eine recht saubere und schnelle Lösung. Aber vielen Dank nochmal für euer Hilfe. Gruß
Den Fehler im FIFO, dann die ISR: void _attribute_ ((_interrupt_, _auto_psv_)) _U1TXInterrupt(void) { IFS0bits.U1TXIF = 0; if (sendBufPTR->readIndex != sendBufPTR->writeIndex) {// Wenn FIFO nicht leer dann... FIFO_Get(sendBufPTR, &U1TXREG); } } und der eigentliche Aufruf des ganzen ist dann nur noch: IFS0bits.U1TXIF = 1;
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.