1 bit Wert PB2 direkt übernehmen (Assembler)

Gast #4271518
Lesenswert?

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
Gast #4271544
Lesenswert?

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
Gast #4271546
Lesenswert?

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
Gast #4271553
Lesenswert?

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
#4271564
Lesenswert?

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. :)
#4271605
Lesenswert?

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?
Gast #4271611
Lesenswert?

@ 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?
Gast #4271628
Lesenswert?

Wenn PINB eher als dünn besetzt zu erwatzen ist, könntest du folgenden 
Ansatz in Betracht ziehen.
1
.DEF  tmp  = r16
2
.DEF  tmp2= r17
3
.DEF    data= r1
4

5

6
.CSEG
7
.ORG 0
8
startup:
9
  ldi    tmp,0xff
10
  out    portb,tmp
11
  
12
  in    tmp,pinb
13
loop:
14
  breq  end
15
  mov    tmp2,tmp
16
  neg    tmp2    ;mask rightmost 1
17
  and    tmp2,tmp
18
  eor    tmp,tmp2  ;clear bin in pinb
19
  rjmp  loop
20
end:
21
  rjmp end

Mit der Bitmaske kann, logo, auch was mit dem data-register gemacht 
werden
#4271629
Lesenswert?

Mathias schrieb:
> 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

= 55 Takte

> Das ganze wollte ich gerne (Durchlaufzeit) etwas "Kompakter" haben !!!

1
IN  tmp, PINB
2
BST tmp, 2
3
BLD data, 7
4
IN  tmp, PINB
5
BST tmp, 2
6
BLD data, 6
7
IN  tmp, PINB
8
BST tmp, 2
9
BLD data, 5
10
IN  tmp, PINB
11
BST tmp, 2
12
BLD data, 4
13
IN  tmp, PINB
14
BST tmp, 2
15
BLD data, 3
16
IN  tmp, PINB
17
BST tmp, 2
18
BLD data, 2
19
IN  tmp, PINB
20
BST tmp, 2
21
BLD data, 1
22
IN  tmp, PINB
23
BST tmp, 2
24
BLD data, 0
= 24 Takte
Gast #4271636
Lesenswert?

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)
Gast #4271638
Lesenswert?

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
Gast #4271700
Lesenswert?

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?
Gast #4271720
Lesenswert?

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.
Gast #4271735
Lesenswert?

Amateur schrieb:
1
XOR Rz,Rz        ; Lösche Ergebnisregister  (1 Takt)
2
MOV Ry,PINB      ; Port lesen               (1 Takt)
3
LSR Ry           ; Abfragebit [1] nach [0]  (1 Takt)
4
LSR Ry           ; Abfragebit [0] nach [C]  (1 Takt)
5
ADC Rz,Rx        ; Rz = 0 oder 1 je nach B2 (1 Takt)

Abgesehen davon, dass es in statt mov heißen muss, fehlt da doch ein 
lsr Ry.
Gast #4271739
Lesenswert?

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.
#4271756
Lesenswert?

@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.
Gast #4271775
Lesenswert?

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 !
Gast #4271808
Lesenswert?

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.
#4271886
Lesenswert?

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!
Gast #4271909
Lesenswert?

Ich glaube zwar nicht, dass es weiterhilft, aber hier eine Lösung mit 
1+16 Takten:
1
.def   tmp = r16
2
 ldi   tmp,0
3
 sbic  PINB,2
4
  ori  tmp,(1<<7)
5
 sbic  PINB,2
6
  ori  tmp,(1<<6)
7
.
8
.
9
 sbic  PINB,2
10
  ori  tmp,(1<<0)
Gast #4272059
Lesenswert?

> 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.
Gast #4272229
Lesenswert?

@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
Gast #4272266
Lesenswert?

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.
Gast #4272614
Lesenswert?

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
#4272624
Lesenswert?

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.
Gast #4272829
Lesenswert?

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
#4272837
Lesenswert?

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?
Moderator Persönliche Seite #4272871
Lesenswert?

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.
Gast #4272880
Lesenswert?

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"
Moderator Persönliche Seite #4272888
Lesenswert?

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.
#4273015
Lesenswert?

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.
#4274127
Lesenswert?

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.
Gast #4274366
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren