Hallo, bin gerade daran, mir Routinen für die serielle Schnittstelle mit Interrupt-Betrieb zu schreiben. Verwendet wird ein Buffer. Jetzt stellt sich mir die Frage, wann und wie ich das Senden einleiten soll. Nach meinem Verständnis sollte ich das Senden aus dem Buffer ja einleiten, sobald sich min. 1 Zeichen im Sende-Buffer befindet, richtig? Also müsste ich einfach das TI-Bit setzen. Wenn ich jetzt z.B. bereits 5 Zeichen im Sende-Buffer habe, und jedesmal das TI-Bit setze, wenn ich ein Zeichen eintrage, startet ja gleich der Sendevorgang, was mir das gerade zu sendende Zeichen versaut. Auch richtig? Wie also kann ich das Problem lösen? Mein Lösungsansatz wäre, ein Flag zu verwenden, welches mir anzeigt, ob bereits gesendet wird. 1. Dieses Flag wird NUR von der Sende-Interrupt-Routine gesetzt und gelöscht. - Gesetzt, solange gesendet wird. - Gelöscht, wenn sich keine Zeichen mehr im Sende-Buffer befinden. 2. Das Senden selbst wird von der Routine eingeleitet, die auch das Zeichen in den Sende-Buffer schreibt. Sie setzt das TI-Bit, aber nur dann, wenn a) das Flag gelöscht ist und b) sich nur 1 Zeichen im Buffer befindet. Kann das so funktionieren? Oder gibt es vielleicht einen anderen (besseren) Ansatz? Gruß Ralf
Das TI-Bit setzt der 8051 selbst, wenn die Sendung durch ist. Das genaue Vorgehen hängt von Deiner gesamten Software ab. Du könntest beispielsweise in Deiner send_ser-Routine das erste Zeichen des Puffers übergeben und dann im Transmit-IRQ jeweils das nächste Zeichen des Puffers in den SBUF schieben, bis der Puffer leer ist.
Hallo Ralf, zunächst zu den RI und TI bits. Beide werden von der Hardware des 8051 gesetzt und müssen unbedingt in der IRQ-Routiene gelöscht werden, sonst kommt der µC nicht aus dem Interrupt raus (wird oft falsch gemacht). Wenn die SER_IRQ-Routine sehr lang ist, sollte das Bit sogar schon am Anfang gelöscht werden (falls bis zum Ende des IRQ schon wieder ein neues Zeichen angekommen ist). Das wäre dann aber schon vom Timing her sehr kritisch... Mit der Sendeprozedur habe ich es ähnlich gemacht, wie Du beschrieben hast. auch bei mir gibt es eine buf_sending Bitvariable, die mir anzeigt, ob ich gerade "am senden bin". Gruß, Markus_8051
Interruptrelevante Bits/Flgas sollten IMMER zu Beginn zurückgesetzt werden. Denkt mal an sich gegenseitig unterbrechende INTs und die damit verbundene zeitliche Verzögerung / Verschachtelung. Die Tatsache, daß eine Int-Anforderung schon wieder bestehen kann, wenn eine alte noch abgearbeitet wird ist als solche noch nicht flasch und beis sehr stark asynchronem Betriebsfällen durchaus sinnig und noch nicht gefährlich, z.B. wenn eine Senderoutine / Schleeife einen Tick langsamer rotiert als die sie fütternde Informationesquelle. Dass sich die INTs nicht "verheddern" muss logistisch gelöst werden- und zwar vornehmlich dadruch, daß die Applikation nicht die CPU überlädt. Wer Probleme mit auslaufenden INTs (Neuanstoss bei noch nicht vollständiger Abarbeitung infolge zu starker Verschachtelung) hat, sollte zu Beginn eines INTs eine Variable hochzählen und am Ende runterzählen. Schaufelt man die auf einenPort, so kann man am Oszi mitlesen, wie tief die INTs im einzelnen laufen.
@Jürgen, "Interruptrelevante Bits/Flgas sollten IMMER zu Beginn zurückgesetzt werden." Beim Programmieren gibt es kein IMMER ! Es hängt immer vom ganz konkreten Fall ab. Z.B. beim Philips/Atmel Hardware-I2C muß das Interruptbit IMMER als letztes gelöscht werden ! Beim CAN-Bus ist das genauso. Man muß erst die Nachricht auslesen und danach darf man das Interruptbit löschen, womit der Empfangspuffer wieder als bereit markiert wird. Nachfolgende Lesezugriffe liefern entweder völlig unsinnige Daten oder ein alt/neu-Gemisch. Es gibt in der Regel immer eine eindeutige Kausalitätskette, die unbedingt einzuhalten ist. Peter
Naja, das sollte ja wohl klar sein, daß zunächst die Anforderung also solche abgearbeitet werden muss, da das löschen den Int-Flags die Bestätigung dafür ist. Meine Aussage war auch so zu lesen, daß die Besttätigung zu erfolgen, bevor in die Verarbeitung der Nachricht eingetreten wird - also in den wirklich unteerbrechbaren Teil einer ISR. Dies muss zeitlich ja auch möglich sein, da z.B. ein Wiedereintritt in eine Can-Lese/Schreibroutine OHNE Auslesen des Registers sowieso zum Unfug führen würde.
Hallo zusammen, vielen Dank für die vielen Antworten. Ich sehe schon, ich sollte wohl erstmal meinen Block und einen Stift zücken, und mir einen gescheiten Ablaufplan erstellen (ist so etwas eigentlich bei der Erstellung von Profi-Software noch üblich?!?). Da ich auch Handshake mit einbauen muss, wird es wohl etwas komplexer. @Andreas: Du hast geschrieben, dass die TI/RI-Bits automatisch von der Hardware gesetzt werden. Das weiss ich. Aber ich hätte es jetzt so gemacht, dass ich das TI-Bit einmal setze, was die Sende-Interrupt-Routine an den Start bringt. Soll heissen, ich beschreibe nicht SBUF, das bleibt allein der Interrupt-Routine vorbehalten, denn nach meinem Verständnis muss es die Interrupt-Routine sein, die den Handshake abwickelt. Gruß Ralf
"Erstellung von Profi-Software noch üblich?!?" Kommt drauf an: Dort, wo rasch , effizient gearbeitet wird, die APP klein und überschaubar ist, oder es auf Code-Optimierung ankommt, wird noch im Kopf und auf Zettel gearbeitet und hardwareorientiert feinoptimiert. Dort, wo 5 Mann an einem Projekt sitzen, Fremdcode eingeflochten werden muss, Auf Widerverwendbarkeit Wert gelegt wird und Codegeeneratoren verwendet werden sollen und düerfen, wird alles in UML geklopft und geparst. (Theoretisch wnigstens :-) Dum könntest Deine Ablaufdiagramme aber mit einem UML-Toll entwicklen, dann hast Du wenigsten den halben Schritt dahin getan ...
UML?!? Ist das so ein Tool, in dem man den PAP erstellt, und das Tool generiert daraus den Code? Naja, ich weiss nicht... Ich bin mittlerweile auf C umgestiegen, das erste Projekt ist ein ISP-Programmer für die AT89S-Serie von ATMEL. Funktioniert auch, bis auf einen Bug, der nicht von mir kommt, sondern vom Terminal-Programm. Ich könnte jetzt einfach im Terminal-Programm eine Millisekunde Wartezeit zwischen jedem Byte einfügen, dann reagiert das Terminal-Programm richtig auf meinen Hardware-Handshake, aber das wäre meiner Meinung nach gemogelt. Aus diesem Grund möchte ich auch die interruptgesteuerte Kommunikation aufbauen. Damit müsste sich das Problem lösen lassen. Aber eben Handshake einbauen ist knifflig. Gruß Ralf
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.