www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Anfänger problem


Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute, ich habe da ein Problem, ich bin noch ganz in den Anfängen
und wollte nun mit zwei tastern zwei led's zum leuchten bringen, und
eine dritte soll die ganze zeit leuchten aber irgendwie klappt das
nicht.
die led's liegen am Port: B0, B1 und B2
die taster an: D2 und D3
die Taster schalten auf Masse wenn man sie drückt. Ich wollte dann also
die LED Ports auf ausgänge schalten und die Taster Ports auf eingang mit
entsprechendem PullUp. das ganze übrigens in -Assembler-
So jetzt wollte ich erst mal mit einem schalter anfangen, jetzt hab ich
das problem dass das board garnicht auf den schalter reagiert und die
led sofort leuchtet? hier der code, danke schon mal

.include  "4433def.inc"
;----------------------------------------------------------------------- 
-
;Reset and Interrupt vector             ;VNr.  Beschreibung
  rjmp  main  ;1   POWER ON RESET
  reti    ;2   Int0-Interrupt
  reti    ;3   Int1-Interrupt
  reti    ;4   TC2 Compare Match
  reti    ;5   TC2 Overflow
  reti    ;6   TC1 Capture
  reti    ;7   TC1 Compare Match A
  reti    ;8   TC1 Compare Match B
  reti    ;9   TC1 Overflow
  reti    ;10  TC0 Overflow
  reti    ;11  SPI, STC Serial Transfer Complete
  reti    ;12  UART Rx Complete
  reti    ;13  UART Data Register Empty
  reti    ;14  UART Tx Complete
  reti    ;15  ADC Conversion Complete
  reti    ;16  EEPROM Ready
  reti    ;17  Analog Comparator
  reti    ;18  TWI (I²C) Serial Interface
  reti    ;19  Store Program Memory Ready
;----------------------------------------------------------------------- 
-
;Start, Power ON, Reset
main:  ;ldi r16,0x00
    ;out  DDRD,r16
    ldi  r16,0xFF
    out  DDRB, r16 ; Port B als Ausgang

    cbi DDRD,2
    cbi DDRD,3

    sbi PORTD, 2 ; Pullup
    sbi PORTD, 3



;----------------------------------------------------------------------- 
-
mainloop:  wdr
      sbi PORTB, 2


      ldi r17, PIND2

      sbrs r17,0
      sbi PORTB, 0

      ;ldi r17, PIND3
      ;sbrs r17,0
      ;sbi PORTB, 2


      rjmp  mainloop

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
main:  ;ldi r16,0x00
    ;out  DDRD,r16

Diese Befehle werden nicht ausgeführt !
und warum ?

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das is klar die wollte ich erst mal ausgrenzen um den fehler zu
suchen
ich wollte das ja hiermit dann manuell machen
cbi DDRD,2
    cbi DDRD,3

    sbi PORTD, 2 ; Pullup
    sbi PORTD, 3

Autor: dotstyler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
bin selber schon seit 2 Jahren Anfänger(ich schäm mich ja).
Ich glaube das mit  ->ldi r17, PIND2<- is nicht korrekt.
 Es sollte so aussehen  ->in r17, PinD2<-
und wenn man auf Port schreiben will dann out ->PortX,rx<-

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cbi DDRD,2
    cbi DDRD,3
  ist nicht nötig, ich weiss nicht ob das funktioniert ,cbi sbi ich
glab das geht nur mit den Portregistern.
Besser über ein Register einstellen
also :
     ldi r16,0
     out ddrd,r16

WDR ist nicht nötig weil Du den Watchdog nicht brauchst.

Ich würde es so machen:

ldi r16,0
out ddrd,r16      ;port d als eingang
ldi r16,0xff
our ddrb,r16      ;portb als ausgang

sbi portb,2      ;led2 an

vonanfang:
sbic PIND, 2  ;nächsten Befehl überspringen,wenn Bit 2 im IO-Register
PIND =0
rjmp led0aus
sbi portb,0       ;leb an

taste2:
sbic PIND, 3  nächsten Befehl überspringen,wenn Bit 3 im IO-Register
PIND =0
rjmp led1aus
sbi portb,1
rjmp vonanfang

led1aus:
cbi portb,1
rjmp vonanfang

led0aus:
cbi portb,0
rjmp taste2

Viel Erfolg !

Autor: dotstyler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;Hi ich täte das in etwa so realisieren:

;I/O festlegen
ldi r16,0b00001100
out    DDRD,r16         ; PortD Pin 2,3 Input
ldi    r16,0b0000 0111
out    DDRB,r16          ; PortB Pin 0,1,2 Output

main:
in      r17,PinD         ;PinD2,3
andi    r17,0b00001100   ;Pin2,3 mit Logisch "1" verknüpfen
sbi     r17,1            ; je nachdem wo deine dauerhaft leuchtende LED
hängt
out     PortB,r17
rjmp main
gtf ;(go to forest) mein eigener Befehl. Der funktioniert auch!!!!

->AVR- Tutorial<- "http://www.mikrocontroller.net/tutorial"
- Das ist sozusagen das große Buch wo alles drin steht!!
- Ein muß für jeden Anfänger

MFG
dotstyler_321

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo danke, ich habs ausprobiert, dann ist aber doch gar kein pullup
widerstand aktiviert? da brauch ich nur dran wackeln dann flackern die
led's auf oder ab

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achtung Semikolon vergessen !

sbic PIND, 3  ;nächsten Befehl überspringen,wenn Bit 3 im IO-Register
PIND =0

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja hatte ich im editor schon verbessert, aber wie gesagt geht irgendwie
nicht

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn ichs so mache funktioniert einer der schalter und schaltet dann die
led von 1-0-1 auf 0-1-0.
so rein von meiner logik her müsste ich doch dann das pinb durch pinb4
ersetzen wenn ich will dass anstatt dem ersten der zweite schalter das
macht, dann is aber schicht im schacht.

also ich hab jetzt mal alles an einen port gelegt.
led: b1,b2,b3
taster: b0,b4

main:

    cbi    ddrb,  0 ;eingang
    cbi    ddrb,   4
    sbi    portb,  0 ;pullup
    sbi    portb,  4 ;pullup
    sbi    ddrb,  1 ;ausgang
    sbi    ddrb,  2
    sbi    ddrb,  3
mainloop:
       ldi    r16,   0b00001101
      in    r17,  pinb
      sbrs  r17,  0
      ldi    r16,  0b00000011
      out    portb,  r16
      rjmp  mainloop

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du an PortB das Bitmuster 00001101 ausgibst, dann
passieren mehrere Dinge:

Der Port ist ja so eingestellt:

      00001110    (das ist das Ergebniss deiner diversen cbi und sbi)
      eeeeaaae    ( e steht fuer Eingang, a steht fuer Ausgang)

so, gibst du jetzt  00001101 aus

      eeeeaaae
      00001101

dann wird ueberall wo ein e über einer 0 steht der Pullup
ausgeschaltet. Ein e über einer 1, schaltet den Pullup ein,
während alles was unter einem a steht als Ausgang rausgeschaltet
wird.

d.h. Das Bitmuster sorgt dafür, dass
  * am Pin B - 4  der Pullup ausgechaltet wird
  * am Pin B - 0  der Pullup eingeschaltet bleibt
  * am Pin B - 1  eine 0 am Ausgang erscheint
  * an den Pins B - 2 und B - 3 eine 1 am Ausgang erscheint.

Da du den Pullup auf B-4 ausschaltest, wird dein Taster an
diesem Pin nachher nicht mehr richtig funktionieren.

> so rein von meiner logik her müsste ich doch dann das pinb
> durch pinb4

Wie du auf diese Logik kommst ist mir rätselhaft. Du arbeitest
mir ein bischen zu viel auf Bit-Ebene an den Ports. Mittels
'in' kannst du nur den ganzen Port einlesen, so wie er grade
eingestellt ist. Was du aber möchtest ist, du möchtest
das Bit Nummer 4 in dem was du vom Port gelesen hast
(und was jetzt im Register r17 steht) testen.

Also
     sbrs  r17, 4

  "Skip next instruction if bit #4 is set in register 17"
  "Überspringe die nächste Anweisung, wenn Bit #4 in R17 gesetzt
ist"

Aber: Das ganze ist doch eigentlich im Tutorial ganz gut
beschrieben. Hast Du da mal reingeschaut?

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich arbeite mit dem myavr leerbuch, aber ich glaub ich hab jetzt von dir
verstanden wo das problem liegt, dass ich erst in nen register laden
muss welchen pin er abfragtund dann den ganzen port abfragen und das
dann nochmal für den anderen,
ich werd morgen mich nochmal dran setzen wenn mein kopf wieder klarer
ist, jetzt hab ich soviel schon probiert, da mach ich heute eh nix mehr
richtiges.

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lehrbuch lol ;) mein ich

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> dass ich erst in nen register laden
> muss welchen pin er abfragtund dann den ganzen port
> abfragen und das dann nochmal für den anderen,

Genau anders rum:
Du liest den ganzen Port in ein Register ein und testest
dann in diesem Register welche Bits gesetzt waren oder eben
nicht gesetzt waren. Das Register enthält eine Kopie des
kompletten Portzustandes.

Im Grunde ist es ganz simpel.
Geh mal (gedanklich) einen Schritt zurück und vergiss mal
all die cbi, sbi, und wie sie alle heissen. Mach dir einen
Plan. Was soll passieren?

0)  die Ports entsprechend initialisieren

1)  die LED an B-1 einschalten

2)  den B Port einlesen

3)  Im Eingelesenen das Bit 0 testen
    Ist es gesetzt, dann die LED an B-2 einschalten
    Wenn nicht, dann die LED an B-2 ausschalten

4)  Im Eingelesenen das Bit 4 testen
    Ist es gesetzt, dann die LED an B-3 einschalten
    Wenn nicht, dann die LED an B-3 ausschalten

5)  Weiter gehts mit Schritt 2 (und damit endlos dahin)

So, dass ist dein Plan. So sollte das ganze ablaufen. Wenn
Du selbst Computer spielst und das ganze durchläufst, kannst
du dich davon überzeugen, dass es das Gewünschte macht.

Kümmern wir uns jetzt etwas mehr um die Details:

0) die Ports entsprechend initialisieren
   Hmm. Wie muessen die stehen? Wir brauchen an B die
   Pins 0 und 4 als Eingang; 1, 2, 3 als Ausgang. Die
   restlichen Pins (5, 6, 7) definieren wir der Einfachheit
   halber ebenfalls einfach als Eingang.
   d.h. wir brauchen ein Steuerwort von 0b00001110 in DDRB.
   Was ist mit den Pullups? Klar wollen wir! An den
   beiden Eingangspins B0 und B4. Das entspricht einem
   Bitmuster von 00010001 das an PORTB ausgegeben werden
   muss, damit die Pullups aktiv werden. Ungluecklicherweise
   werden dadurch die Ausgangspins alle auf 0 gezogen, aber
   das soll uns im Moment nicht weiter stören.

   Der Programmteil lautet daher

   ldi   r16, 0b00001110
   out   DDRB, r16
   ldi   r16, 0b00010001
   out   PORTB, r16

1) die LED an B-1 einschalten

   das ist leicht. Ich weiss zwar nicht, wie du deine LED
   angehaengt hast, aber ich rate mal: LED gegen Vcc verschaltet.
   d.h. eine 0 am Port bringt die LED zum leuchten.

   damit bedeutet diese Aufgabe: stelle sicher dass an B-1
   eine 0 ausgegeben wird. Oder in Code

   cbi   PORTB, 1

2) den B Port einlesen

   das ist leicht. Alles was du brauchst ist ein Register, dass
   den Zustand des kompletten B-Ports (und damit den Zustand
   der beiden Input-Pins) aufnimmt. Entscheiden wir uns für
   Register 17

   in    r17, PINB

   (Achtung: beliebter Fehler. Beim rausschreiben heisst es PORT,
    beim reinlesen heisst es PIN !)

3) Im Eingelesenen das Bit 0 testen
    Ist es gesetzt, dann die LED an B-2 einschalten
    Wenn nicht, dann die LED an B-2 ausschalten

   Wie testet man ein Bit?
   Da gibt es mehrere Möglichkeiten. Aber ich will das benutzen
   was du schon kennst: sbrs

   Also: mittels sbrs testen wir das Bit. Ist es gesetzt, dann
   wird die nächste Instruktion übersprungen, ansonsten wird
   sie ausgeführt. Wir machen das so:
   Ist das Bit nicht gesetzt dann springen wir zum Programmcode
   der die LED ausschaltet. Ist das Bit gesetzt, dann unterbleibt
   dieser Sprung (da ja die Anweisung vom sbrs uebersprungen
   wird) und es folgt direkt der Code, der die LED einschaltet.

           sbrs  r17, 0        ; Bit 0 gesetzt ?
           rjmp  LED_0_AUS     ; ja: weiter gehts beim Ausschalten
           cbi   PORTB, 2      ; nicht gesetzt, schalte LED ein
           rjmp  LED_0_ENDE    ; Das wars, LED 0 ist behandelt
LED_0_AUS: sbi   PORTB, 2
LED_0_ENDE:

    Soweit so gut.

4)  Im Eingelesenen das Bit 4 testen
    Ist es gesetzt, dann die LED an B-3 einschalten
    Wenn nicht, dann die LED an B-3 ausschalten

    Das ist analog zu obigem, nur ein paar Zahlen aendern sich.
    Daher:

           sbrs  r17, 4        ; Bit 0 gesetzt ?
           rjmp  LED_1_AUS     ; ja: weiter gehts beim Ausschalten
           cbi   PORTB, 3      ; nicht gesetzt, schalte LED ein
           rjmp  LED_1_ENDE    ; Das wars, LED 0 ist behandelt
LED_1_AUS: sbi   PORTB, 3
LED_1_ENDE:

5)  Weiter gehts mit Schritt 2 (und damit endlos dahin)

    Das ist wieder leicht. Alles was wir brauchen ist
    ein rjmp und ein entsprechendes Label als Ziel des
    rjmp.
    Das Ziel ist der Schritt 2:

LOOP:  in     r17, PINB

       ...
       ...

       rjmp LOOP

D.h. das komplette Programm sieht dann so aus:

            ldi   r16, 0b00001110
            out   DDRB, r16
            ldi   r16, 0b00010001
            out   PORTB, r16
;
            cbi   PORTB, 1      ; eine LED ist immer ein
;
LOOP:       in     r17, PINB
            sbrs  r17, 0        ; Bit 0 gesetzt ?
            rjmp  LED_0_AUS     ; ja: weiter gehts beim Ausschalten
            cbi   PORTB, 2      ; nicht gesetzt, schalte LED ein
            rjmp  LED_0_ENDE    ; Das wars, LED 0 ist behandelt
LED_0_AUS:  sbi   PORTB, 2
LED_0_ENDE:

            sbrs  r17, 4        ; Bit 0 gesetzt ?
            rjmp  LED_1_AUS     ; ja: weiter gehts beim Ausschalten
            cbi   PORTB, 3      ; nicht gesetzt, schalte LED ein
            rjmp  LED_1_ENDE    ; Das wars, LED 0 ist behandelt
LED_1_AUS:  sbi   PORTB, 3
LED_1_ENDE:
;
            rjmp LOOP

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Boaaahhh danke vielen vielen dank ihr habt mir echt geholfen, jetzt hab
ichs endlich, und weiß sogar genau warum, hab mir jetzt erst mal weiter
zum lernen erst mal ne selbsthaltung mit gebaut, echt genial. Mein
problem liegt halt noch größtenteils in der ganzen logik mit der
hardware. dachte ich könnte jeden pin einzeln direkt überprüfen ohne
den ganzen port in einem register zwischenzuspeichern, weil ich halt in
ner tabelle noch so sachen wie PORTB0...7 gefunden habe dachte ich halt,
dass ich dass dann halt direkt machen könnte, hatte mich aber auch die
ganze zeit gefragt warum er denn eigendlich bit 0 automatisch nimmt.
ich dachte mit dem sbrs befehl kontrolliere ich das register und die
stelle danach wäre für ist gleich 0 oder 1 und nicht für die stelle des
registers. das ist die umstellung auf assembler, man versucht halt
irgendwie noch in diesen if then else anweisungen zu denken, und
spagetthi code mit sprungmarken war bei anderen sprachen er verpönt und
als zu vermeiden angesehen, deshalb muss ich mich da jetzt erst mal
reinfinden ;)
danke nochmal

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> und
> spagetthi code mit sprungmarken war bei anderen sprachen er verpönt

Das war dann "Ravioli" (Objekte mit Füllung)...

Duck & wech...
...

Autor: Perter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hehehe, musste dich nicht ducken, ich hab das programmieren was wir
machen mussten total gehasst, weil man das ergebniss nur am monitor
hatte, der stundenlangen arbeit. jetzt hab ich endlich was inner hand,
was ich gemacht habe. und ich find mich immer besser mit zurecht. ich
dachte z.b. das ganze board wär im eimer weil es beim an und
ausschalten jedesmal was anderes gemacht hat.
das lag an der styropor unterlage die ich hatte damit das board nicht
auf dem metall vom pc liegt. kopfschütte nenenenee, sowas gemeines
lach.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.