Forum: Mikrocontroller und Digitale Elektronik Bit Verknüpfung


von Sam700 (Gast)


Lesenswert?

Hallo

So ich wollte mal anfangen mit den Atmel Mega 8 was zu machen.
Natürlich fange ich da mit den Grundlagen an!!( nicht gleich meckern)
Wollte nur 2 Bit´s miteinander undverknüpfen. In der Hilfe auf der Seite 
steht auch was dazu drin aber irgentwie geht das nicht.
Erleuchtet mich bitte der Quode:
1
; Start, Power ON, Reset
2
main:    ldi     r16, lo8(RAMEND)
3
         out     SPL, r16
4
         ldi     r16, hi8(RAMEND)
5
         out     SPH, r16
6
         cbi  DDRB,0          ;Port B.0 Input    (cbi = setze bit 0,0)
7
         sbi  PORTB,0          ;Port B.0 PullUp   (SBI = setze bit 0, 1)
8
         cbi  DDRB,1          ;Port B.1 Input    (cbi = setze bit 0,0)
9
         sbi  PORTB,1          ;Port B.1 PullUp   (SBI = setze bit 0, 1)
10
         sbi  DDRB,2          ;Port B.1 Aus ausgang einestellt
11
         ; Hier Init-Code eintragen.
12
;---------------------------------------------------------------------------
13
mainloop: wdr
14
          ldi  r16 , 0         ;lade Register R16 mit 0 damit die LED auch aus geht 
15
          in  r17 , PINB         ;Lese PINB ein 
16
          andi    r17,0b11        ; prüfe Bit #0 und #1 in r17
17
          cpi     r17,0b11        
18
         breq    A1          ;Wenn bedingung gegeben dann Springen auf A1 
19
         
20
          out   PORTB , r16  
21
          rjmp mainloop
22
 A1:      ldi  r16, 0b0000011      ; Wenn der taster nicht geshaltet ist überspringe nächsten schritt
23
          out   PORTB , r16        ;Ausgabe PortB
24
          rjmp mainloop
25
;---------------------------------------------------------------------------

Ich danke schon mal....

Sam

von Floh (Gast)


Lesenswert?

Sam700 schrieb:
> cbi  DDRB,0          ;Port B.0 Input    (cbi = setze bit 0,0)
>          sbi  PORTB,0          ;Port B.0 PullUp   (SBI = setze bit 0, 1)
>          cbi  DDRB,1          ;Port B.1 Input    (cbi = setze bit 0,0)
>          sbi  PORTB,1          ;Port B.1 PullUp   (SBI = setze bit 0, 1)

Pins auf Eingang und Pullup.
Daher gehe ich davon aus, dass deine Taster gegen Masse schalten.
Also müsstest du hier invertiert abfragen.
:-)

von Karl H. (kbuchegg)


Lesenswert?

Sam700 schrieb:

>          ldi  r16 , 0         ;lade Register R16 mit 0 damit die
> ....
>           out   PORTB , r16

Tja.
Und damit sind dann wohl deine Pullup-Widerstände zur Geschichte 
geworden :-)

Beim ausgeben auf einen Port IMMER darauf auchten, dass mittels OUT alle 
8 Bit geschrieben werden!
Wenn du Bits hast, die so bleiben müssen (wie zb die Bits zuständig für 
Pullup Widerstände) dann musst du das berücksichtigen!

von Sam700 (Gast)


Lesenswert?

Hallo

Hm.. Was müsste ich dan ändern?

Einen Fehler habe ich noch gefunden und zwar wen man versucht den 
eingagnstaster zu beschreiben und nicht die LED na ja ...
Falsch
A1:      ldi  r16, 0b0000011
Richtig
A1:      ldi  r16, 0b000100


Jetzt geht auch eine LED an aber das ist jetzt eine Oder verknüpfung. 
Das kan doch nach
1
    andi    r16,0b1010  ; prüfe Bit #1 und #3 in r16
2
    cpi     r16,0b1010
3
    breq    alle_bits_sind_gesetzt
garnicht sein. Wen jetzt wieder nichts gehen würde dan ok aber eine Oder 
obwohl ich das so gemacht habe?

Danke

Sam

p.s. Aller Anfang ist schwer :)

von Floh (Gast)


Lesenswert?

Sam700 schrieb:
> Wen jetzt wieder nichts gehen würde dan ok aber eine Oder
> obwohl ich das so gemacht habe?
Stichwort De-Morgan.

Dein Sprung wird jetzt ausgeführt, sobald EINER der beiden Taster nicht 
eins ist, also wenn einer der beiden gesrückt wurde (-> oder).

Denke daran, dass die Eingabe invertiert ist, wenn die Taster nach Masse 
schalten.
Gedrückt -> Pin ist 0
nicht gedrückt -> Pin ist 1

Also musst du eine Wahrheitstabelle ausfüllen, die passt:

keiner gedrückt    ...11
einer gedrückt     ...10
                   ...01
beide gedrückt     ...00

auf was genau willst du reagieren? Das entsprechede musst du dann 
abfragen.
:-)

von Sam700 (Gast)


Lesenswert?

Hallo nochmal

So ich hbe meinen Fehler gefunden.
Wie es scheint habe ich einen Fehler ind en Sprungmarken gemacht.
So geht das :
1
mainloop: wdr
2
          ldi  r16 , 0x0         ;lade Register R16 mit 0 damit die LED auch aus geht 
3
          in  r17 , PINB         ;Lese PINB ein 
4
          andi    r17, 0x3              ; prüfe Bit #0 und #1 in r17
5
         breq    A1          ;Wenn bedingung gegeben dann Springen auf A1 
6
          ldi  r16, 0b000100      ; Wenn der taster nicht geshaltet ist überspringe nächsten schritt
7
  A1:     out   PORTB , r16        ;Ausgabe PortB
8
          rjmp mainloop

Na ja manchmal steht man einfach auf der Leitung.
BEim nächstenmal einfach einen schritt zurück und dan nochmal schauen :)

THX erstmal (Ich komme bestimmt wieder :) )

Sam

von oldmax (Gast)


Lesenswert?

Hi
Auch wenn du "nur" Anfänger bist, werde ich dir mal ein kleines 
Geheimnis verraten: "Module"...
Grad wenn u in Assembler deine Gehversuche startest, dann solltest du 
folgendes beherzigen.
Verwende kleine Unterprogramme. Z. B. Initialisiere zuerst den Stack, da 
kmmst du oft nicht drum herum. Danach setze die IO, den Timer, den UART. 
Anschließend setze deine Variablen und Register auf Defaultwerte. Für 
jede Aufgabe eine eigene Routine. Mußt du später mal etwas ändern, hast 
du nur einen kleinen Programmblock zu bearbeiten.
In deiner Hauptschleife beginne mit einem Unterprogramm, um die Eingänge 
zu lesen. Diese Werte legst du in einer Variablen ab und veränderst 
diese in der gesamten Programmschleife nicht mehr. Auch hier der 
Vorteil: ändern sich deine IO, dann brauchst du nur diese Routine ändern 
und du kannst die Eingangspins schön in einer Variablen auf ein oder 
zwei Byte  legen, egal, wie gemischt du sie einsammeln mußt.
Wenn du deine Eingänge nach GND schaltest, macht es Sinn, die Bits vor 
der Weiterverarbeitung zu drehen. Das ist einfach mit einer EOR 
(Exclusiv-Oder) und einer konstanten "1" durchzuführen.
Bsp.
 In   Reg_A, PortB     ; ich lese mal ein ganzes Byte ein
 LDI  Reg_B,0b11111111 ; alle Bits auf "1", EOR geht nur unter Registern
 EOR  Reg_A, Reg_B     ; EOR geht nur unter Registern
 STS  New_In, Reg_A    ; nun ist ein betätigter Schalter auch "1"
                       ; und in einer Variablen abgelegt.

Natürlich kann man auch erst verschiedene Bits "einsammeln" und einer 
Variablen zuorden. Anschließend wird der Inhalt der Variable wie im 
Beispiel "gedreht".
Mit diesen Bits machst du nun  in deiner Programmschleife die 
Bearbeitung. Dabei ist auch hier auf kleine Programmblöcke zu achten, 
die mit RCALL aufgerufen werden. Gib unterwegs nicht mal hier und mal da 
etwas aus, sondern sammle auch hier erst Bits in einer Variablen, die 
dun dann am Ende der Programmschleife in einem eigenen Block den 
Ausgangsbits zuweist. Auch dies ist später bei Änderungen übersichtlich.
Grad wenn man Anfänger ist, sind meiner Meinung nach grad diese Hinweise 
auf kleine Programmblöcke und ausgiebige Nutzung von Unterprogrammen 
wichtig.
Gruß oldmax

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
Noch kein Account? Hier anmelden.