Forum: Mikrocontroller und Digitale Elektronik 80c537 & Seriell Port ISR


von Gerd (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,
ich sehe hier ab und zu mal rein und finde diese Forum manchmal gute
Ideen und Lösungsansätze.
Nun, ich hab da auch ein Problem mit einem 80C537 der mit 24Mhz Takt
arbeitet. Ich benutze die zweite serielle Schnittstelle des Kontrollers
in halb Duplex bei 9k6. Ziel meiner Anstrengung ist es eine eigentlich
recht simple Fernbedienung an einem seriellen Bus (CIV) angeschlossen
ist. Die Entwicklungsumgebung ist der KEIL Compiler und ich benutze C
als Programmiersprache.
Leider schmiert mir das Programm des Kontrollers immer mal wieder unter
Last ab oder ich verliere Zeichen.
Eigentlich müsste ich noch viel mehr in der ISR machen aber wegen der
Probleme habe ich mir das schon mal gekniffen und erledige die
Vorauswertung der reinkommenden Telegramme beim Lesen des Rinpuffers im
Programm. Leider ist die Serielle nicht gut designed. Es fehlt natürlich
wieder ein adäquater Empfangspuffer. Ich dachte auch schon mal daran die
ISR in Assembler zu formulieren, jedoch so groß ist der generierte Kode
des C-Compilers nicht. Den Gewinn schätze ich nicht so hoch ein. Wenn
euch was dazu einfällt, bitte immer raus damit.
Eine Bitte noch vorweg. Ob der von mir benutzte Browser ok ist oder
nicht ist und soll nicht Gegenstand der Diskussion sein oder werden.
Das Projekt ist nur Hobby daher hat es auch keine wirklich hohe
Priorität.

Gruß aus Dortmund,
Gerd, DD4DA

von Peter D. (peda)


Lesenswert?

"Ob der von mir benutzte Browser ok ist oder nicht ist und soll nicht
Gegenstand der Diskussion sein oder werden."


Ich weiß jetzt nicht, was das mit Deiner Frage zu tun hat, aber gemault
wird nur bei sehr groben Fouls (Quelltexte als Word, PDF usw., Main ohne
Hauptschleife usw.).


Dein Programm ist leider nicht vollständig, daher sind Seiteneffekte
nicht zu erkennen.
Aber laß mal das "using 0" weg, das müßte tödlich sein.

"using" ist wirklich nur in absoluten Ausnahmefällen sinnvoll,
besonders als Einsteiger fährt man viel besser, wenn man die
Bankzuweisung dem Compiler selber überläßt. In der Regel klaut man sich
dadurch außerdem 8 Byte wertvollen SRAM.

Irgendein Idiot muß wohl bei 80C537 Beispielen "using" verwendet
haben und nun machen es alle nach und fliegen auf die Schnauze.


Peter

von Strombach (Gast)


Lesenswert?

ich weiss nicht ob es Sinn macht, den Int während der Routine
auszuschalten, es ist ja kein Taster oder sowas, das undefiniert
prellen oder zwischendurch noch mal ausgelöst werden kann. Bei 24 MHz
macht Dein Prozessor ca 25000 Befehle, bevor das nächste Byte vorliegt.
Da könntest Du schon fast auf die ISR verzichten und die Daten durch
polling abfragen.

von Gerd (Gast)


Lesenswert?

Wooh, das war jetzt schnell und auch noch erfolgreich. Ich habe die IRQs
zur Ausführungzeit der ISR unberührt gelassen und ebenfalls die "USING
0" - Anweisung radiert. Das Ergebnis ist überraschend positiv. Zum
einen fehlen jetzt keine Zeichen / Telegramme mehr und zuum anderen
kann ich mit 9k6 nun richtig Speed machen ohne das mir der Kontroller
die Löffel hängen lässt.
Noch ergänzend will ich erwähnen das dass Problem tatsächlich an dem
"USING 0" lag, warum auch immer. Ich benutze kein Bankswitching da
mein Programm eh in 2K Adressraum passen sollte. Mehr kann ich mit dem
Keil auch nicht linken da es die EVal-Version ist. Bequem ist die
Umgebung schon -mir kommt aber dann und wann schon mal der Verdacht
dass die Libraries nicht so ganz sauber sind. Zumindest sind die
Routinen der Lib manchmal etwas umständlich - verglichen mit dem ASM
Code den ivch von Hand schreiben würde und den den der Compiler/Linker
später dafür einsetzt. Lesbar ist er jedoch noch - wenn auch mit Mühe.

Das Gerät dass ich baue / programmiere soll mal meine Funkgeräte
(CIV-Schnittstelle ) steuern. Die Funkgeräte sind in Japan konstruiert
und so manch nützliche Funktion wurde gegen weniger nützliche
Funktionen auf dem Bedienpanel eingetauscht. Der PC löst dass Prblem
schon recht hübsch, jedoch wäre mir ein diskretes kleines Gerät lieber.
Ist transportabler und es ist kein Windows drauf.
Das Gerät soll via CIV-BUS die DSP-basierte implementation eines
quasi-variables Bandfilters in der ZF des Empfängers mit Hilfe eines
Poti und dem Kontroller die Bandbreite von aussen einstellbar machen.
Dazu benutze ich den ADC und ein paar Poti, errechne die Parameter und
forme das CIV-Telegramm und sende es an das Funkgerät.
Da alle Stellgrößen auf dem Panel digital sind lassen die sich gut von
aussen anfassen. Das muss aber schnell gehen.
Der zweite Schritt ist dann ein 25iger Tastenfeld mit hilfe dessen ich
Frequenz und andere Betriebmode Parameter schnell verstellen will ohne
dass ich mich wieder in die Menü's der Funkgeräte vergraben muss. Die
sind umfangreich und deren sachliche Zusammenstellung öffnet sich einem
Westeuropäer auch nicht auf Anhieb.
Nochmals meinen Dank für die schnelle und erfolgreiche Hilfe. So komme
ich doch schon weiter. In der Keil-beschreibung finde ich nicht viel
über das Verhalten von "Using" in einer Non-Bankswitching Umgebung.
Die gebes es in ihren Beispielen immer brav an. Ich unterstelle das
zahlende Kunden (3500 Euro) diese Info nicht vorenthalten wird.

Gerd, aus Dortmund
DD4DA

von Peter D. (peda)


Lesenswert?

"das dass Problem tatsächlich an dem "USING 0" lag, warum auch
immer."

Dann war wohl meine Vermutung richtig, daß das tödlich ist.

"using" sagt dem Compiler: Kümmere Dich nicht mehr um die
Registersicherung, denn ich mache das jetzt.

Blöd nur, wenn man dann ausgerechnet die Bank 0 nimmt, die ja auch das
Main benutzt. Der Interrupt zerhackt Dir also die Register und Dein
Main schmiert ab.

Die Registerbank hat auch nichts mit Codebanking zu tun, jeder 8051 hat
4 Registerbänke a 8 Register.


Und das mit den Interrupts abschalten stört zwar nicht, bringt aber
auch nichts.

Der 8051 hat nämlich eine besonders clevere Interruptlogik, die
Prioritäten unterstützt und dadurch die doppelte Ausführung der
gleichen Prioritätsstufe unmöglich macht.

Ein Interrupt könnte nur dann sich selbst unterbrechen, wenn man
innerhalb des Handlers die eigene Priorität hochsetzt.


Peter

von Thomas (Gast)


Lesenswert?

Ich glaube eigendlich nicht dass using 0 das Problem ist (war).
Meiner Meinung nach ist using 0 und weglassen das gleiche.

using 0 heist dass im Interrupt alle benutzten register auf
dem stack gespeichert werden. Die 0 gibt dabei die verwendete
Registerbank an. Mit using 1 kann der Compiler manchmal die PUSH
POP der Rn Register sparen.

Du hast keinen Ringbuffer programmiert!

Hier ein Beispiel wie ich das mache:

//Groesse des Rxbuffers
#define BUFFSIZE 0x20                  //muss 2er Potenz sein

void Serial2IRQ(void)  interrupt 16
{
  if (RI1)                             // RI1; RX IRQ-Handler
  {
     InBuffer[InBufCounter] = S1BUF;   // Zeichen in buffer
     InBufCounter++;                   // Lesezeiger weiterstellen
     InBufCounter&=BUFFSIZE-1;         // Buffer begrenzen
     RI1=0;                            // lösche RI1 FLAG
  }
  if (TI1)                             // Transmiter
  {
    TI1=0;                      // lösche TI1  Flag
  }
}

Achtung:
im Hauptprogramm muss immer wenn irgendwas mit InBufCounter gemacht
wird, der ser Int kurz gesperrt werden

Noch ein paar Bemerkungen zu den Libs:
Die sind wirklich sehr gut optimiert. Wenn du glaubst das in ASM
besser machen zu können dann solltest du den Programierstil überprüfen
Mann kann mit Keil so programmieren, dass so gut wie keine Libmodule
eingebunden werden.
Nochmal: USING hat nichts mit Bankswitching zu tun!

Thomas

von Gerd (Gast)


Angehängte Dateien:

Lesenswert?

Ich möchte anmerken dass ich kein professioneller Programmierer bin -
ich glaube ich würde verhungern, gemessen an der Zeit die ich für meine
Bastelprogramme brauche.  :-)
Was nun wirklich die Ursache für die ABstürze war, werde ich mal am
Wochenende untersuchen. Ob es einen Unterschied gibt ob USING 0 oder
"nichts" das glkeiche ist offenbart das Assemblerlisting des
Compilerlaufs.
Die Keil Umgebung ist sehr bequem und ich benutze sie gern. Leider kann
ich mangels der € 3500.- für das ProfDevKit, nur kleine Programme
schreiben und muss den Speicherbedarf etwas im Auge behalten. Was mir
ganz besonders gut gefällt ist der MON51. Wenn ich mal im Lotto
gewinne...
Ich hab nochmal die Ringpuffer-Nummer angehangen. So isses einer.

Nochmals vielen Dank für eure Hilfe.

Gerd aus Dortmund
DD4DA

von Gerd (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe mal die erzeugten ASM-Quellen des Compilers mit und ohne den
Einsatz von "USING 0" verglichen und als Anhang beigefügt.
Thomas, der Unterschied ist recht deutlich zu erkennen. Es ist wie
Peter schon vermutet hat, das ohne "Using 0" im Aufruf, mehr
gesichert wird bevor der eigentliche ISR-Handler ausgeführt wird und,
selbstverständlich im Anschluß wieder zurückgeholt werden.
Ich habe derweilen einige experimente mit dem Abschalten des IRQ wärend
der Ausführungzeit des ISR gemacht. Es macht derzeit keinen Unterschied
ob abgeschaltet wird oder nicht. Da die ISR eh mit Priorität von 3
(höchste) läuft und sonst kein weitere IRQ definiert ist, erwarte ich
auch keine Nebeneffekte. Das wird sich ändern wenn andere IRQ-Quellen
behandelt werden müssen. Ich hab da noch einen ADC-Wandler auszuwerten.
Evtl. kommt auch noch ein 25er Tastenfeld dazu.

Gruß Gerd

von Thomas (Gast)


Lesenswert?

Du benutzt meiner Meinung nach eine alte Version des Compilers.
Der Code bei using 0 ist schlicht falsch da der DPTR nicht gesichert
wird. Das ist (war) ein Bug im Compiler.
Wenn du die DPTR Features des 517 ausschaltest sollte der Code
identisch sein.
Da der DPTR bei dir auf den Stack kommt vermute ich mal dass du den
Large Mode verwendest oder?

Den IRQ speren solange die Interruptroutine läuft ist nicht notwendig.

Thomas

von Gerd (Gast)


Lesenswert?

Hallo Thomas,
der Compiler ist aktuell und bei Keil als eval zu saugen. Ich benutze
den Large Mode. Ob es ein Bug ist kann ich nicht sagen. Ich habe "mein
Problem mit dem USING 0" auch mal auf einer älteren Version probiert
und bin ebenfalls auf die Nase gefallen. Werde mir das Assemblerlisting
dazu mal ansehen und mit dem Aktuellen vergleichen. Na ja, ich möchte
mit den Registerbänken manuell nichts machen daher ist die USING
Problematik nicht wirklich ein Problem für mich.
Den Irq im Handler zu sperren hab ich weggelassen.
Ich bin aber darauf hingewiesen worden dass ich den IRQ sperren muss
wenn ich die Variable des Zeichenindex innerhalb des Haupprogramms
ändere - was ich ohne Zweifel mach wenn ich feststelle wieviele Zeichen
im Puffer sind. Ich werde jedoch den Teil der Auswertung mal probieren
in die ISR zu verlagern. Mal sehen ob ich genug Rechenzeit dafür übrig
habe. Das CIV-Protokoll ist so aufwendig nicht und daher hab ich nun
was für das kommende Wochenende.

Gerd

von peter dannegger (Gast)


Lesenswert?

"Ich bin aber darauf hingewiesen worden dass ich den IRQ sperren muss
wenn ich die Variable des Zeichenindex innerhalb des Haupprogramms
ändere"


Das ist korrekt.

In der Mainloop ist Sperren durchaus sinnvoll und sogar notwendig, wenn
mit Interrupts Variablen ausgetauscht werden müssen.

Im Handler selber ist es Mumpitz, da der sich nicht selbst unterbrechen
kann (s.o.).


Warum benutzt Du das Large-Modell ?

Es erzeugt etwa doppelt so großen Code und läuft nur halb so schnell.
Es macht nur Sinn, wenn man ständig mit sehr großen Datenmengen
arbeiten muß.


Einen simplen FIFO kann man auch im Small Modell als xdata deklarieren,
wenn er nicht mehr in die 256 Byte idata paßt.


Peter

von Thomas (Gast)


Lesenswert?

nochwas was ich vorher vergessen hatte.
Der Code mit using 0 wäre korrekt wenn du DPSEL in der main einmalig
am Anfang auf 1 gestellt hättest. Dann würde DPTR 0 für den Interrupt
verwendet werden DPTR 1 für den normalen Calltree.
Das beste ist immer noch "Use multiple DPTR" in den Optionen für
deinen Target auszuschalten.
Ich habe das gerade nochmal mit V8.02 ausprobiert.
ohne multible DPTR support passt der Code auch mit using 0.
Dabei habe ich bemerkt, dass S1CON im Gegensatz zu Dallas wohl nicht
bitadressierbar ist (Was für ein MIST)
mein Vorschlag mit  if(TI1) passt dann nicht. es muss dann heisen:
if (S1CON & RI1)

Thomas

von Gerd (Gast)


Lesenswert?

Hallo Peter,
warum ich das Large Modell benutze...mhh...wenn der Compiler/Linker
fertig ist habe ich es später mit ca 16Kbyte Code Segment size und etwa
32Kbyte XDATA Segment Size zutun. Ich kann die Module selber nicht
fertig übersetzten und binden - das erledigt später ein Freund für mich
der das Keil-PDK am Institut benutzen darf.
Zugegeben ist der Weg umständlich aber für mich ist das Programmieren
von Microcontroller nur ein Hobby und dafür wäre die Anschaffung des
Keil-Systems vorsichtig ausgedrückt, überzogen.
Die frei verfügbaren Umgebungen wie SDCC51 und andere sind mit was den
Aspekt des Debuggens betrifft, zu umständlich. Ich schreibe daher
mein Projekt in Lego Modulbauweise.
Mumpitz, ja recht hast Du - genau das ist es gewesen. Ich hab nochmal
etwas über die IRQ-Struktur und der Prioritäten gelesen nach dem ich
hier mit der Nase in den Senf gestossen wurde. Wichtiger ist
aufzupassen das beim anfassen der Puffer und Zeichenzähler in der Main
Loop auf den IRQ aufpasse. Werde mir den ISR nochmal
vornehmen.Grundsätzlich löffelt der schon mal nicht mehr ab und
verliert auch keine Zeichen mehr. Da scheint was zu gehen - will also
die CIV-Messages schon innerhalb der ISR wieder aus den Zeichen
zusammenbauen. Damit kann ich Speicher sparen denn die Steuerzeichen
muss ich nicht erst speichern sondern mit einem Handler gleich in eine
Message-Tabelle schreiben.
Noch eine Frage die sicherlich Ansichtssache ist. Ich habe es zum Teil
mit Funktionen zutun die mit mehr als einem Argument augerufen werden
müssen. Nun hab ich mir angeshen wie umständlich der Compiler die
Variablen in ASM übernimmt. Der Fummelt zum Teil mit den DPTR rum das
die Heide kracht. Wenn ich die Variablen global halte kann ich die
innerhalb jeder Funktion anfassen. Das würde den komplexen
Übergabeumgang sparen - schön ist das aber nicht. Wie machst Du sowas?
Schreibst Du die Funktionen komplett mit Übergabeparametern und
Retcode? Die Alternative wäre eine Struktur zu bauen und dann nur den
Zeiger auf die Struktur übergeben.

Gerd

von Gerd (Gast)


Lesenswert?

Dabei habe ich bemerkt, dass S1CON im Gegensatz zu Dallas wohl nicht
bitadressierbar ist (Was für ein MIST)
mein Vorschlag mit  if(TI1) passt dann nicht. es muss dann heisen:
if (S1CON & RI1)

Ja, ist verdammter MIST. Ich hab ein Makro für RI1 und TI1 gebaut. Ist
später (wenn ich noch mehr graue Haare hab) mal etwaseinfache zu lesen
was dort passiert ohne gross drüber nachdenken zu müssen das Siemens
beim S1CON und weiteren SFR gepennt haben. Beim S0CON sind die Flags
Bitadressierbar. Warum nicht auch beim zweiten Port öffnet sich mir
nicht.
Gerd

von Peter D. (peda)


Lesenswert?

"Nun hab ich mir angeshen wie umständlich der Compiler die
Variablen in ASM übernimmt. Der Fummelt zum Teil mit den DPTR rum das
die Heide kracht. Wenn ich die Variablen global halte kann ich die
innerhalb jeder Funktion anfassen. Das würde den komplexen
Übergabeumgang sparen - schön ist das aber nicht. Wie machst Du
sowas?"

Das sind die Folgen des Large-Modells und genau deshalb benutze ich es
nicht.

Es gibt überhaupt keinen Grund das Large-Modell zu nutzen. Die Größe
des Programms hat damit überhaupt nichts zu tun.

Im Small Modell muß man lediglich große Variablenfelder, die nicht mehr
in den idata passen als xdata deklarieren.

Large erspart Dir also nur Schreibarbeit für die explizite
Speicherbereichzuweisung bei großen Variablenfeldern.

Nimm mal Small und staune, wie klein die Programme plötzlich werden.

Lies Dir auch mal den C51-Primer durch.


Peter

von Gerd (Gast)


Lesenswert?

Hallo Peter,
C51-Primer - ja, gut Idee. Small Model hab ich mal eingeschaltet. Die
Codesize ändert sich um 1Byte. Large benutzt 1Byte weniger als Small.
Es sieht so aus als dass sich nicht viel ändert. Liegt evtl auch am
Compiler/Linker im Zusammenhang mit dem Umstand dass ich nur die EVAL
hab. Der Borland PC-Compiler für DOS unterscheidet auch zwischen den
Speichermodellen. Der generierte Code sieht erheblich anders aus. Es
ist schade dass der Compiler so teuer ist. Ist ein sehr schönes
Werkzeug.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

"Large benutzt 1Byte weniger als Small."

Bei kurzen einfachen Funktionen kann es durchaus nur ein Byte
Unterschied sein.

Sind nur wenige lokale Variablen zu bearbeiten, hält auch LARGE sie in
Registern und braucht den DPTR garnicht.

Du mußt das schon bei umfangreicheren Funktionen oder ganzen Programmen
betrachten, da wird der Unterschied wesentlich deutlicher.

Anbei mal ein Beispiel (15 Byte / 9 Byte)


Peter

von Gerd (Gast)


Lesenswert?

"Anbei mal ein Beispiel (15 Byte / 9 Byte)"

Der Compiler 8.02 für Windows erzeugt exakt den gleichen Code.
Die Fummelei mit DPTR liegt ja in der Natur der Sache. XDATA-Zugriffe
werden eben über die DPTR gemacht. Sieht halt nicht sehr schön aus und
schneller werden die Programme bei extensivem Genuss dessen, auch
nicht. ich hab das Array dass die CIV-Messages aufnimmt in das IDATA
Segment verlegt. Das geht sort recht gut ab. Nun kommt nochmal das
eigentliche Protokoll-Handling. Ich werde ncohmal versuchen es in den
ISR zu verlegen. Damit kann ich mir eine recht große Tabelle sparen und
eine Menge an Traffic innerhalb der Programme spare ich auch ein.

Gruß aus dem warmen (na endlich) Dortmund,
Gerd

von Gerd (Gast)


Lesenswert?

Der ISR für den 80c537 ist nun fertig und liefert erstaunlich lückenlose
Ergebnisse. Ich bin beendruckt wie schnell der doch betagte Controller
mit 19k2 ohne Handshake umgeht. Das CIV-Protokoll sieht sowas nicht
vor.

Nochmal meine Dank für die Hilfe.

Gerd aus dem warmen Dortmunder Westen

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.