Hallo,
ich möchte, in Assembler, mit möglichst wenig Instruktionen ein Bit von
PB2 in "data"(Register) übernehmen, jedoch darf data nicht komplett
überschrieben werden.
[\avrasm]
SBIC PINB,2
ORI data,0x01
Frage: Geht dies auch mit weniger Instruktionen? Eleganter?
Danke
Mathias
Weniger als ein Befehl?
Das dürfte sportlich werden.
Vielleicht könntest Du einen Tipp zum verwendeten Prozessor geben.
Meine Glaskugel ist nämlich immer noch in der Werkstatt.
Hallo,
sorry. Der µC ist Atmel Attiny 13A. Ich shifte das Datenbit, lese dann
PB2 ein, setze das Bit (0/1), vergleiche, wieviele Schiebeoperationen
ich hatte und breche bei 8 ab.
1. LSL data ; Datenbyte linkshift
2. SBIC PINB,2 ; Überspringe nächste, wenn PIN PB2 = 0
3. ORI data,0x01 ; wert setzen
4. INC counter ; Counter erhöhen
5. CPI counter,8 ; Counter auf max-wert prüfen
6. BRNE ....etc..pp
Das ganze wollte ich gerne (Durchlaufzeit) etwas "Kompakter" haben !!!
Mathias
Hi
Eleganter? Keine Ahnung, aber was ist, wenn PINB nicht "1" ist?
Vieleicht setzt du noch vor deine Anweisung ein
ANDI data,0xFE
Sonst bleibt ein einmal gesetztes Bit für immer und ewig "1"
Aber mal eine Frage, wieso willst du bei ca. 3 Takten noch "eleganter"
werden?
Gruß oldmax
Hallo,
wenn PB2 nicht 1 ist, ist er automatisch null (da shift vorher). Dann
wird gezählt.
Routine dient zum seriellen einlesen. Mit jedem Shift rückt das
datenbyte nach links, bis 8 "voll" sind. Ich wollte nur die Zählerei
kürzer machen, hab aber noch keine idee !
Mathias
Mathias schrieb:> Ich shifte das Datenbit, lese dann> PB2 ein, setze das Bit (0/1), vergleiche, wieviele Schiebeoperationen> ich hatte und breche bei 8 ab.
Start: Datenbyte mit 1 laden
Schleife: Schieben + Testen, aber ohne counter
Endetest: Wenn deine am Anfang geladene 1 im Carrybit auftaucht, sind
automatisch 8 Durchläufe fertig. :)
Hallo,
gibt es einen "Trick" um den PB2 (und nur das Bit von PB2) direkt mit
Data zu verknüpfen, ohne es vorher explizit in ein register einzulesen?
Mathias
Amateur schrieb:> ...aber 1 x LSR = 1 x DEC> 1 x LDI = 1 x LDI (1/8)> 1 x BRCS = BREQ
Hmm. Wenn, dann wird nach links geschoben und getestet ob das Carry-Flag
noch nicht gesetzt ist:
1
ldi r16, 1
2
input:
3
lsl r16
4
sbic PINB, 2
5
ori r16, 1
6
brcc input
... wäre jetzt so mein Gedanke.
Edit:
Vielleicht müsste noch ein 'clc' vor die Schleife zur Sicherheit?
@ Mathias
Soweit mir bekannt ist, hat der AVR keinen Befehl um unter Angabe einer
Bitnummer, oder auch einer Bitmaske und einer Speicheradresse (oder auch
eines Registers, dass eine Speicheradresse enthält) ein Bit an dieser
Speicheradresse zu beeinflussen.
http://www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf
Wenn das in data zu beeinflussende Bit an der selben Position sitzt, wie
in Port, dann ist diese Befehlsfolge
1
ANDI data,(0xFF-0x04)
2
SBIC PINB,2
3
ORI data,0x04
die kürzeste die mir einfällt. (Wobei "data" ein Register ist).
Nebenbei:
Ich verstehe nicht, zu welchem Zweck Du diese Schiebeoperationen machst.
Kannst Du das mal erklären, bitte?
Ein Port-Register zu verschieben ist nicht sinnvoll.
Außer dem SBI?-Befehl gibt es nicht viele Möglichkeiten.
... aber manche Programmierer haben, aus Geschwindigkeitsgründen ein
Register welches konstant mit Null belegt ist.
also weit außerhalb Deiner Schleife gibt es dann einmalig
ein LDI Rx,0 oder wie auch immer Du löschst.
...
XOR Rz,Rz ; Lösche Ergebnisregister (1 Takt)
MOV Ry,PINB ; Port lesen (1 Takt)
LSR Ry ; Abfragebit [1] nach [0] (1 Takt)
LSR Ry ; Abfragebit [0] nach [C] (1 Takt)
ADC Rz,Rx ; Rz = 0 oder 1 je nach B2 (1 Takt)
Lese gerade, dass es -nur- um PB2 geht. Dann ist es natürlich unnötig,
sich um den ganzen PINB zu kümern...
Tschuldigung mein Fehler ich habe hier gar nicht mehr weitergelsen, ich
hab mich etwas in avrasm eingelesen schnell, das ist Jahre her, dass ich
damit gespielt habe.
Wie gesagt: sorry
@Bedienungsanleitungssucher (Gast)
2-Wire in Software, bei jedem Takt an PB1 lese ich PB2 ein, shifte bis 8
bit voll->Flag setzen und verarbeiten!
Mathias
Mathias schrieb:> @Bedienungsanleitungssucher (Gast)>> 2-Wire in Software, bei jedem Takt an PB1 lese ich PB2 ein, shifte bis 8> bit voll->Flag setzen und verarbeiten!>> Mathias
Aha. Danke.
Und das ist tatsächlich ein Protokoll mit byteweisem Takt? Kenne ich
gar nicht. Nun gut. Ich kenne nicht alles, was es gibt. Hast Du da mal
einen Link auf die Protokollbeschreibung?
Mathias schrieb:> An PB1 liegt die Taktleitung. Bei jedem Takt wird ein Bit (0/1)> übernommen und weitergeschoben. Link zu Protokoll wird schwierig, da> Eigenbau!>> Mathias
Aha. Dankeschön.
Hmm. Naja. Auch bei selbst definierten Protokollen ist eine Beschreibung
zweckmäßig, denke ich. Aber gut. Deine Sache. Im übrigen ist dann I2C
das ähnlichste Protokoll.
Nur berücksichtigt der Code oben, wenn ich das richtig sehe, den Takt
nicht. Weder die von den Antwortern (die das ja nicht wissen konnten)
noch Dein eigener. Es wird einfach, so schnell wie möglich eingelesen
und geschoben.
Ein paar Randbedingungen fehlen aber immer noch.
Ist, bezogen auf den Takt, das Datenbit während der ansteigenden Flanke
gültig; während er high oder low ist; oder während der abfallenden
Flanke?
Und was vielleicht nicht ganz unwichtig ist: Wie schnell Tickst Du?
Aber vielleicht fallen Dir ja noch ein paar Randbedingungen ein, die das
alles umwerfen.
@Mathias
Hast du schon eine funktionierende Lösung und willst das ganze nur noch
schneller/ sparsamer machen? Falls nicht, ist das jetzt noch nicht der
richtige Zeitpunkt um über solche Details nachzudenken...
Mathias schrieb:> Link zu Protokoll wird schwierig, da> Eigenbau!
Mach mal eine ordentliche Beschreibung von dem Protokoll. Wenn da noch
der Takt berücksichtigt werden soll, wird das nix mit 'ner Schleife bzw.
der schnellen, 'aufgerollten' von Stefan.
An der funktionierenden Lösung bastele ich zur Zeit noch.
Der Loop läuft durch, sobald über INT0 die Taktflanke erkannt wurde.
Wenn 8 bit durch sind, setze ich ein Flag und arbeite das in der
Hauptschleife ab.
Die Routine muß so schnell sein, um den AVR aus dem Sleep aufzuwecken,
Bit speichern und wieder schlafen legen zu können !
Und ja, sobald das ganze bidirektional läuft, werde ich eine
ausführliche Beschreibung machen !
Amateur schrieb:
> Stimmt, mein Editor hat aber nicht gemeckert;)
Es reicht ja, wenn der Landolt meckert.
> Wie willst Du eigentlich den "Anfang" finden?
Und wie die Mitte des abzutastenden Bits?
> Ich weiß, ich bin ein Spielverderber...
Da sind wir schon zu zweit, das ist m.E. sehr schwer bis unmöglich.
Mathias schrieb:> Die Routine muß so schnell sein, um den AVR aus dem Sleep aufzuwecken,> Bit speichern und wieder schlafen legen zu können !
Hmm. Bit speichern? Da brauchst du ja keine Schleife. Trotzdem, wenn
ich jetzt mal für die Verarbeitung des Bits 4 Takte ansetze (nicht
nachgerechnet!), du möchtest eine Datenübertragung in Software mit
F_CPU/4?
Und wenn du jetzt sagst: "Alles ganz anders"...
Mathias schrieb:> Und ja, sobald das ganze bidirektional läuft, werde ich eine> ausführliche Beschreibung machen !
... lieber gleich!
> sobald über INT0 die Taktflanke erkannt wurde> Die Routine muß so schnell sein, um den AVR aus dem Sleep> aufzuwecken, Bit speichern und wieder schlafen legen zu können!
Bit? Ich dachte Byte.
Das ist so direkt nur bei relativ langsamer Übertragung machbar. Wenn
aber der Sender dem eigentlichen Byte einen Startimpuls im Abstand von
etwa 10-15 Takten vorausschickt, dann sollte eine Übertragung mit
f_CPU/4 machbar sein, vielleicht auch /3.
@Amateur: Takt ist 128KHz über WD-oszi
Datenbit ist während der ansteigenden Flanke des Taktsignals gültig
Sender schickt Taktsignal, um Empfänger zu wecken, Überträgt 3x8bit und
geht in Empfang/Sleep
128 K ist ganz schön ziemlich.
Ich hoffe, dass Dein µP, zwischenzeitlich, in der Wachperiode, genügend
Zeit hat sich die Daten auch anzusehen. Datenübertragung ist ja kein
Selbstzweck.
Vor allem das erste Bit (Takt) hat's in sich.
Ausgehend von "S. Landolt"'s Sequenz brauchst Du, netto, 128K * 16 Takte
zum Empfangen. Da bleibt kaum zum Speichern Zeit, geschweige etwas
anderes zu machen.
Mathias schrieb:> @Amateur: Takt ist 128KHz über WD-oszi
Ist der Watchdog-Oszi nicht ziemlich ungenau? Wenn man dann, ohne
weitere Takt-Synchronisierung, frei laufend 8 Datenbits einlesen will...
?
Zum Protokoll:
Prinzipiell steuere ich den Empfänger an, wie ich ein Schieberegister
ansteuere, die Idee ist entstanden, als ich eine 7seg ANzeige
angesteuert habe, dachte ich mir: so könnte das auch von µC zu µC
funktionieren.
Mathias
Mathias schrieb:> so könnte das auch von µC zu µC> funktionieren.
Ja. Ich würde mich aber zur Sicherheit von der Geschwindigkeit im
Verhältnis zum CPU-Takt verabschieden.
Muss der tiny unbedingt mit 128kHz getaktet werden?
Alternative zum Vorschlag von Stefan Ernst:
1
.dseg
2
3
data: .BYTE 24 ; 3x8 Byte
4
5
.cseg
6
7
ldi XL, low(data)
8
ldi XH, high(data)
9
10
in r16, PINB
11
st X+, r16
12
13
; usw.
Alle drei Bytes können ohne 'Registerwechsel' hintereinander übertragen
werden. (Wenn ich wüsste, was ein 'AVR8L based device' ist, könnte das
sogar noch schneller sein.)
Hinterher gemütlich auswerten.
----
Mathias schrieb:> Prinzipiell steuere ich den Empfänger an, wie ich ein Schieberegister> ansteuere,
Von der Einlesegeschwindigkeit würde ich mich allerdings, wie gesagt,
trennen. Bitweise Syncronisation in einer Schleife oder im Interrupt bei
deutlich höherer F_CPU wäre meine Wahl.
Hallo,
also der 128KHz Takt kommt, da der Tiny u.a. über einen 0.22F
Kondensator betrieben wird. Mehr "Power" F_CPU kann ich nicht
rausnehmen, sonst bin ich nach 30sek schon am Ende.
Mathias schrieb:> also der 128KHz Takt kommt, da der Tiny u.a. über einen 0.22F> Kondensator betrieben wird.
Wie machst Du das?
> Mehr "Power" F_CPU kann ich nicht> rausnehmen, sonst bin ich nach 30sek schon am Ende.
Von "rausnehmen" war nicht die Rede, Ralf sprach von einem deutlich
"höheren" CPU-Takt.
Supercap lädt auf - ab 1,6/1,8V springt der Tiny an.
Im Versuch läuft der Tiny mit 600KHz aktuell gerade mal ca. 15 min bei
1,8 V . Da ich ungefähr alle 10-15 min eine kurze "Ladephase" bekomme,
muß der Tiny die magere Zeit überbrücken können. Bei 1,2MHz saugt der µC
den Cap zu schnell leer
Mathias schrieb:> Im Versuch läuft der Tiny mit 600KHz aktuell gerade mal ca. 15 min bei> 1,8 V .
Hmm. Irgendjemand hat da aber jetzt einen Denkfehler drin :-/
600kHz -> 15min - Hat der in der Zeit richtig zu tun?
9Mhz -> 1min was machen, den Rest schlafen. Okay, wird nicht ganz
linear sein...
Achso:
Jetzt sind wir wieder beim Protokoll für die Datenübertragung: kann das
auch deutlich langsamer gehen?
Mathias schrieb:> Prinzipiell steuere ich den Empfänger an, wie ich ein Schieberegister> ansteuere
Also SPI.
Wenn du dir einen Gefallen tun willst: ersetz' die popeligen ATtiny13
durch pinkompatible ATtiny25. (Die DIL-Version ist bei Reichelt sogar
billiger als der '13, die SOIC gleich viel.) Die haben eine USI, die
dich bei der Implementierung eines seriellen Protokolls in Hardware
unterstützt.
Energieverbrauchsmäßig nehmen sich die beiden auch nichts.
Mathias schrieb:> also der 128KHz Takt kommt, da der Tiny u.a. über einen 0.22F> Kondensator betrieben wird.
Milchmädchenrechnung. Schnellerer Takt und längere Schlafphasen sind
energieverbrauchsmäßig nicht schlechter als ein durchtickernder
langsamer Takt. Voraussetzung: Betrieb vom RC-Oszillator, damit er
in wenigen Takten aufwacht und nicht erst einen Quarz ankurbeln muss.
Hatte das ganze mit 1,2MHz laufen, jedoch schaffe ich die Abarbeitung
der Daten dann nicht (Look-up table etc..), da der Cap dann zu schnell
unter die 1,8V (benötigt für 1,2MHz) druntergeht.
Ich komme von der Energie gerade so über 1,6 - 1,8V raus, d.h. bei 1,2
Mhz gibt es viele Zyklen, bei denen er garnicht mehr "anspringt", daher
kam die Idee mit 128KHz zu arbeiten!
Mit 128Khz könnte ich an der 1,6V Grenze länger "arbeiten"
Mathias schrieb:> Mit 128Khz könnte ich an der 1,6V Grenze länger "arbeiten"
Betrieb völlig jenseits der Grenzwerte, ojeh.
Wenn du keinen Brownout-Detektor aktivierst, garantiert dir aber auch
keiner, dass da überhaupt noch sinnvolles Zeug aus dem Flash gelesen
wird und nicht mal irgendwann beim Auslesen ein gekipptes Bit drin
ist, sodass die Firmware kompletten Humbug veranstaltet.
Mathias schrieb:> An PB1 liegt die Taktleitung. Bei jedem Takt wird ein Bit (0/1)> übernommen und weitergeschoben. Link zu Protokoll wird schwierig, da> Eigenbau!
Das hört sich ziemlich nach SPI an. Warum nimmst du nicht einfach SPI?
Mathias schrieb:> weil tiny13A keinen SPI hat, deshalb ist glaube ich wechsel zu> Tiny25> sinnvoll, wenn der Preisunterschied so marginal ist
Entweder du suchst dir einen Controller, der mit <=1,6V spezifiziert ist
oder du spendierst deiner Schaltung eine vernünftige
Spannungsversorgung. Und sag nicht: "Das geht nicht." Einen Controller
ausserhalb der Spezifikation zu betreiben, geht gar nicht.
Ob der 25er in deiner jetzigen Schaltung überhaupt läuft, steht ohnehin
in den Sternen. Die 25/45/85 gehören nämlich noch zur alten Garde. Bis
1,8V runter gehen nur die V-Typen. Bei denen dürfte das Preisargument
gegenüber dem 13A allerdings nicht mehr greifen.
mfg.
Thomas E. schrieb:> Bei denen dürfte das Preisargument gegenüber dem 13A allerdings nicht> mehr greifen.
Ja, weil es sie nicht als A-Typen gibt.
Wenn die Baugröße keine so große Geige spielt: ATtiny24A.
Mathias schrieb:> da der Tiny u.a. über einen 0.22F Kondensator betrieben wird.Mathias schrieb:> Im Versuch läuft der Tiny mit 600KHz aktuell gerade mal ca. 15 min bei 1,8V.
Mal so gerechnet:
Kondensator 0.22F = 220mAs -> 900s
Akku 300mAh -> milchmädchenmäßige ~1200h (~50d)
Warum nimmst du keinen Akku?
Mathias schrieb:> Da ich ungefähr alle 10-15 min eine kurze "Ladephase" bekomme,
Wie kurz? -> Vorwiderstand ermitteln für ordentlich 'Saft auf den Akku',
so dass der sich noch wohlfühlt.
Akku-> Nicht möglich, da Energy Harvesting Lösung angestrebt ist. 0,22F
ist eigentlich zu viel, es sollten eher <0,1 sein, aber ich muß im
Prototypenstadium den µC ja auch zum laufen kriegen....paar minuten