Forum: Haus & Smart Home Strukturierung Buszugriff -> ext.Interrupt vs. Timerroutinen


von Gast Andy (Gast)


Lesenswert?

Hallo zusammen,

ich hätte eine prinzipielle Frage zur Strukturierung Eurer Programme, 
d.h.es geht mir weniger um konkreten Code als ein paar Anregungen :-)

Bei meinem Hausbusprojekt (RS485 mit 10kBd) werden die Bytes in der Form 
1Startbit(low) + 8Datenbits + 1Stopbit (high) übertragen.

Da für diverse Software-Counter usw. alle 100ms eine Timer-Routine 
aufgerufen werden muß, kann es ja vorkommen, daß gerade in dieser
ein RX-Event vom Bus auftritt. Solange die Timer-Routine kurz genug ist 
kein Problem.
Wenn aber auf Grund von Erweiterungen diese zukünftig so groß wird, daß 
sich der 1.Samplepoint über das Startbit verschiebt gibt es ein 
Empfangsproblem.

Wie könnte man das in den Griff kriegen?
Die Timerroutine sofort verlassen bzw. die ext. Interrupts während der
Timerroutine zu deaktivieren scheint mir nicht sinnvoll.


MFG
Andy

von MC (Gast)


Lesenswert?

>Bei meinem Hausbusprojekt (RS485 mit 10kBd) werden die Bytes in der Form
>1Startbit(low) + 8Datenbits + 1Stopbit (high) übertragen.
also benutzt du den mormalen UART, oder nicht?

>Wenn aber auf Grund von Erweiterungen diese zukünftig so groß wird, daß
>sich der 1.Samplepoint über das Startbit verschiebt gibt es ein
>Empfangsproblem.
Wenn du den internen UART deines µCs benutzt, sollte das kein Problem 
sein.

>Wie könnte man das in den Griff kriegen?
Mein persönlicher Vorschlag wäre, ein modernes 8051 Derivat zu nehmen, 
welches einerseits für deine Anforderungen schnell genug ist, 
andererseits Interruptprioriäten besitzt (bis zu 4 Stück).

von Gast Andy (Gast)


Lesenswert?

Hallo MC,

nein ich verwende nicht den UART.
Der ext.Int0 Pin vom Mega8 hängt am RX-Ausgang des RS485-Treibers.
Der Bus ist multimasterfähig incl. Kollisionserkennung. Alles in SW 
gelöst (das ganze Bustiming ist ziemlich aufwendig, aber man lernt viel 
dabei und der Weg ist das Ziel :-)
Um einen recessiven und dominanten Pegel wie beim CAN zu realisieren 
hängt an den Datenleitungen ein Pullup und Pulldown. Zum Senden wird der 
Tranceiver en- und disabled.

MFG
Andy

von Axel (Gast)


Lesenswert?

Was für Erweiterungen an der Timerroutine erwartest Du denn ?

Ich habe in der Timer Routine nur einen Zähler, der inkrementiert wird 
und dann wird die Routine wieder verlassen.

Die ganze weitere Software nutzt diesen Zähler. Damit sollte bei 10kBaud 
immer genug Zeit sein, um aus der Zählerroutine rauszuspringen und in 
die Interruptroutine rein.

Allerdings ist bei mir auch nichts Zeitkritisches, was nicht eher im 
Rahmen von Sekunden als ms abgehandelt werden kann.

Gruss
Axel

von Andreas K. (a-k)


Lesenswert?

AVR hat zwar keine priorisierten Interrupts in Hardware, aber stapeln 
dürfen sich die schon. Und solange dein Timer-Interrupt nicht so lange 
dauert, dass er sich irgendwann selber überholt, spricht nichts dagegen, 
darin die Interrupts sofort wieder freizugeben. Braucht nur etwas mehr 
Platz auf dem Stack.

Hast du dir die Aufgabe per Soft-UART mit Absicht möglichst kompliziert 
gemacht?

Warum hast du an Stelle des vergewaltigten RS485-Transceivers keinen 
CAN-Transceiver verwendet?

von Gast Andy (Gast)


Lesenswert?

Hallo zusammen,

Danke für Eure Antworten!

@Axel
>was für Erweiterungen an der Timerroutine erwartest Du denn ?

Momentan habe ich 8 Delaycounter (8bit) für die Eingänge (Reedkontakte 
etc.), einen Systemcounter (32bit), einen Counter (8bit) für den 
Diagnosezustand und natürlich die Uhrzeit + Datum. Die eigentliche 
Applikationsschicht existiert ja noch nicht. Wenn später dann noch für 
die Programmierung der Rolläden ein paar zusätzliche Abfragen mit rein 
sollen, bin ich schnell an der Grenze.

Ich sample jedes Bit 3x und mache einen Mehrheitsentscheid, d.h. nach 
Auftreten des Interrupts vom Bus muß spätestens nach 25µs der erste 
Sample kommen, d.h. diese 25µs sind das Limit. Vielleicht braucht man 
dieses Oversampling nicht unbedingt - wie löst Ihr das?

In den Interrupthandlern werden bei mir nur Flags gesetzt und in der 
Mainloop dann in die entsprechenden Routinen gesprungen.

@Andreas Kaiser
>Warum hast du an Stelle des vergewaltigten RS485-Transceivers keinen
CAN-Transceiver verwendet?

Ich wollte einfach ein adressbasiertes Bussystem haben und kein 
messageorientiertes, außerdem auch mehr als 8 Datenbytes pro Telegram 
übertragen (die Baudrate 10kBd vs. 500 kBd mal außen vor).

Ich habe mal irgendwo hier im Forum gelesen, Busprogrammierung sei was 
für Masochisten - ganz so falsch ist das nicht, d.h. viele Ansätze und 
viele Irrwege ;-)

MFG
Andreas

von Andreas K. (a-k)


Lesenswert?

Gast Andy wrote:

> Ich wollte einfach ein adressbasiertes Bussystem haben

Einen CAN Controller hatte ich auch nicht erwähnt. Nur CAN 
Transceiver-Bausteine wie PCA82C250, und die sind auch direkt mit UART 
verwendbar.

von Wasweissich (Gast)


Lesenswert?

>Momentan habe ich 8 Delaycounter (8bit) für die Eingänge (Reedkontakte
>etc.), einen Systemcounter (32bit), einen Counter (8bit) für den
>Diagnosezustand und natürlich die Uhrzeit + Datum.

>Solange die Timer-Routine kurz genug ist kein Problem.

Zwar schreibst Du:
>In den Interrupthandlern werden bei mir nur Flags gesetzt und in der
>Mainloop dann in die entsprechenden Routinen gesprungen.
Aber gilt das auch für die Timer?
Im Moment habe ich den Vermutung, das Du das hochzaehlen und die 
Auswertung aller dieser Zaehler in einem einzigen Interrupt erledigst.
Falls das so ist, ist das unnötig. Du kannst das hochzählen ausserhalb 
erledigen.

Aber auch wenn nicht: Es gibt eine Methode mehrere Timer zu "simulieren" 
und dabei eigentlich nur einen einzigen Timer tatsächlich bei jedem Tick 
hochzuzählen. Gibt natürlich einen gewissen Verwaltungsaufwand, aber ab 
einer gewissen Zahl von Timern lohnt sich das dann.

Insgesamt, ob so oder so, muss Deine Performance natürlich ausreichen.

von Gast Andy (Gast)


Lesenswert?

Hallo zusammen,

@Wasweissich
Nein auch beim Timerinterrupt wird nur ein Flag gesetzt.
So würde im Falle eines RX-Interrupts während der Timerroutine das 
RX-Flag gesetzt und die Timerfunktion erst abgearbeitet, bis in die 
RX-Routine gesprungen werden kann.

>Es gibt eine Methode mehrere Timer zu "simulieren"
Kannst Du bitte diese Technik kurz mal näher erläutern?

@ an alle anderen
Habt Ihr nicht noch ein paar gute Tipps bezüglich des Buszugriffs, 
Statemachines etc. ? Worauf ist noch im Allgemeinen zu achten?
Wie habt Ihr das gelöst?

MFG
Andy

von Wasweissich (Gast)


Lesenswert?

@Andy
>Nein auch beim Timerinterrupt wird nur ein Flag gesetzt.

Na, dann habe ich wohl den falschen Eindruck gehabt.

Aber warum dann:

>Solange die Timer-Routine kurz genug ist kein Problem.
>Wenn aber auf Grund von Erweiterungen diese zukünftig so groß wird,

Dann kann sie ja eigentlich nicht grösser werden.

>Kannst Du bitte diese Technik kurz mal näher erläutern?

Im Grunde ist das ganz einfach. Du musst Dir nur klar machen, das wenn 
zwei Timer gleichzeitig starten und laufen, beide eine Zeitlang, nämlich 
bis zum Ablauf des kürzeren, das selbe zählen. Selbst wenn Du den 
längeren Timer einfach nicht starten würdest und die kürze Zeit läuft 
ab, wüßtest Du das Du von dem Startwert des zweiten Timers die erste 
Zeit einfach abziehen könntest. Er hat ja einfach nur für die Dauer der 
Laufzeit des ersten Timers nicht gezählt. Für jeden weiteren Timer mit 
längerer Laufzeit gilt das selbe.

von Gast Andy (Gast)


Lesenswert?

@Andreas Kaiser
Danke für den Tip mit dem CAN-Baustein. War mir bis jetzt nicht bekannt,
daß es reine CAN-Schnittstellen-ICs ohne Protokoll gibt. Das wäre 
durchaus eine Alternative zum "vergewaltigten" RS485-Treiber. Von der SW 
her ändert sich ja nichts.

@Wasweissich
Danke für die Erklärung!

@ alle anderen
Hat keiner noch etwas zu dem Thema? Alle nur fertige CAN-Bausteine 
verwendet? ;-)

MFG
Andy

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.