Guten Tag, allerseits, Folgende Problem steht vor mir... Ich muss eine verbesserte zuverlässige Kommunikation zweier Systeme entwickeln, 1.Fall: mikrocontroller sendet ununterbrochen die auswertbare Daten an RS232 des STK500 -> PC empfängt die nur, aber muss imstande sein,die Anwenderbefehle zu senden, so dass der Controller die auch bekommt. Meine Frage ist wie erkennt stk500, dass die neue Daten vorhanden sind, während der Übermittlung? PC-Daten werden vermisst! Da die STK500 verfügt über RS232-Spare aber nur mit RXD,TXD (keine RTS,DTR,RI,CTS) Leitungen und die einfach blockiert sind wenn Controller sendet! Und wenn ich die Interruptausführung aufhalte, um nach neuem Input zu sehen, wird es nicht zum Überfühlen des Puffers kommen? Entweder muss ich die RS232 (inklusiv MAX202 ) neu konzepieren, oder die Hoffnung haben, dass das Überschreiten des Puffers nicht auftritt. 2.Fall: PC sendet ständig die Daten zum Nacharbeiten an STK500,dann möchte Controller was senden, werden es nach dem Auslösen des Interrupts die vom PC gesendete Daten verloren gehen?! was könnte man entwickeln, was die ganze Kommunikation zwischen PC und STK500 steuern kann( mit Fehlermeldungen und Aufhaltungen der Interrupts). Was benutzt man besser Polling oder Interrupt? Ich weiss einfach nicht wie ich anfange. Habt Ihr vielleicht wertvolle Tips für mich, wie ich das Problem angehe? Danke im voraus, (danke-für eure Zeit und Wissen :~)) mfg Alex )
>Was benutzt man besser Polling oder Interrupt?
Interrupt mit einem Puffer - für beide Richtungen.
Ich gehe davon aus, dass du mit STK500 den Controller meinst, der auf
das STK500 gesteckt wird; nicht die Programmier-Controller.
Zum Senden und Empfangen solltest du auf jeden Fall eine Kommunikation
mit Interrupts aufbauen, die die Daten in einen Puffer schreiben
(Empfang) und aus einem Puffer lesen (Senden).
In der Empfangs-Interruptroutine setzt du dann ein Flag, das der
Hauptschleife anzeigt, dass neue DAten empfangen wurden.
Die Puffer mußt du natürlich so groß auslegen, dass es zu keinem
Überlauf kommen kann. Die Grösse hängt also von der Baudrate, der
Datenmenge und der Verarbeitungsgeschwindigkeit dieser Daten ab.
steuern kannst du das ganze mit XON/XOFF (Softwarehandshake), ist normalerweise aber nicht erforderlich. Jedes einzelne Byte braucht rel. viel Zeit zur Übertragung und belastet den Prozessor im Interruptbetrieb kaum. Bei 9600 Baud beispielsweise tröpfelt etwa jede ms ein Byte herein, und du hast bei 16MHz 16.000 Takte, um das zu verarbeiten. Interruptaufruf, Byte abholen und im Buffer zwischen dauert vielleicht 50 Takte, also nur einen sehr kleinen Teil der zur Verfügung stehenden Zeit.
Danke Rahul, Ich arbeite mit Atmega8515 und in seine Architektur(Datenblatt) hat er UDR und Shift Register, die sich in USART befinden. Ich muss also zusätzliche Puffern schaffen wo ich die ankommmende Bytes kopiere, aber wenn die UDR und Shift Register voll sind, besteht keine Möglichkeit die Daten zu empfangen/senden? PC merkt das nicht und sendet weiter, infolge dessen gehen die Daten verloren. Wenn das vollständige RS232 wäre, hätte ich das Problemm nicht mehr, da ich anhang der Signale die Interrupts ausführen könnte.
Hast du das Datenblatt schonmal durchgelesen? Wenn du ein zeichen empfängst kann auch ein Interrupt ausgeloest werden und dort kannst du dafuer sorgen das das Zeichen in einen groesseren Puffer im RAM kommt.
Danke crazy horse, ich benötige ein zusätzlichen Signal, um neue Daten zu identifizieren, da Receive und Transmiter benutzen gleiche UDR und Shiftregister,dadurch wird es nicht gewährleistet dass ich gleizeitig senden/empfangen kann. ich kann die Sendephase des Controllers unterbrechen,weil ich dafür gleichen Register(Flags) benötige
An Wolfram,danke, o.k. Aber wie kann ich interrupt mit einem neuen interrupt unterbrechen? Da zum Senden auch ein Interrupt benutzt wird?
>Wenn das vollständige RS232 wäre, hätte ich das Problemm nicht mehr, >da ich anhang der Signale die Interrupts ausführen könnte. Der AVR hat eine vollständige serielle Schnittstelle. Sobald der Controller ein Byte empfangen hat, löst er ein Interrupt aus, das Hauptprogramm wird unterbrochen und die Interrupt-Service-Routine (ISR) wird aufgerufen. In dieser Routine liest man das UDR aus und sichert es in einer Variablen. Diese Variable kann teil eines Arrays sein. Es wird noch ein Flag gesetzt, das dem Hauptprogramm signalilsiert, dass neue Daten eingetroffen sind. Ist die ISR zuende, macht der Controller an der Stelle weiter, wo das Hauptprogramm unterbrochen wurde. Dieses Hauptprogramm durchläuft dauernd eine Abfrage, ob das Flag gesetzt ist, und reagiert entsprechend darauf. Sooo schwer ist das nicht!
Jungs,vielen Dank an alle Beteiligten, aber ich versuche die Situation zu beschreiben, wo gleichzeitig oder mit ganz minimalen Verluste kommunitiert wird. Oder durch eine Meldung der Datenfluss umgeleitet/aufgehaltet wird
Die Handshake-Signale kannst Du voll vergessen. Das sind nur zusätzliche IO-Pins, die UART kümmert sich keine Deut darum. Was Du brauchst, ist ein Protokoll, z.B. ein Ping-Pong Protokoll: Jede Station weiß, wie groß der Puffer der Gegenseite ist und sendet dann Blöcke, die max so groß sind und wartet dann auf ein Signal, daß sie den nächsten Block senden darf. Z.B. haben ich in meinem ATmega8 512 Byte Puffer eingerichtet, d.h. der PC darf maximal 512 Byte am Stück senden und muß dann auf Antwort warten. Um nun zu prüfen, ob ein Block gültig ist, hängt man z.B. noch ne 16Bit CRC mit ran. Peter
>um neue Daten zu identifizieren, da Receive und Transmiter benutzen >gleiche UDR und Shiftregister Die heissen vielleicht gleich. Es sind aber 2 unterschiedliche Register, die unter der gleichen Adresse angesprochen werden. Wenn man versucht, das Sende-UDR auszulesen, bekommt man den Inhalt des Empfangs-UDR geliefert.
An inoffizieller WM-Rahul, Nein eben nicht die hat nur 2Leitungen RX TX.Die anderen sind gekreuzt oder auf Masse gelegt(Schaltplan),dadurch werden nicht alle Möglichkeiten der RS232 erschöpft. Ich werde dankend eure Antworten entgegenehmen(VIELEN DANK) ich muss nur kurz weg(ca.20min) sorry,sorry,sorry, bis dann MFG Alex
"...Receive und Transmiter benutzen gleiche UDR und Shiftregister,dadurch wird es nicht gewährleistet dass ich gleizeitig senden/empfangen kann." Quatsch mit Soße. Du hast nicht ins Datenblatt geschaut. Der Name UDR ist zwar gleich, aber schreiben und lesen gehen auf 2 verschiedene Register ! Die UART ist daher sehr wohl Voll-Duplex fähig. Peter
>Nein eben nicht die hat nur 2Leitungen RX TX.Die anderen sind >gekreuzt oder auf Masse gelegt(Schaltplan),dadurch werden nicht alle >Möglichkeiten der RS232 erschöpft. Ja, und? Wie Peter schon schrieb: Die restlichen Leitungen sind irrelevant. Dein Puffer muß nur die entsprechende Grösse haben. Die brauchst du bei 16MHz aber eigentlich auch erst dann, wenn du auf einen Schlag mehr als 2 Bytes verarbeitest (z.B. Strings). Wenn du wirklich ein Hardware-Handshake bauen willst/mußt, dann kannst du Portpins und einen weiteren MAX202 (oder einen MAX232 o.ä.) nehmen. Um das Handshake musst du dich aber dann selber kümmern. Soweit ich weiß, kümmern sich andere (externe) UART auch nicht um die Handshake-Leitungen. Das sind nur irgendwelche Pins, die auf das Ändern von Registern im Chip reagieren. Die Engangspins auf RS232-Seite könnten vielleicht noch einen Interrupt auslösen. Den muß der Host-Controller aber auch auswerten. Vielleicht erzählst du mal was zu den Randbedingungen: Wieviel Daten bei welcher Baudrate und wie schnell müssen die verarbeitet werden? Was soll der Controller überhaupt machen? [OT] Vielleicht solltest du mal in eine Tüte atmen. Du scheinst mir etwas zu hyperventilieren. >ich muss nur kurz weg(ca.20min) Kacken? [/OT]
Irgendwie siehst du Probleme, wo gar keine sind. Bevor du eine verbesserte Kommunikation zwischen 2 Systemen entwickelst; hast du schonmal eine einfache Kommunikation zwischen 2 Systemen entwickelt? Statt ueber das darüberliegende Protokoll, diskutieren wir hier gerade über die Funktionalität einer UART. >Aber wie kann ich interrupt mit einem neuen interrupt unterbrechen? >Da zum Senden auch ein Interrupt benutzt wird? ??? das ist überhaupt nicht nötig und selbst wenn es passieren würde, ist das egal, da die jeweiligen Zwischenpuffer unabhängig sein sollten. Die angesprochenen Zwischenpuffer hast DU zu programmieren.
Cool,danke für Eure Hilfe. An Peter Dannegger: >Was Du brauchst, ist ein Protokoll, z.B. ein Ping-Pong Protokoll. GENAU DAS BRAUCHE ich! >Die UART ist daher sehr wohl Voll-Duplex fähig ja jetzt gerufft. >Um nun zu prüfen, ob ein Block gültig ist, hängt man z.B. noch ne 16Bit CRC mit ran. könntest du noch mal erklären, was du meinst. An inoffizieller WM-Rahul >Vielleicht erzählst du mal was zu den Randbedingungen >Vielleicht solltest du mal in eine Tüte atmen. ja, ich sollte :) An Wolfram >hast du schonmal eine einfache Kommunikation zwischen 2 Systemen entwickelt? ja habe ich. Die waren nicht so umfangreich und kompliziert. Aber eigene Protokoll( Peter's Vorschlag) zu entwickelt, kann ich noch nicht :(( ich werde mich noch etwas verbessern in Frage USART bevor ich euch mit meine dumme Fragen belästige... Anfänger-Mangelhafte Wissen,Geduld und Wille
>schonmal eine einfache Kommunikation zwischen 2 Systemen entwickelt? >ja habe ich. Die waren nicht so umfangreich und kompliziert. dann verbessere deine einfache Kommunikation auf eine Kommunikation mit Interrupts und zwischenpuffern, das ist die Grundlage auf der die Protokollschicht dann aufsetzt. Hier zur Ansicht mal ein Bsp. fuer den Sendeteil mit Ringpuffer struct Seriell_Senden { char Buffer[Seriell_SendbufferSize]; volatile unsigned char outp; volatile unsigned char inp; }Seriell_Senden; FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, uart_getchar,_FDEV_SETUP_RW); ISR(USART_UDRE_vect) //TransmitInterrupt { if (Seriell_Senden.outp!=Seriell_Senden.inp) {//Zeichen in Puffer Seriell_Senden.outp=(unsigned char)(Seriell_Senden.outp+1)%Seriell_SendbufferSize; UDR=Seriell_Senden.Buffer[Seriell_Senden.outp]; } else {//Sendeinterrupt aus UCSRB&=~(1<<UDRIE); } } int uart_putchar(char c,FILE *stream) { unsigned char tmp; tmp=((unsigned char)(Seriell_Senden.inp+1)%Seriell_SendbufferSize); while (tmp==Seriell_Senden.outp){}//solange kein Platz im Puffer warte Seriell_Senden.Buffer[tmp]=c; Seriell_Senden.inp=tmp; //SendeInterrupt auslösen UCSRB|=(1<<UDRIE); return(0); }
An Wolfram: danke für den Beispiel :) ich hab riesen Problem, die Struktur des Ping-Pong Protokoll zu verstehen. Wie genau sollte das Erlaubnis zum Weitersenden erfolgen? Oder die Bestätigung über das erfolgreiche Empfangsergebnis aussehen? Wie könnte es auf code-Ebene aussehen?
http://www.mikrocontroller.net/forum/read-2-426342.html#new Hi, indem Beispiel benutzte ich ein FIFO als Empfangsbuffer. Du koenntest die Daten jetzt sammeln und am Ende auswerten. Für das Senden kannst du Dir auch ein FIFO bauen und dann per ISR die Daten vom FIFO aus senden. Ich hab die Funktionen verbessert und gestern abend mal ein bischen Ping Pong gesendet und konnte kein Datenverlust feststellen. Gruß, Dirk
Hallo, es hindert Dich niemand, einen kompletten Hardware-Handshake aufzubauen, wenn Du viele Daten in beide Richtungen schicken mußt und Datenverlust sicher verhindert werden soll. Du brauchst dann 4 Portpins, 2 als Eingang und 2 als Ausgang. Dazu brauchst Du die nötigen Pegelwandler (ein kompletter 232 z.B.). Um die Ansteuerung muß Du Dich allerdings komplett in Deiner Software kümmern... Aufpassen dabei, wenn Du Stop zum PC schickst, hört der erst auf zu senden, wenn der interne Buffer des IO-Chips leer ist, da können durchaus nach dem Stop-Signal einige Byte Daten kommen. Ob es allerdings einfacher ist, als eine reine Softwarelösung, bezweifle ich erstmal. Du brauchst einen FIFO zum Senden, einen zum Empfangen. Senden/Empfangen jeweils in einer Interruptroutine Byte-weise. Buffer z.B. 128Byte. Wenn Du beim Empfang bei 96Byte bist, Stop zum PC senden. Wenn Du wieder auf 32Byte bist, dem PC Senden Empfang wieder erlauben. Beim Senden genauso: erst schauen, ob der PC empfangen kann, wenn ja, dann senden, enn nicht, warten. Wenn man es einmal eingebaut hat, hat es den Vorteil, daß man sich um den ganzen Kram nicht mehr kümmern muß, nur noch im Hauptprogramm die Daten aus dem Buffer abholen bzw. den Sendebuffer nachfüllen, wenn nötig. Das geht aber dann ohne irgendwelche Zeitkritischen Geschichten. Gruß aus Berlin Michael
danke Dirk, dein code ist sehr hilfsreich, ich werde mir das genau anschauen! danke Michael für die ausführliche Beschreibung der Vorgehensweise, aber ich muss erst mal klarmachen, wie es in meinem Protokoll die Bedingungen aussehen werden,nach welch Kriterien gehandelt wird. Vielen Dank an alle, Ihr habt noch ein verzweifelten Anfänger 'gerettet' !!!! Ich melde mich noch ein mal, als es etwas deutlicher wird Mit freundlichen Grüssen, Alex Nik.
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.