...@Dirk Werde mir das Beispiel auf dem Simulator anschauen und testen, ggf. auch direkt am Port messen, was da passiert. Danke für das Beispiel...
Da könnte man jetzt noch das R17 über den Stack retten und wiederherstellen lassen, um dann im laufenden Programm nicht mehr drauf achten zu müssen. Achso, die Pins müssen natürlich vorher mal irgendwo zum Ausgang gemacht worden sei, klar.
Außerdem künnte man SCK, Data und Store als Kompilervariablen/Konstanten (.equ) irgendwo im Kopf festlegen lassen, um das im Programm einfach ändern zu können.
Zum Algorithmus - der ist ja hier so (in der Schleife):
Code:
Datenbyte rollen
Wenn 'ne 1 ins carry fällt, springe nach "eins", sonst:
lösche Datenbeinchen
springe nach "Clock-Impuls"
"eins":
setze Datenbeinchen
"Clock-Impuls":
Impuls durch löschen und setzen des Clock-Beinchens
Bitzähler dekrementieren, und ggf (Z-Flag=0) zurück zum Anfang,
sonst Impuls am Store-Beinchen (Latch) und Ende
Könnte man auch so machen:
Code:
Datenbeinchen löschen
Datenbyte rollen
Wenn 'ne 0 ins carry fällt, springe nach "Clock-Impuls", sonst:
setze Datenbeinchen
"Clock-Impuls":
Impuls durch löschen und setzen des Clock-Beinchens
Bitzähler dekrementieren, und ggf (Z-Flag=0) zurück zum Anfang,
sonst Impuls am Store-Beinchen (Latch) und End
...@LotadaC Mit dem USI vom Tiny25 wird das wohl in assembler erstmal nichts geben, das wird für den Anfang zu sehr kompliziert sein..
Ach... so schlimm sollte das auch nicht sein. Eine Lösung steht ja schon im Datenblatt des Tiny25 (15.3.2 auf S. 113). Entgegen dem richtigen SPI ist das USI nicht selbst an irgendeine Taktquelle gekoppelt. Es verfügt aber über einen 4-bit-Zähler, der beim Überlauf einen Interrupt auslösen kann. Der Zähler zählt die Flanken der SCK, dabei wird außerdem das Datenregister geschoben (wobei das herausgeschobene Bit im DO landet, die andere Seite mit DI gefüllt wird.. Als Master kann man diese Flanken auf unterschiedliche Arten auslösen.
Im Beispiel erfolgt das durch setzen des USITC-Bits im USICR.
Das ganze soll in der Schleife wiederholt werden bis der 4-bit-Zähler überläuft. Dabei wird automatisch das USIOIF (USI Counter Overflow Interrupt Flag) im USISR gesetzt, welches in der Schleife geprüft wird.
Achtung, hier scheint irgendwer beim Copy&paste Mist gemacht zu haben. Das Register wird hier nach R16 geladen, und das Bit ausgewertet. R16 enthält aber eigentlich das Bitmuster, welches ins USICR geschrieben wird, um die SCK zu generieren (also jede Flanke). Würde hier überschrieben werden.
In anderen Tiny-Datenblättern wird USIOIF direkt im USISR geprüft (bzw eben die entsprechende Skip-Operation für I/O-Register (SBIS) verwendet), und gar nicht in ein Rechenregister geladen. Im Tiny25 hat USISR die Adresse 0x0E - würde also auch hier gehen. Warum man hier unbedingt über ein Rechenregister gehen wollte ist mir nicht klar - aber R16 wird in der Schleife bereits anderweitig verwendet.
C&P läßt sich übrigens auch am dann folgenden Abschnitt erahnen:
Code:
The code is size optimized using only eight instructions (plus return)...
Es sind aber 9. Wenn man das Register eben nicht nach R16 laden würde, und statt mit SBRS das Rechenregister... mit SBIS gleich das I/O-Register prüfen würde... ja, dann wärens 8.
Ein 2tes Beispiel verzichtet auf den Zähler, stattdessen werden einfach 16 Toggle-Impulse nach USITC geschrieben, bei jedem 2ten wird außerdem das Registerschieben ausgelöst (USI Clock Strobe).
Als letzte Möglichkeit könnte man den Zähler übrigens noch an den Timer0 CompareMatch heften (hm... A oder B? Timer0 hat ja 2 OCR... beim Tiny26 ging das nur mit dem TOV0)