Bascom | Hard- und Soft- SPI im gleichen Programm?

  • Hallo Leute,


    es hat sich bei mir die Notwendigkeit ergeben, in einem Programm nebst 74HCT595 Porterweiterungsbausteinen auch noch eine Hand voll WS2801 anzusteuern. Die Porterweiterungen hängen schon jeher auf Hard- SPI mit SS, MOSI, SCK. Dazugekommen sind die WS2801 auf Mosi=D.1, SCK=D.0. Das Pragramm dazu ist vereinfacht dieses: (ich habe alles was nicht den Übermittlungteil betrifft fürs Forum raus genommen)


    Das Ziel war nun eigentlich in jedem Programmdurchlauf einmal den Porterweiterungen und einmal den WS2801 neue Daten zu übermitteln. Leider funktioniert das so nicht wie gedacht. So wie der vereinfachte Code jetzt oben steht werden offensichtlich Daten welche für die WS2801 bestimmt sind an die Porterweiterungen übermittelt (Ein Farbverlauf lässt meine Ventile binär hoch zählen). Je nachdem welchen Teil ich nun ausklammere geht der andere auch problemlos. Nehme ich SoftSPI- Übermittlung raus, bekommen die Ventile an der Hard SPI ihre Daten; nehme ich die HardSPI- Übermittlung aus dem Programm bekommen die WS2801 ihre Daten. Beides hintereinander geht halt nicht. Bestimmt muss da nur wieder irgenwo ein Register gesetzt oder geleert werden.? Hat jemand einen Verdacht woran das liegen könnte?


    beste Grüße, Simon

  • Ich hatte diese Porterweiterung noch nicht auf dem Tisch.
    Wenn der aber die Daten vom 2801 auswertt, würde ich mal einfach probieren, das Ding an die Datenausgänge des letzten WS2801 zu hängen.
    Die Ausgabe dann natürlich im Programm anpassen...




    Gruß aus der Mitte
    Dirk

  • Entweder verstehe ich dich falsch, oder habe mich oben nicht ganz eindeutig ausgedrückt: die Porterweiterungsbausteine und die WS2801 sind hardwaretechnisch voneinander getrennt. Die Porterweiterungen bekommen ihre Daten von der Hard-SPI und die WS2801 von der Soft-SPI. War zumindest so geplant, denn so muss ich am Layout nur minimal verändern. Die Idee die Dinger hintereinander zu hängen ist gar nicht mal blöd, solange nacher nicht das Licht flackert, wenn die Ventile neue Daten bekommen; oder die Ventile anfangen an und aus zu faden. Ich war nur überzeugt, dass das programmtechnisch lösbar wäre.

  • OK, das Layout musst Du natürlich ändern. Sollte aber kein Problem sein, wenn nicht schon ein "paar" Platinen fertig sind.
    Zum Lichtflackern: warum sollte es? Du gibst erst die Daten der Ventile raus, dann die RGB-Werte, dann die Pause zum übernehmen.
    Wenn beide die selbe Sprache sprechen, sollte das klappen.
    Nebeneffekt wären noch 2 freie Pins...



    Gruß aus der Mitte
    Dirk

  • Hi Elite,


    dem zusammengestutzten Code traue ich jetzt mal nicht ganz.
    Und im angehängten, vollständigen Code, sind leider SPI-Befehle bereits auskommentiert. Teils durch Hochkommas, teils durch
    öffnende/schließende Klammern.


    Besser wäre es, wenn man den kompletten Code sehen könnte, und zwar in genau dem Zustand, wie er - wie von Dir beschrieben - NICHT funktioniert.


    Ein genereller Tipp:
    Lagere die einzelnen Funktionsteile in Unterroutinen aus.
    Dann stehen im Idealfall fast nur noch deren Funktionsaufrufe innerhalb der Hauptschleife.
    Das erhöht etwas die Klarheit und es passiert nicht mehr so leicht, dass sich Programmteile gegenseitig beeinflussen.
    Zudem kann man dann, durch das Auskommentieren einer einzigen Zeile, mal schnell 'ne komplette Funktion deaktivieren.


    Für noch weitergehende Kapselung hat mir ein gestandener Programmierprofi mal empfohlen, sämtliche Datenausgaben stets über den Aufruf einer einzigen Datenausgaberoutine abzuwickeln.
    Sofern die Ablaufgeschwindigkeit diese Vorgehensweise zulässt, ist das echt ein guter Tipp, auch wenn es zunächst umständlich klingt.


    Programmteile, die Daten ausgeben wollen, pusten diese also nicht mehr direkt über SPI (oder COM etc.) raus, sondern sie rufen nur besagte Routine auf, die das dann erledigt.
    Der dickste Vorteil: Wenn sich an der grundlegenden Art der Datenausgabe mal etwas ändert, brauchen nicht etliche Stellen im Quelltext abgeändert zu werden, sondern schlicht nur diese eine Routine.


    Bei Basom gibt es da noch den Haken, dass man aus Zeitgründen dort besser nicht mit Parameterübergabe an Sub / Function arbeitet (wie es eigentlich elegant wäre).
    Statt dessen nimmt man bei Bascom lieber den (unter Programmierern eigentlich verpönten, aber in Bascom ungleich schnelleren Weg) über globale Variablen.



    Das sind jetzt natürlich nur allgemeine Tipps; ich kann leider nicht direkt mit dem Finger auf eine fehlerhafte Stelle im Code zeigen.
    Aber ich kann mir gut vorstellen, dass der Fehler ganz von selbst verschwindet, wenn Du das Programm entsprechend umwurschtelst.

  • Hi Irrlicht,


    nachdem ich nun alle deine Hinweise eingearbeitet habe, sieht der Code nun so aus.
    Fehlerbeschreibung:
    Ist der Code wie im Anhang, so erfolgt keine Datenausgabe an die Ventile (Hard- SPI, Ventile schalten nicht) und die Datenausgabe an die WS2801 ist um drei Byte verschoben. (LED an zweitem WS2801 zeigt Infos, die für WS2801 bestimmt waren. LED1 scheint die Ventil-Informationen anzuzeigen)
    Klammere ich (nur) die Datenausgabe an die Ventile komplett aus, so funktioniert die Lichtausgabe richtig, die Ventile schalten nicht.
    Klammere ich (nur) die Datenausgabe an die WS2801 aus, so habe ich gar keine Funktion. Weder eine LED leuchtet noch schaltet ein Ventil.


    Alles in allem hat die Hard-SPI gar keine Funktion und je nachdem was ich ausklammere bekommt die Soft-SPI noch die drei Byte von der Hard-SPI mit auf den Weg.
    Nachdem auch das hintereinanderschalten von 74HCT595 und WS2801 nicht auf anhieb funktioniert hat, denke ich nun darüber nach einen zweiten Controller für die WS2801 zu nehmen.

  • Hi Elite,


    Dein Code wirkt schon mal viel übersichtlicher.
    Schauen wir mal, warum Hard-SPI eventuell klemmen könnte.


    http://avrhelp.mcselec.com/spiinit.htm
    http://avrhelp.mcselec.com/spiout.htm
    http://avrhelp.mcselec.com/config_spi.htm


    Im letzten Link steht weit unten eine viel aufwändigere Configuration für den Hard-SPI.
    Probiere doch mal die explizite Angabe aller Parameter.

    Zitat

    Example for Hardware SPI


    Config Spi = Hard , Interrupt =Off,Data Order = Msb , Master = Yes , Polarity =High, Phase = 1 , Clockrate = 4 , Noss = 1


    Spiinit

    (Natürlich anpassen an Deine Gegebenheiten. Ich habe den String von mcselec.com einfach direkt zitiert, ohne zu editieren.)
    Vielleicht hilft es ja.


    Und statt dem hier:



    Probiere einfach mal explizit:

    Code
    1. Spiout Valves(1) , 1
    2. Spiout Valves(2) , 1
    3. Spiout Valves(3) , 1


    Wenn Hard-SPI dann immer noch nicht korrekt gehen sollte, dann setze testweise mal direkt vor den ersten Spiout eine explizite Wertzuweisung, ohne jede Berechnung (genau wie Du es beim zweiten Aufruf gemacht hast, wo Du Nullbytes sendest).


    Beispiel:

    Code
    1. Valves(1) = &B01010101 :spiout Valves(1) ,1
    2. Valves(2) = &B11110000 :spiout Valves(2) ,1
    3. Valves(3) = &B00001111 :spiout Valves(3) ,1


    Mit so einer unmittelbaren Wertzuweisung kann man Berechnungsfehler schön ausschließen. Der Test sorgt dafür, dass ohne jeden Zweifel definierte Bytes gesendet werden.


    .
    .
    .


    Öh, noch was: Vieleicht bin ja nur gerade mit Blindheit geschlagen, aber ich vermisse die Festlegung der an SPI beteiligten Pins als Ausgänge.
    Ich würde mich nicht darauf verlassen, dass Spiinit das automatisch tut.


    Ich habe mir angewöhnt, am Programmanfang, noch vor jeder Variablendeklaration, einen Block zu setzen, der alle Pins definiert. Beispiel:

  • danke Irrlicht,


    Ich teste das dann mal am Samstag und mache dann aus diesem Beitrag wieder einen halbwegs sinnvollen.

    Beispiel:
    Valves(1) = &B01010101 :Spiout Valves(1) ,1
    Valves(2) = &B11110000 :Spiout Valves(3) ,1
    Valves(3) = &B00001111 :Spiout Valves(3) ,1

    hehe, muss ich das Smileyinterpreter- Plugin für Bascom vorher installieren. ^^



    Edit: habe heute die meisten deiner Anmerkungen umgesetzt aber das Problem nicht in den Griff bekommen. Mir ist ausgefallen, dass Hard-SPI erst wieder funktioniert hat, sobald ich den Soft-SPI- Teil komplett raus gelöscht habe. Das ausklammern des entsprechenden Aufrufs im main-loop hat nicht gereicht. Ich umgehe die Problematik nun, indem ich die Daten an einen zweiten AVR weiterprinte und dort ausgebe, bevor ich noch mehr Zeit in Fehlersuche vergrabe. Danke für deine Hilfe Irrlicht, ich werde versuchen Großteile deiner Vorschläge nächstes Mal direkt umzusetzen.

  • Jooo, habe jetzt schon zwei mal editiert und noch immer sieht es doof aus.
    Zum Einem schlägt die BBCode-Erkennung der Forensoftware zu und ersetzt Zeichenkombinaltionen duch Smileys.
    Zum Anderen hauen Abstände dauernd nicht hin, wenn mehrere Leerzeichen verwendet wurden.


    Aber Du bist ja helle im Kopp und verstehst es dennoch. :-)