Forum: Mikrocontroller und Digitale Elektronik serieller Interrupt beim 8051


von Ralf (Gast)


Lesenswert?

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

von Andreas (Gast)


Lesenswert?

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.

von Markus_8051 (Gast)


Lesenswert?

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

von Jürgen Schuhmacher (Gast)


Lesenswert?

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.

von peter dannegger (Gast)


Lesenswert?

@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

von Jürgen Schuhmacher (Gast)


Lesenswert?

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.

von Ralf (Gast)


Lesenswert?

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

von Jürgen Schuhmacher (Gast)


Lesenswert?

"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 ...

von Ralf (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.