www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Würde dies Funktionieren?


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi ihr,

es tut mir leid das ich euch mit dieser Kleinigkeit, für mich
aber eine Herrausforderung belästige.

Ich muss ein kleines Programm für einen ATMEL ATMege16 in Assembler 
schreiben, das auf Knopfdruck des Tasters 1 auf der ATMEL STK500 Platine
die LED 1,2,3 und 4 zum leuchten bringt.

Wenn man die Taste 2 Drückt soll LED 5,6,7 und 8 angehen.

Würde dies so funktionieren wie ich es unten geschrieben habe?

Würde mich sehr freuen wenn ihr mir weiterhelfen könntet, ich muss mir 
den Einstieg selbst erarbeiten, und dies ist mein Ergebnis...

Mit freundlichen Grüßen und voller hoffen! ;-)







;*********************************************************************** 
*******
;*********************************************************************** 
*******

;Geschrieben von    Martin
;Datum        2008-04-13
;version      1.0
;file safe as:
;for AVR:      ATMega16
;clock frequency    8MHz

;*********************************************************************** 
*******
;Program function
;
;
;
;*********************************************************************** 
*******

.device ATmega16          ;teilt dem Compiler den Prozessortyp mit
.nolist        ;Programmcode nicht in Logfile aufnehmen
.include "m16def.inc"    ;include file ist die Atmel Mega Definition

;===============
;Declarations:

.def  temp = r16

;===============
;===============
;Start Programm

  rjmp Init         ;Erste Zeile vom Programm

;==============
Init:

ldi    temp, 0b00000000  ;konfiguriert als Input(da 0-7 alles 0)
out    DDRD,temp

ldi    temp, 0b11111111  ;konfiguriert als Output(da 0-7 alles 1)
out    DDRA, temp
out    DDRB, temp
out    DDRC, temp

out    PortD, temp       ;PullUp`s für PortD
out    PortA, temp
out    PortB, temp
out    PortC, temp

;=============
;Hauptprogramm beginnt hier:

Start:
sbis  PIND,0      ;Springe, wenn Bit 0 im Port D Eins ist
rcall  Lampe14   ;Wenn Gedrückt,also oben Null,SpringeProgramm Lampe14

sbis  PIND,1      ;Springe, wenn Bit 1 im Port D Eins ist
rcall   Lampe48  ;Wenn Gedrückt, also oben Null,Springe Programm Lampe48



Lampe14:
  in      temp,PortA  ;Lese aktuellen Zustand von Port B
  andi  temp, 0b11110000   ;Lösche Bit 0 bis 3 mit UND Befehl
  out  PORTA, temp  ;Schreibe ergebnis zurück
  ret      ;Springe zurück von dort wo du kommst.

Lampe48:
  in  temp, PortA
  andi  temp, 0b00001111 ;Lösche Bit 4 bis 7 mit UND Befehl
  out  PORTA,temp   ;Schreibe ergebnis zurück
  ret      ;Springe zurück von dort wo du kommst.





rjmp START      ;springt wieder an den Start

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

Bewertung
0 lesenswert
nicht lesenswert
Nein das würde so nicht funktionieren.

* Du verwendest rcall, also einen Unterprogrammaufruf.
  Du initialisierst aber nie den Stackpointer

* Wie geht deine Programmausführung weiter, wenn die beiden sbis
  ihre jeweils nächste Anweisung nicht überspringen?
  Genau, dann gehts bei Lampe14 weiter.
  -> Die Hauptschleife ist an dieser Stelle zu Ende und der rjmp Start
     muss genau dort hin.
     Deine Hauptschleife sieht tatsächlich nur so aus
Start:
       sbis  PIND,0     ; Springe, wenn Bit 0 im Port D Eins ist
       rcall  Lampe14   ; Wenn Gedrückt,also oben Null,SpringeProgramm Lampe14

       sbis  PIND,1     ; Springe, wenn Bit 1 im Port D Eins ist
       rcall   Lampe48  ; Wenn Gedrückt, also oben Null,Springe Programm Lampe48

       rjmp Start       ; und wieder von vorne

Tip: Wenn du wissen möchtest, ob ein Programm funktioniert und
du die reale Hardware zum Testen nicht verfügbar hast, dann kannst
du immer noch dein Programm im Simulator des AVR-Studios laufen
lassen. Für Programme in diesem Schwierigkeitsgrad geht das noch
einigermassen vernünftig.

Autor: Martin W. (Firma: lernender) (martinnsu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Schnelle Antwort, hat mich wirklich sehr gefreut.
hmm muss gleich mal schauen wie der Simulator funktioniert.

Also hab das Programm nun abgeändert, so müsste es eigentlich klappen?
Würde die Aufgabe gern hinter mir haben... ;-)

Die Hardware, ist schon bestellt, muss aber noch leider zwei
Wochen drauf warten.


************************************************************************ 
******

;Geschrieben von    Martin Wimmer
;Datum          2008-04-13
;version        1.0
;file safe as:
;for AVR:        ATMega16
;clock frequency    8MHz

;*********************************************************************** 
*******
;Program function
;
;
;
;*********************************************************************** 
*******

.device ATmega16  ;teilt dem Compiler den Prozessortyp mit
.nolist      ;Programmcode nicht in Logfile aufnehmen
.include "m16def.inc"   ;include file ist die Atmel Mega Definition

;===============
;Declarations:

.def  temp = r16

;===============
;===============
;Start Programm

  rjmp Init       ;Erste Zeile vom Programm

;==============
Init:

ldi    temp, 0b00000000 ;stellt PortD als Input(da 0-7 alles 0)
out    DDRD,temp

ldi    temp, 0b11111111 ;stellt Port A,B und C als Out(da alles 1)
out    DDRA, temp
out    DDRB, temp
out    DDRC, temp

out    PortD, temp    ;PullUp`s für PortD
out    PortA, temp
out    PortB, temp
out    PortC, temp

;=============
;Hauptprogramm beginnt hier:

Start:
sbis  PIND,0     ;Springe, wenn Bit 0 im Port D Eins ist
rcall  Lampe14     ;Wenn Gedrückt,also oben Null, dann zu Programm 
Lampe14

sbis  PIND,1     ;Springe, wenn Bit 1 im Port D Eins ist
rcall   Lampe48     ;Wenn Gedrückt, also oben Null, dann zu Programm 
Lampe48

rjmp START     ;springt wieder an den Start



Lampe14:
  in  temp,PortA        ;Lese aktuellen Zustand von Port B
  andi  temp, 0b11110000  ;Lösche Bit 0 bis 3 mit UND Befehl
  out  PORTA, temp    ;Schreibe ergebnis zurück
  ret        ;Springe zurück von dort wo du kommst.

Lampe48:
  in  temp, PortA
  andi  temp, 0b00001111 ;Lösche Bit 4 bis 7 mit UND Befehl
  out  PORTA,temp   ;Schreibe ergebnis zurück
  ret      ;Springe zurück von dort wo du kommst.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie gehen die LEDs wieder aus?

Autor: Martin W. (Firma: lernender) (martinnsu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;-) Soweit hab ich gerade garnicht gedacht!
Danke Matthias!

Hab jetzt noch was hinzugefügt, wäre jetzt alles in Ordnung?

Danke noch einmal für eure Bemühungen



;*********************************************************************** 
*******
;*********************************************************************** 
*******

;Geschrieben von    Martin
;Datum        2008-04-13
;version      1.0
;file safe as:
;for AVR:      ATMega16
;clock frequency    8MHz

;*********************************************************************** 
*******
;Program function
;
;
;
;*********************************************************************** 
*******

.device ATmega16   ;teilt dem Compiler den Prozessortyp mit
.nolist       ;Programmcode nicht in Logfile aufnehmen
.include "m16def.inc"  ;include file ist die Atmel Mega Definition

;===============
;Declarations:

.def  temp = r16

;===============
;===============
;Start Programm

  rjmp Init  ;Erste Zeile vom Programm

;==============
Init:

ldi    temp, 0b00000000 ;konfi. PortD als Input(da 0-7 alles 0)
out    DDRD,temp

ldi    temp, 0b11111111 ;konfi.PortABC als Output(da 0-7 alles 1)
out    DDRA, temp
out    DDRB, temp
out    DDRC, temp

out    PortD, temp     ;PullUp`s für PortD
out    PortA, temp
out    PortB, temp
out    PortC, temp

;=============
;Hauptprogramm beginnt hier:

Start:
sbis  PIND,0     ;Springe, wenn Bit 0 im Port D Eins ist
rcall  Lampe14     ;Wenn Gedrückt,also oben Null,Springe Programm 
Lampe14

sbis  PIND,1     ;Springe, wenn Bit 1 im Port D Eins ist
rcall   Lampe48     ;Wenn Gedrückt, also oben Null,Springe Programm 
Lampe48

sbis  PIND,2     ;Springe wenn Bit 2 im PortD Eins ist
rcall  LEDAUS     ;Wenn Gedrückt,also oben Null,Springe Programm LEDAUS

rjmp START     ;springt wieder an den Start



Lampe14:
  in   temp,PortA     ;Lese aktuellen Zustand von Port B
  andi temp, 0b11110000  ;Lösche Bit 0 bis 3 mit UND Befehl
  out  PORTA, temp  ;Schreibe ergebnis zurück
  ret            ;Springe zurück von dort wo du kommst.

Lampe48:
  in  temp, PortA
  andi temp, 0b00001111  ;Lösche Bit 4 bis 7 mit UND Befehl
  out  PORTA,temp   ;Schreibe ergebnis zurück
  ret           ;Springe zurück von dort wo du kommst.

LEDAUS:
  in temp, PortA   ;Lese aktuellen Zustand von Port B
  andi temp; 0b11111111  ;Lösche Bit 0 bis 7
  out  PORTA, temp     ;Springe zurück von dort wo du kommst.
  ret

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

Bewertung
0 lesenswert
nicht lesenswert
Martin W. wrote:

> LEDAUS:
>   in temp, PortA   ;Lese aktuellen Zustand von Port B
>   andi temp; 0b11111111  ;Lösche Bit 0 bis 7
>   out  PORTA, temp     ;Springe zurück von dort wo du kommst.
>   ret

Na ja. Es ist etwas sinnfrei, zuerst den aktuelle Zustand von
PortA einzulesen, nur um dann sowieso alle Bits auf 0 zu
setzen. Das kannst du doch auch einfacher mittels
LEDAUS:
   ldi   temp, 0
   out   PORTA, temp
   ret

erreichen. Des weiteren bezweifle ich, dass das die LED
wieder ausschalten würde. So wie dein Programm geschrieben
ist, sind die LED aus, wenn die entsprechenden Bits auf 1 sind.
Du willst zum Ausschalten, die Bits also nicht auf 0 haben,
sondern auf 1
LEDAUS:
   ldi   temp, 0b11111111
   out   PORTA, temp
   ret

Autor: Martin W. (Firma: lernender) (martinnsu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also müsste ich einfach meinen:

LEDAUS:
  in temp, PortA         ;Lese aktuellen Zustand von Port B
  andi temp; 0b11111111  ;Lösche Bit 0 bis 7
  out  PORTA, temp       ;Springe zurück von dort wo du kommst.
  ret

durch den von kbuchegg ersetzen

LEDAUS:
   ldi   temp, 0b11111111
   out   PORTA, temp
   ret




 und schon würde es funktionieren?

Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin W. wrote:

>  und schon würde es funktionieren?

Nein: Du verwendest immer noch rcall bei uninitialisiertem Stackpointer 
(siehe den Beitrag von Karl Heinz). "Springe zurück von dort wo du 
kommst", wie in Deinen Kommentaren steht, findet damit nur zufällig 
statt!

Autor: Martin W. (Firma: lernender) (martinnsu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm heiß übrigens auch Wimmer!

kann mir jemand helfen, hab schon versucht es selber rauszufinden, wie 
man einen Stackpointer einbaut?
Wäre wirklich dankbar

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LEDAUS:
  in temp, PortA         ;Lese aktuellen Zustand von Port B
  andi temp; 0b11111111  ;Lösche Bit 0 bis 7
  out  PORTA, temp       ;Springe zurück von dort wo du kommst.
  ret

Bist du da in den Zeilen verrutscht, wegen den Kommentaren?

1. liest du den Ausgangszustand von PORTA, nichts von PORTB,
2. löschst du nix, diese Zeile ändert nix, ";" ist kein Trennzeichen
3. setzt du den PORTA in denselben Zustand wie vorher.

Macht irgendwie gar keinen Sinn.

Autor: Martin W. (Firma: lernender) (martinnsu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke Thilo,
aber ich glaube du hast den falschen Quellcode von mir erwischt...
hab diesen Teil durch eine Verbesserung von jemandem aus dem forum 
ersetzt
und dieser steht nun ganz unten....

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

Bewertung
0 lesenswert
nicht lesenswert
> kann mir jemand helfen, hab schon versucht es selber rauszufinden, wie
> man einen Stackpointer einbaut?
> Wäre wirklich dankbar

http://www.mikrocontroller.net/articles/AVR-Tutorial

Autor: Lötkünstler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schlage mal vor eine etwas üblichere Schreibweise durch einrücken
vorzunehmen damit der Quelltext leichter zu lesen ist.


z.B.
Label     Memorics Operant          Kommentar

Lampe14:
          in    temp,PortA        ;Lese aktuellen Zustand von Port B
          andi  temp, 0b11110000  ;Lösche Bit 0 bis 3 mit UND Befehl
          out   PORTA, temp       ;Schreibe ergebnis zurück
          ret                     ;Springe zurück von dort wo du kommst.

Lampe48:
          in    temp, PortA
          andi  temp, 0b00001111  ;Lösche Bit 4 bis 7 mit UND Befehl
          out   PORTA,temp        ;Schreibe ergebnis zurück
          ret                     ;Springe zurück von dort wo du kommst.


Was den Stack angeht brauchst du dir darüber keine Gedanken machen weil
ein Stack grundsätzlich Bestandteil eines jeden Computersystems ist.
Dieser wird genutzt um die Adresse von der der Unterprogrammaufruf 
(rcall)stattgefunden hat,zu merken,um wieder nach Rücksprung(ret)und 
Adresswiederherstellung +1(Macht der Prozzessor automatisch)nach dem
Aufruf mit den folgenden Befehlen fortzufahren.
Schon seltsam das keiner der anderen das mal beschrieben hat.
Lötkünstler

<Mit der Lizenz zum löten>

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

Bewertung
0 lesenswert
nicht lesenswert
Lötkünstler wrote:

> Was den Stack angeht brauchst du dir darüber keine Gedanken machen weil
> ein Stack grundsätzlich Bestandteil eines jeden Computersystems ist.
> Dieser wird genutzt um die Adresse von der der Unterprogrammaufruf
> (rcall)stattgefunden hat,zu merken,um wieder nach Rücksprung(ret)und
> Adresswiederherstellung +1(Macht der Prozzessor automatisch)nach dem
> Aufruf mit den folgenden Befehlen fortzufahren.

Alles richtig.
Trotzdem muss der Stackpointer noch initialisiert werden.

Autor: Lötkünstler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger (kbuchegg) (Moderator)

>>>Trotzdem muss der Stackpointer noch initialisiert werden.
meinste das so?
         ldi temp, LOW(RAMEND)    ; LOW-Byte der obersten RAM-Adresse
         out SPL, temp
         ldi temp, HIGH(RAMEND)   ; HIGH-Byte der obersten RAM-Adresse
         out SPH, temp


Lötkünstler

<Mit der Lizenz zum löten>

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

Bewertung
0 lesenswert
nicht lesenswert
Lötkünstler wrote:
> @ Karl heinz Buchegger (kbuchegg) (Moderator)
>
>>>>Trotzdem muss der Stackpointer noch initialisiert werden.
> meinste das so?

Yep

Autor: Martin W. (Firma: lernender) (martinnsu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Hilfe dir ihr mir geleistet habt!
;-)
Danke!

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.