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
>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).
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
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
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?
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
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.
>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.
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
@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.
@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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.