Forum: Mikrocontroller und Digitale Elektronik SW-Uart input abfrage abbrechen ?


von HansHans (Gast)


Lesenswert?

SW-Uart input abfrage abbrechen ?


Hallo,
Ich muß mehrere SW-Uart (90S8515)verwenden und habe das Problem
das ich an einer Stell auf 6 Zeichen warten muß.
Kommen die 6 Zeichen ist auch alles OK.
aber wenn sie nicht kommen (oder nur 5) hängt mein Programm.

gelöst habe ich es jetzt erst mal mit dem Watchdog aber
ich will nicht das ganze Programm neu Starten .

Ich denke eine Interruptroutine ist eine Lösung,
 die darf ich dann aber nicht mit Reti (Return) verlassen,
um nicht wider in der Warteschleife zu hängen, sonder
mit Goto aber was muß ich da beachten ?
Register zurücksetzen ?

Ich verwende Bascom aber das Problem ist ja sicher
nicht nur Bascom spezifisch  ...

Danke für eine Hilfe

Gruß HansHans

von Tobi (Gast)


Lesenswert?

warum nicht im interupt ein flag setzten wenn abgerochen werden soll und
dann ganz normal reti und in der schleife darauf prüfen und abbrechen
(in c heisst der befehl break, in bascom hab ich keine ahnung)

von HansHans (Gast)


Lesenswert?

Also anscheinend doch Bascom spezifisch

- - > und in der schleife darauf prüfen und abbrechen

auf die Bascom Befehle Inputbin oder Get habe ich aber keinen Einfluß
die Wartet nun halt mal auf ein Zeichen ....
oder habe ich was übersehen ?

Ideal wäre ein Befehl der nur max 0,5s den Eingang abfragt
 und nicht auf ein Zeichen wartet .

von crazy horse (Gast)


Lesenswert?

lass doch in der Empfangsroutine die Zeichen nur in einen buffer
schreiben, wieviele angekommen sind, steht in einer extra-Variablen.
Im Hauptprogramm fragst du nur die Anzahl der Zeichen ab, sind es
genug, liest du die Zeichen aus dem Buffer und wertest die dann erst
aus.

von HansHans (Gast)


Lesenswert?

- - > lass doch in der Empfangsroutine die Zeichen nur in einen buffer
schreiben
das geht aber bei Bascom nur mit dem HW-Uart für den
SW gibt es keinen Buffer und wenn man sich selber einen schreibt
bleibt der auch wieder hängen wenn man nach dem Zeichen fragt
und kein‘s kommt

oder habe ich die falschen Befehle für die SW-Uart Abfrage ?

von crazy horse (Gast)


Lesenswert?

wer will dich hindern, beim Software-Uart dasselbe wie beim
Hardware-Uart zu machen? Bei der HW-Uart löst normalerweise der Rxc-Int
dieses aus, beim SW-Uart macht man das halt nach 8,5Bitlängen nach der
fallenden Flanke des Startbit. Ich sehe da keinen prinzipellen
Unterschied.
-ext. Int mit fallender Flanke, Timer auf halbe Bitlänge setzen, ext.
Int sperren
-nach halber Bitlänge schauen, ob Startbit immer noch 0
 nein, war nur ein Rülps, ext. Int wieder freigen, Timer stoppen
 ja -> Zeichen beginnt
Timer auf volle Bitlänge stellen, in der Timer-ISR das Bit einlesen,
nach 8 bit ist das Zeichen komplett und wird in den Buffer geschrieben,
Schreibpointer erhöhen (max. prüfen, ggf. an den Bufferanfang
zurücksetzen), rec_byte_count incrementieren, fertig. Die komplette
Pufferung ist in jedem Fall Softwaresache. Zu Bascom-spezifischen
Sachen kann ich dir allerdings absolut nicht weiterhelfen.

von HansHans (Gast)


Lesenswert?

Hallo,
Danke crazy horse aber die ganze SW Routine wollte ich nicht
neu schreiben dafür habe ich ja Bascom ...

Ich habe eine Lösung gefunden, und mein Programm läuft.

Ich verlasse die Timer -Interruptroutine  ohne Return (Reti)
setze aber  Flag I (Bit.7 im SREG) und beende dann mit Goto,
somit stopt die SW-UART abfrage wenn nach 1s kein Zeichen kam .
Nachteil:
 4 Byte bleiben auf den Stack,
(warum 4 weis ich nicht, 2 waren mir klar)
jetzt mache ich 4 x POP R0
da ich denke (hoffe) das Register R0 von Bascom nicht benutzt wird.

Jetzt  meine neue Frage an die ASM Fachleute :
 Wie lösche ich in (mit) ASM 4 Byte vom Stack ?
ohne ein Register zu verändern ?
oder kann ich den Stack- zeiger  verändern ?
(meine letztes ASM Programm war noch mit einen Z80)

Danke für eine Hilfe......

von Rahul (Gast)


Lesenswert?

muss man da nicht nur den Stackpointer entsprechend modifizieren?
Also um 4 Positionen weiter oben verschieben (Stackpointer wachsen doch
immer noch von oben nach unten, oder?)

Zum Thema  SW-UART fällt mir eine AN vom Atmel ein (AVR304).
Allerdings ist die nur halfduplex. Da wird ein 8Bit-Timer benutzt.
könnte man das Ding bei Verwendung eines weiteren Timers nicht sogar zu
einer vollduplex-UART aufbohren, sofern man diesen Timer für nix anders
braucht?

Gruß Rahul

von HansHans (Gast)


Lesenswert?

--->Stackpointer entsprechend modifizieren
wie ist der ASM Befehl dafür ?
INCR ??  DECR ??

Gruß HansHans

von wb1 (Gast)


Lesenswert?

Versuch mal folgendes:

; dein interrupteinsprung

interrupteinsprung_von_uart:
;stack wurde um 2 erhöht, stack enthält ruecksprungadresse vom
;interrupt
;es werden zwei ramzellen benötigt
;register werden nicht verändert
sts ramadresse,temp1
sts ramadresse+1,temp2
ldi temp1,low(interruptabbruch)
ldi temp2,high(interruptabbruch)
;erst low-teil dann highteil pushen
push temp1
push temp2
lds temp2,ramadresse+1
lds temp1,ramadresse
reti

Damit hast du die rücksprungadresse manipuliert, deine interruptroutine
wird wie ein normaler call bearbeitet, neue interrupts sind zugelassen
und können bearbeitet werden


interruptabbruch:
;deine routinen
;deine goto-routine
;oder dein assembler wie zum Beispiel
ldi temp,irgendwas
; usw
;ende deiner routine
ret

von Peter D. (peda)


Lesenswert?

"Danke crazy horse aber die ganze SW Routine wollte ich nicht
neu schreiben dafür habe ich ja Bascom ..."


Das ist der Nachteil an allen vorgefertigten Systemen, Du kannst nur
die Funktionen nehmen, die der Entwickler für Dich vorausgesehen hat.
Brauchst Du was anderes, mußt Du es selber entwickeln.
Deshalb benutze ich kein Bascom.

Und da kommt der Vorteil von C ins Spiel:

In C gibt es nichts vorausgesehenes, sondern Bibliotheken.
Und diese Bibliotheken sind nicht monolitisch im Compiler mit
einzementiert, sondern sie liegen als kommentierter Quelltext vor und
jeder kann sie nach seinen Wünschen modifizieren und erweitern.
Deshalb benutze ich C.

Soweit ich bemerkt habe, hält sich Codevision aber nicht daran, sondern
da ist auch vieles einzementiert. Ist quasi ein verkapptes Bascom mit C
Syntax. Daher würde ich es auch nicht nehmen. Ich benutze WINAVR.



Den Stack zu manipulieren ist sehr unsauberes Programmieren !!!

Du kannst Dich nicht darauf verlassen, daß die Stackauslastung konstant
ist. D.h. solche Programme laufen bei geringen Änderungen an völlig
anderer Stelle oder auch bei einer anderen Compilerversion sehr gerne
gegen den Baum.

Ich würde es daher ausschließlich so machen wie crazy horse.


Peter

von Philipp Sªsse (Gast)


Lesenswert?

Das ist aber bitte kein Vorteil C vs. Basic! Selbstverständlich gibt es
Basics mit kommentierten Quellcodebibliotheken und C-Compiler ohne.
Basic oder C ist nur eine Syntaxfrage, keine Philosophiefrage. Und auch
in C gibt es "unvorausgesehendes"; die Sprache legt Dir auch
Einschränkungen auf, wie unzählige Fragen hier ("64-Bit-Variablen",
"gemeinsamer Pointer für RAM und Flash" fallen mir spontan aus
jüngster Zeit ein) belegen. Die Anpassungsfähigkeit von C hört halt
hinter den Funktionsaufrufen auf, wenn man an Operatoren und
Programmablauf gehen will, muß man dann doch Assembler einflechten, was
schnell arg kompliziert werden kann, weil man den Compiler selbst nicht
im Griff hat.

Also: deshalb benutzt Du WinAVR. Mit C hat das nichts zu tun.

von HansHans (Gast)


Lesenswert?

Danke ihr habt ja alle irgendwie recht aber warum immer
die Diskussionen ob ASM ,C Basic usw.
wechselt ihr bei jedem kleinen Problem eure Sprache ?
Wenn es ein Problem gibt muß es gelöst werden, mit dem
was man halt gerade hat, und bei ist es halt im Moment Bascom,
damit habe ich die auch bisher alles gelöst was ich gebraucht habe,
so auch in diesem Fall das Programm läuft bis jetzt problemlos
Da Register R0 frei ist,ob das nach Späteren Änderungen auch noch der
Fall ist weis ich natürlich nicht.
Deshalb such ich ja eine Lösung um 4 Byte vom Stack zu löschen ohne
ein Register zu verändern (Ram erlaubt)
Die Rücksprungadresse (wie von wb1 vorgeschlagen) zu ändere brauche ich
nicht mehr .
Nur  4 Byte vom Stack löschen ..... Mehr will ich nicht !!!
geht das mit ASM oder auch mit  Bascom ?
wenn ja wie ?
Danke ....
(Nur zur Info: In Bascom ist eigenes ASM erlaubt bzw möglich)

Gruß HansHans

von Tobi (Gast)


Lesenswert?

4x pop r0

trotzdem verdammt schlechter code. es geht ja auch besser, nur willst
du dir keine arbeit machen und lieber murksen

von HansHans (Gast)


Lesenswert?

-- >4x pop r0
das mache ich doch gerade!! ,
da verändere ich aber doch r0 ,
das will ich vermeiden

von wb1 (Gast)


Lesenswert?

Speichere ein register im ram, poppe und lade das register mit dem
ursprungswert.

beginn:
sts ramadresse,r16
pop r16
pop r16
pop r16
pop r16
lds r16,ramadresse

r16 ist unverändert, sp = sp-4

von HansHans (Gast)


Lesenswert?

Danke wp1 ,genau so ....

Das habe ich auch gerade gefunden ....
Bascom ASM mix ....

Var = Peek(0)
        pop R0
        pop R0
        pop R0
        pop R0
     Poke 0 , Var

Danke für eure Hilfe
Gruß HansHans

von Philipp Sªsse (Gast)


Lesenswert?

Der Vollständigkeit halber:

Natürlich kann man auch den StackPointer manipulieren, aber dazu muß
man ihn auch in ein Register holen (und dieses vorher retten).

Ein IN, SUBI und OUT sind gerade mal drei statt acht (für 4xPOP) Takte.
(Beim 90S8515 muß man freilich auch für den Fall der Fälle den Überlauf,
d.h. Unterlauf betrachten, hat also IN, SUBI, OUT, IN, SBCI, OUT und
damit auch 6 Takte ... bleib bei der Popperei!)


Aber: weiß jemand, was der Bascom da noch zusätzlich auf den Stack
legt? Da wird er doch mal vermutlich zu Beginn der Interruptroutine ein
von ihm benutztes Register ablegen und am Ende wiederherstellen. Wenn Du
nicht plötzlich vor einen Voodoo-Phänomen stehen willst, solltest Du da
nicht in unverstandenen Eingeweiden rumpfuschen, sondern das Compilat
disassemblieren, um zu sehen, was er da wirklich tut. Und dann würde
ich die entsprechenden Werte genau dorthin poppen, wo er sie vorher
weggepusht hat (falls meine Vermutung da stimmt). Dein Programm mag
jetzt laufen, aber je nachdem in welchem Moment das Interrupt
zuschlägt, sind vielleicht irgendwelche Register überschrieben, die der
Bascom für sicher hielt. Ich weiß es nicht, aber ich würde es
überprüfen.

von HansHans (Gast)


Lesenswert?

- - >sondern das Compilat disassemblieren
das habe ich gemacht daher wußte ich das r0 frei ist.
- - > aber je nachdem in welchem Moment das Interrupt zuschlägt
Ich gebe den Interrupt nur vor dem Start des SW-Uart frei und
sperre ihn gleich wieder wenn die Zeichen eingetroffen sind.
somit schlägt er nur innerhalb der SW-Uart Routine  zu wenn eine
Fehler in der Übertragung ist .
Das Programm läuft im Moment wirklich fehlerfrei ,
aber ich verspreche euch wenn ich wieder Zeit finde, versuche ich die
SW-Uart Routine von Bascom nochmals zu disassemblieren
und eine Zeitüberwachung direkt einzuarbeiten ,
dann werde ich aber sicher noch mal Fragen haben.
Im Moment muß ich aber erst noch andere Sachen machen .
Gruß HansHans

von crazy horse (Gast)


Lesenswert?

"Das Programm läuft im Moment wirklich fehlerfrei"

hihi, das kann wirklich nur ein Anfänger sagen, sorry. Ein Programm ist
nicht dann fehlerfrei, wenn es gerade das tut, was es im Moment tun
soll, also was der Programmierer eigentlich machen wollte. Die
Fehlerarmut (von Fehlerfreiheit will ich gar nicht mehr sprechen)
offenbart sich dann, wenn das Programm mit Zuständen (logischen und
zeitlichen) konfrontiert wird, die der Programmierer nicht explizit
vorgesehen hat. Und gerade dann Mist zu machen - dafür sind deine
Ansätze bestens geeignet. Es gibt Software, die läuft monatelang
scheinbar fehlerfrei, dann bockt es plötzlich. Wer denkt da an einen
Softwarefehler? Richtig, kaum einer, der nichts davon versteht. Es gibt
keinerlei Grund, solche Hilfskrücken einzubauen, und die Bemerkung - es
läuft ja - kannst du dir getrost sparen, das macht es nicht besser. Man
kann auch 230V-Lampen über Klingeldraht oder Koax anschliessen,
funktioniert auch.
Du handelst dir völlig unnötig Probleme ein, die vielleicht nicht mal
jetzt auftreten, sondern später, wenn du scheinbar harmlose Änderungen
machst oder ne andere Compilerversion benutzt. Und das alles nur, um
sich die Arbeit zu sparen, es mit ein paar Zeilen mehr richtig zu
machen, ich versteh es einfach nicht. Dazu kommt, dass man sich einen
solchen Stil angewöhnt...

von HansHans (Gast)


Lesenswert?

Hi,
Was soll ich jetzt noch machen oder bin ich euch schuldig ?

1. ich habe Nachbestellung versprochen obwohl das  Programm läuft
2. Ich programmiere kein medizinisches Gerät oder  Mondfähren.
3. Es ist nur ein Hilfsmittel zur Meßdatenerfassung
4. Wenn‘s ausfällt ist es unschön aber keine Katastrophe
5. vor meinen -- > „ Hilfskrücken“ hing das Programm min. 3 x am Tage
da z.B. ein Meßgerät plötzlich keine Daten mehr sendet
(Vom Profi programmiert )
6. Seit meiner „ Hilfskrücken“ hing es nicht mehr
Ich bin erstmals so zufrieden gelobe aber immer noch Nachbestellung

Gruß HansHans

von crazy horse (Gast)


Lesenswert?

mir persönlich ist völlig egal, was und wie du es machst. Ich wollte dir
nur klarmachen, das das, was du gerade machst, nicht die feine Art ist
und sich das früher oder später höchstwahrscheinlich rächen wird.
Software schreibt man heute nicht mehr "tricky" und kompakt um jeden
Preis, sondern übersichtlich und wartbar. Dazu gehört, sich an die
Konventionen zu halten. Stackmanipulationen gehören für mich zu den
Dingen, die man lassen sollte (zumindest wenn es auch anders geht), der
Stack gehört dem Compiler.
Und nun lassen wir es gut sein, ja?

von Peter D. (peda)


Lesenswert?

Wenn ich das richtig verstanden habe, arbeitet die SW-UART von Bascom
nur, wenn Du sie aufrufst.
D.h. Du kannst Dich immer nur mit einer unterhalten.

Ist es das, was Du wirklich willst ?
Sind dann nicht mehrere UARTs sinnlos ?


Ich benutze SW-UARTS nur, wenn ich sie gleichzeitig brauche und dann
müssen sie in einen Interrupt eingefügt werden.
Der (Timer-)Interrupt sammelt die Bits und legt sie in einem Byte ab
und setzt ein Flag, daß ein Byte empfangen wurde.
Diese Flags von jeder SW-UART kann man dann im Hauptprogramm testen und
die Bytes auslesen.

Es kommt also nie zu einem Festhängen in der Empfangsroutine.


Peter

von Philipp Sªsse (Gast)


Lesenswert?

[HansHans:]
> Ich gebe den Interrupt nur vor dem Start des SW-Uart frei und
> sperre ihn gleich wieder wenn die Zeichen eingetroffen sind.
> somit schlägt er nur innerhalb der SW-Uart Routine  zu wenn eine
> Fehler in der Übertragung ist .

Weißt Du, ob der Compiler ein Register vor dem Aufruf der UART-Routine
belegt und nachher wieder liest? Und vielleicht ist es gerade dieses,
das die Interruptroutine auf den Stack rettet, weil es das Register
dann anders benutzt.

Im Augenblick klingt das eher unwahrscheinlich, aber vielleicht
erweiterst Du das Programm irgendwann, und plötzlich gibt es dann
Probleme, wenn Du an diesen Kniff nicht mehr denkst. Aber das ist Dir
ja auch offenbar bewußt. (Und von wegen Anfänger: von all den Ratgebern
scheint ja auch keiner an die Gefahren gedacht zu haben ...)

Mich würde übrigens einfach nur interessieren, was der Bascom da macht.
Es schadet nie, zu wissen, wie ein Werkzeug arbeitet, damit man es
optimal einsetzen kann. Dazu müßtest Du ja nur die Interruptroutine
finden und schauen, was da gepusht und gepoppt wird.

von Christoph Seiwert (Gast)


Lesenswert?

Hallo HansHans,

ich hänge gerade an dem selben Problem.

Kann ich bitte mal einen aufschlußreichen Codeauszug von Dir haben ?

Das wäre bestimmt sehr hilfreich ...

vielen Dank

mfg
SMILEY

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.